provided code

This commit is contained in:
LabTS
2024-10-01 23:37:39 +01:00
commit 8724a2641e
697 changed files with 74252 additions and 0 deletions

26
.gitignore vendored Normal file
View File

@@ -0,0 +1,26 @@
#ignore temp files
*~
#ignore pdf files (just keep source files)
*.pdf
#ignore junk files from latex output
*.out
*.log
*.aux
*.dvi
*.ps
*minted*
#ignore junk files from compiling C code
*.o
#ignore other junk files
*.backup
*.kate-swp
*.swp
*.snm
*.vrb
*.nav
*.toc

43
AUTHORS Normal file
View File

@@ -0,0 +1,43 @@
src -*- text -*-
---
* Pintos core originally written by Ben Pfaff <blp@cs.stanford.edu>.
* Additional features contributed by Anthony Romano <chz@vt.edu>.
* The original structure and form of this operating system is inspired
by the Nachos system from the University of California, Berkeley. A
few of the source files are more-or-less literal translations of the
Nachos C++ code into C. These files bear the original UCB license
notice.
projects
--------
* The projects are primarily the creation of Ben Pfaff
<blp@cs.stanford.edu>.
* Godmar Back <godmar@gmail.com> made significant contributions to
project design.
* Although little remains unchanged, the projects were originally
derived from those designed for Nachos by current and former CS140
teaching assistants at Stanford University, including at least the
following people:
- Yu Ping <yph@cs.stanford.edu>
- Greg Hutchins
- Kelly Shaw <kashaw (at) cs.stanford.edu>,
- Paul Twohey <twohey AT cs DOT stanford DOT edu>
- Sameer Qureshi <squreshi@cs.stanford.edu>
- John Rector
If you're not on this list but should be, please let me know.
* Example code for condition variables is from classroom slides
originally by Dawson Engler and updated by Mendel Roseblum.

56
LICENSE Normal file
View File

@@ -0,0 +1,56 @@
Pintos, including its documentation, is subject to the following
license:
Copyright (C) 2004, 2005, 2006 Board of Trustees, Leland Stanford
Jr. University. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
A few individual files in Pintos were originally derived from other
projects, but they have been extensively modified for use in Pintos.
The original code falls under the original license, and modifications
for Pintos are additionally covered by the Pintos license above.
In particular, code derived from Nachos is subject to the following
license:
/* Copyright (c) 1992-1996 The Regents of the University of California.
All rights reserved.
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose, without fee, and
without written agreement is hereby granted, provided that the
above copyright notice and the following two paragraphs appear
in all copies of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO
ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE
AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
*/

13
Makefile Normal file
View File

@@ -0,0 +1,13 @@
CLEAN_SUBDIRS = src doc tests
all::
@echo "This makefile has only 'clean' and 'check' targets."
clean::
for d in $(CLEAN_SUBDIRS); do $(MAKE) -C $$d $@; done
distclean:: clean
find . -name '*~' -exec rm '{}' \;
check::
make -C tests $@

26
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1,26 @@
*.aux
*.cp
*.dvi
*.fn
*.info*
*.ky
*.log
*.pg
*.toc
*.tp
*.vr
/pintos-ic.fns
/pintos-ic.tps
/pintos-ic.vrs
mlfqs1.pdf
mlfqs1.png
mlfqs2.pdf
mlfqs2.png
pintos-ic.html
pintos-ic.pdf
pintos-ic.ps
pintos.text
pintos-ic_*.html
projects.html
sample.tmpl.texi
task0_sheet.pdf

403
doc/44bsd.texi Normal file
View File

@@ -0,0 +1,403 @@
@node 4.4BSD Scheduler
@appendix 4.4@acronym{BSD} Scheduler
@iftex
@macro tm{TEX}
@math{\TEX\}
@end macro
@macro nm{TXT}
@end macro
@macro am{TEX, TXT}
@math{\TEX\}
@end macro
@end iftex
@ifnottex
@macro tm{TEX}
@end macro
@macro nm{TXT}
@w{\TXT\}
@end macro
@macro am{TEX, TXT}
@w{\TXT\}
@end macro
@end ifnottex
@ifhtml
@macro math{TXT}
\TXT\
@end macro
@end ifhtml
@macro m{MATH}
@am{\MATH\, \MATH\}
@end macro
The goal of a general-purpose scheduler is to balance threads' different
scheduling needs. Threads that perform a lot of I/O require a fast
response time to keep input and output devices busy, but need little CPU
time. On the other hand, CPU-bound threads need to receive a lot of
CPU time to finish their work, but have no requirement for fast response
time. Other threads lie somewhere in between, with periods of I/O
punctuated by periods of computation, and thus have requirements that
vary over time. A well-designed scheduler can often accommodate threads
with all these requirements simultaneously.
For task 1, you must implement the scheduler described in this
appendix. Our scheduler resembles the one described in @bibref{McKusick},
which is one example of a @dfn{multilevel feedback queue} scheduler.
This type of scheduler maintains several queues of ready-to-run threads,
where each queue holds threads with a different priority. At any given
time, the scheduler chooses a thread from the highest-priority non-empty
queue. If the highest-priority queue contains multiple threads, then
they run in ``round robin'' order.
Multiple facets of the scheduler require data to be updated after a
certain number of timer ticks. In every case, these updates should
occur before any ordinary kernel thread has a chance to run, so that
there is no chance that a kernel thread could see a newly increased
@func{timer_ticks} value but old scheduler data values.
The 4.4@acronym{BSD} scheduler does not include priority donation.
@menu
* Thread Niceness::
* Calculating Priority::
* Calculating recent_cpu::
* Calculating load_avg::
* 4.4BSD Scheduler Summary::
* Fixed-Point Real Arithmetic::
@end menu
@node Thread Niceness
@section Niceness
Thread priority is dynamically determined by the scheduler using a
formula given below. However, each thread also has an integer
@dfn{nice} value that determines how ``nice'' the thread should be to
other threads. A @var{nice} of zero does not affect thread priority. A
positive @var{nice}, to the maximum of 20, decreases the priority of a
thread and causes it to give up some CPU time it would otherwise receive.
On the other hand, a negative @var{nice}, to the minimum of -20, tends
to take away CPU time from other threads.
The initial thread starts with a @var{nice} value of zero. Other
threads start with a @var{nice} value inherited from their parent
thread. You must implement the functions described below, which are for
use by test programs. We have provided skeleton definitions for them in
@file{threads/thread.c}.
@deftypefun int thread_get_nice (void)
Returns the current thread's @var{nice} value.
@end deftypefun
@deftypefun void thread_set_nice (int @var{new_nice})
Sets the current thread's @var{nice} value to @var{new_nice} and
recalculates the thread's priority based on the new value
(@pxref{Calculating Priority}). If the running thread no longer has the
highest priority, yields.
@end deftypefun
@node Calculating Priority
@section Calculating Priority
Our scheduler has 64 priorities and thus 64 ready queues, numbered 0
(@code{PRI_MIN}) through 63 (@code{PRI_MAX}). Lower numbers correspond
to lower priorities, so that priority 0 is the lowest priority
and priority 63 is the highest. Thread priority is calculated initially
at thread initialization. It is also recalculated for each thread (if necessary)
on every fourth clock tick.
In either situation, it is determined by the formula:
@center @t{@var{priority} = @code{PRI_MAX} - (@var{recent_cpu} / 4) - (@var{nice} * 2)},
@noindent where @var{recent_cpu} is an estimate of the CPU time the
thread has used recently (see below) and @var{nice} is the thread's
@var{nice} value. The result should be rounded down to the nearest
integer (truncated).
The coefficients @math{1/4} and 2 on @var{recent_cpu}
and @var{nice}, respectively, have been found to work well in practice
but lack deeper meaning. The calculated @var{priority} is always
adjusted to lie in the valid range @code{PRI_MIN} to @code{PRI_MAX}.
This formula gives a thread that has received CPU time recently lower priority
for being reassigned the CPU the next time the scheduler runs.
This is key to preventing starvation:
a thread that has not received any CPU time recently will have a
@var{recent_cpu} of 0, which barring a high @var{nice} value should
ensure that it receives CPU time soon.
This technique is sometimes referred to as "aging" in the literature.
@node Calculating recent_cpu
@section Calculating @var{recent_cpu}
We wish @var{recent_cpu} to measure how much CPU time each process has
received ``recently.'' Furthermore, as a refinement, more recent CPU
time should be weighted more heavily than less recent CPU time. One
approach would use an array of @var{n} elements to
track the CPU time received in each of the last @var{n} seconds.
However, this approach requires O(@var{n}) space per thread and
O(@var{n}) time per calculation of a new weighted average.
Instead, we use an @dfn{exponentially weighted moving average}, which
takes this general form:
@center @tm{x(0) = f(0),}@nm{x(0) = f(0),}
@center @tm{x(t) = ax(t-1) + (1-a)f(t),}@nm{x(t) = a*x(t-1) + (1-a)*f(t),}
@center @tm{a = k/(k+1),}@nm{a = k/(k+1),}
@noindent where @math{x(t)} is the moving average at integer time @am{t
\ge 0, t >= 0}, @math{f(t)} is the function being averaged, and @math{k
> 0} controls the rate of decay. We can iterate the formula over a few
steps as follows:
@center @math{x(0) = f(0)},
@center @am{x(1) = af(0) + (1-a)f(1), x(1) = a*f(0) + (1-a)*f(1)},
@center @am{\vdots, ...}
@center @am{x(4) = a^4f(0) + a^3(1-a)f(1) + a^2(1-a)f(2) + a(1-a)f(3) + (1-a)f(4), x(4) = a**4*f(0) + a**3*(1-a)*f(1) + a**2*(1-a)*f(2) + a*(1-a)*f(3) + (1-a)*f(4)}.
@noindent The value of @math{f(t)} has a weight of @math{(1-a)} at time @math{t},
a weight of @math{a(1-a)} at time @math{t+1}, @am{a^2(1-a), a**2(1-a)} at time
@math{t+2}, and so on. We can also relate @math{x(t)} to @math{k}:
@math{f(t)} has a weight of approximately @math{1/e} at time @math{t+k},
approximately @am{1/e^2, 1/e**2} at time @am{t+2k, t+2*k}, and so on.
From the opposite direction, @math{f(t)} decays to weight @math{w} at around
time @am{t + \log_aw, t + ln(w)/ln(a)}.
The initial value of @var{recent_cpu} is 0 in the first thread
created, or the parent's value in other new threads. Each time a timer
interrupt occurs, @var{recent_cpu} is incremented by 1 for the running
thread only, unless the idle thread is running. In addition, once per
second the value of @var{recent_cpu}
is recalculated for every thread (whether running, ready, or blocked),
using this formula:
@center @t{@var{recent_cpu} = (2*@var{load_avg})/(2*@var{load_avg} + 1) * @var{recent_cpu} + @var{nice}},
@noindent where @var{load_avg} is a moving average of the number of
threads ready to run (see below). If @var{load_avg} is 1, indicating
that a single thread, on average, is competing for the CPU, then the
current value of @var{recent_cpu} decays to a weight of .1 in
@am{\log_{2/3}.1 \approx 6, ln(.1)/ln(2/3) = approx. 6} seconds; if
@var{load_avg} is 2, then decay to a weight of .1 takes @am{\log_{3/4}.1
\approx 8, ln(.1)/ln(3/4) = approx. 8} seconds. The effect is that
@var{recent_cpu} estimates the amount of CPU time the thread has
received ``recently,'' with the rate of decay inversely proportional to
the number of threads competing for the CPU.
Assumptions made by some of the tests require that these recalculations of
@var{recent_cpu} be made exactly when the system tick counter reaches a
multiple of a second, that is, when @code{timer_ticks () % TIMER_FREQ ==
0}, and not at any other time.
The value of @var{recent_cpu} can be negative for a thread with a
negative @var{nice} value. Do not clamp negative @var{recent_cpu} to 0.
You may need to think about the order of calculations in this formula.
We recommend computing the coefficient of @var{recent_cpu} first, then
multiplying. In the past, some students have reported that multiplying
@var{load_avg} by @var{recent_cpu} directly can cause overflow.
You must implement @func{thread_get_recent_cpu}, for which there is a
skeleton in @file{threads/thread.c}.
@deftypefun int thread_get_recent_cpu (void)
Returns 100 times the current thread's @var{recent_cpu} value, rounded
to the nearest integer.
@end deftypefun
@node Calculating load_avg
@section Calculating @var{load_avg}
Finally, @var{load_avg}, often known as the system load average,
estimates the average number of threads ready to run over the past
minute. Like @var{recent_cpu}, it is an exponentially weighted moving
average. Unlike @var{priority} and @var{recent_cpu}, @var{load_avg} is
system-wide, not thread-specific. At system boot, it is initialized to
0. Once per second thereafter, it is updated according to the following
formula:
@center @t{@var{load_avg} = (59/60)*@var{load_avg} + (1/60)*@var{ready_threads}},
@noindent where @var{ready_threads} is the number of threads that are
either running or ready to run at time of update (not including the idle
thread).
Because of assumptions made by some of the tests, @var{load_avg} must be
updated exactly when the system tick counter reaches a multiple of a
second, that is, when @code{timer_ticks () % TIMER_FREQ == 0}, and not
at any other time.
You must implement @func{thread_get_load_avg}, for which there is a
skeleton in @file{threads/thread.c}.
@deftypefun int thread_get_load_avg (void)
Returns 100 times the current system load average, rounded to the
nearest integer.
@end deftypefun
@node 4.4BSD Scheduler Summary
@section Summary
The following formulas summarize the calculations required to implement the
scheduler. They are not a complete description of the scheduler's requirements.
Every thread has a @var{nice} value between -20 and 20 directly under
its control. Each thread also has a priority, between 0
(@code{PRI_MIN}) through 63 (@code{PRI_MAX}), which is recalculated (as necessary)
using the following formula:
@center @t{@var{priority} = @code{PRI_MAX} - (@var{recent_cpu} / 4) - (@var{nice} * 2)}.
@var{recent_cpu} measures the amount of CPU time a thread has received
``recently.'' On each timer tick, the running thread's @var{recent_cpu}
is incremented by 1. Once per second, every thread's @var{recent_cpu}
is updated this way:
@center @t{@var{recent_cpu} = (2*@var{load_avg})/(2*@var{load_avg} + 1) * @var{recent_cpu} + @var{nice}}.
@var{load_avg} estimates the average number of threads ready to run over
the past minute. It is initialized to 0 at boot and recalculated once
per second as follows:
@center @t{@var{load_avg} = (59/60)*@var{load_avg} + (1/60)*@var{ready_threads}}.
@noindent where @var{ready_threads} is the number of threads that are
either running or ready to run at time of update (not including the idle
thread).
Note that it is important that each of these calculations is based on up-to-date data values.
That is, the calculation of each thread's @var{priority} should be based on the most recent @var{recent_cpu} value
and, similarly, the calculation of @var{recent_cpu} should itself be based on the most recent @var{load_avg} value.
You should take these dependencies into account when implementing these calculations.
You should also think about the efficiency of your calculations.
The more time your scheduler spends working on these calculations,
the less time your actual processes will have to run.
It is important, therefore, to only perform calculations when absolutely necessary.
@node Fixed-Point Real Arithmetic
@section Fixed-Point Real Arithmetic
In the formulas above, @var{priority}, @var{nice}, and
@var{ready_threads} are integers, but @var{recent_cpu} and @var{load_avg}
are real numbers. Unfortunately, PintOS does not support floating-point
arithmetic in the kernel, because it would
complicate and slow the kernel. Real kernels often have the same
limitation, for the same reason. This means that calculations on real
quantities must be simulated using integers. This is not
difficult, but many students do not know how to do it. This
section explains the basics.
The fundamental idea is to treat the rightmost bits of an integer as
representing a fraction. For example, we can designate the lowest 14
bits of a signed 32-bit integer as fractional bits, so that an integer
@m{x} represents the real number
@iftex
@m{x/2^{14}}.
@end iftex
@ifnottex
@m{x/(2**14)}, where ** represents exponentiation.
@end ifnottex
This is called a 17.14 fixed-point number representation, because there
are 17 bits before the decimal point, 14 bits after it, and one sign
bit.@footnote{Because we are working in binary, the ``decimal'' point
might more correctly be called the ``binary'' point, but the meaning
should be clear.} A number in 17.14 format represents, at maximum, a
value of @am{(2^{31} - 1) / 2^{14} \approx, (2**31 - 1)/(2**14) =
approx.} 131,071.999.
Suppose that we are using a @m{p.q} fixed-point format, and let @am{f =
2^q, f = 2**q}. By the definition above, we can convert an integer or
real number into @m{p.q} format by multiplying with @m{f}. For example,
in 17.14 format the fraction 59/60 used in the calculation of
@var{load_avg}, above, is @am{(59/60)2^{14}, 59/60*(2**14)} = 16,110.
To convert a fixed-point value back to an
integer, divide by @m{f}. (The normal @samp{/} operator in C rounds
toward zero, that is, it rounds positive numbers down and negative
numbers up. To round to nearest, add @m{f / 2} to a positive number, or
subtract it from a negative number, before dividing.)
Many operations on fixed-point numbers are straightforward. Let
@code{x} and @code{y} be fixed-point numbers, and let @code{n} be an
integer. Then the sum of @code{x} and @code{y} is @code{x + y} and
their difference is @code{x - y}. The sum of @code{x} and @code{n} is
@code{x + n * f}; difference, @code{x - n * f}; product, @code{x * n};
quotient, @code{x / n}.
Multiplying two fixed-point values has two complications. First, the
decimal point of the result is @m{q} bits too far to the left. Consider
that @am{(59/60)(59/60), (59/60)*(59/60)} should be slightly less than
1, but @tm{16,110\times 16,110}@nm{16,110*16,110} = 259,532,100 is much
greater than @am{2^{14},2**14} = 16,384. Shifting @m{q} bits right, we
get @tm{259,532,100/2^{14}}@nm{259,532,100/(2**14)} = 15,840, or about 0.97,
the correct answer. Second, the multiplication can overflow even though
the answer is representable. For example, 64 in 17.14 format is
@am{64 \times 2^{14}, 64*(2**14)} = 1,048,576 and its square @am{64^2,
64**2} = 4,096 is well within the 17.14 range, but @tm{1,048,576^2 =
2^{40}}@nm{1,048,576**2 = 2**40}, greater than the maximum signed 32-bit
integer value @am{2^{31} - 1, 2**31 - 1}. An easy solution is to do the
multiplication as a 64-bit operation. The product of @code{x} and
@code{y} is then @code{((int64_t) x) * y / f}.
Dividing two fixed-point values has opposite issues. The
decimal point will be too far to the right, which we fix by shifting the
dividend @m{q} bits to the left before the division. The left shift
discards the top @m{q} bits of the dividend, which we can again fix by
doing the division in 64 bits. Thus, the quotient when @code{x} is
divided by @code{y} is @code{((int64_t) x) * f / y}.
This section has consistently used multiplication or division by @m{f},
instead of @m{q}-bit shifts, for two reasons. First, multiplication and
division do not have the surprising operator precedence of the C shift
operators. Second, multiplication and division are well-defined on
negative operands, but the C shift operators are not. Take care with
these issues in your implementation.
The following table summarizes how fixed-point arithmetic operations can
be implemented in C. In the table, @code{x} and @code{y} are
fixed-point numbers, @code{n} is an integer, fixed-point numbers are in
signed @m{p.q} format where @m{p + q = 31}, and @code{f} is @code{1 <<
q}:
@html
<CENTER>
@end html
@multitable @columnfractions .5 .5
@item Convert @code{n} to fixed point:
@tab @code{n * f}
@item Convert @code{x} to integer (rounding toward zero):
@tab @code{x / f}
@item Convert @code{x} to integer (rounding to nearest):
@tab @code{(x + f / 2) / f} if @code{x >= 0}, @*
@code{(x - f / 2) / f} if @code{x <= 0}.
@item Add @code{x} and @code{y}:
@tab @code{x + y}
@item Subtract @code{y} from @code{x}:
@tab @code{x - y}
@item Add @code{x} and @code{n}:
@tab @code{x + n * f}
@item Subtract @code{n} from @code{x}:
@tab @code{x - n * f}
@item Multiply @code{x} by @code{y}:
@tab @code{((int64_t) x) * y / f}
@item Multiply @code{x} by @code{n}:
@tab @code{x * n}
@item Divide @code{x} by @code{y}:
@tab @code{((int64_t) x) * f / y}
@item Divide @code{x} by @code{n}:
@tab @code{x / n}
@end multitable
@html
</CENTER>
@end html

46
doc/Makefile Normal file
View File

@@ -0,0 +1,46 @@
TEXIS = pintos-ic.texi intro.texi codebase.texi threads.texi userprog.texi vm.texi \
license.texi reference.texi 44bsd.texi standards.texi \
doc.texi sample.tmpl.texi devel.texi debug.texi installation.texi \
bibliography.texi localsettings.texi task0_questions.texi localgitinstructions.texi
all: pintos-ic.html pintos-ic.info pintos-ic.dvi pintos-ic.ps pintos-ic.pdf task0_sheet.pdf alarmclock.pdf
pintos-ic.html: $(TEXIS) texi2html
./texi2html -toc_file=$@ -split=chapter -nosec_nav -nomenu -init_file ./pintos-t2h.init $<
pintos-ic.info: $(TEXIS)
makeinfo $<
pintos-ic.text: $(TEXIS)
makeinfo --plaintext -o $@ $<
pintos-ic.dvi: $(TEXIS)
texi2dvi $< -o $@
pintos-ic.ps: pintos-ic.dvi
dvips $< -o $@
pintos-ic.pdf: $(TEXIS)
texi2pdf $< -o $@
task0_sheet.pdf : task0_sheet.texi task0_questions.texi
texi2pdf $< -o $@
alarmclock.pdf : alarmclock.tex
pdflatex -shell-escape alarmclock
%.texi: %
sed < $< > $@ 's/\([{}@]\)/\@\1/g;'
clean:
rm -f *.info* *.html
rm -f *.aux *.cp *.dvi *.fn *.fns *.ky *.log *.pdf *.ps *.toc *.tp *.tps *.vr *.vrs *~
rm -rf WWW
rm -f sample.tmpl.texi
rm -f alarmclock.pdf
dist: pintos-ic.html pintos-ic.pdf
rm -rf WWW
mkdir WWW WWW/specs
cp *.html *.pdf *.css *.tmpl WWW
(cd ../specs && cp -r *.pdf freevga kbd sysv-abi-update.html ../doc/WWW/specs)

385
doc/alarmclock.tex Normal file
View File

@@ -0,0 +1,385 @@
\documentclass[a4paper,11pt]{article}
\setcounter{tocdepth}{3}
\usepackage[margin=1in]{geometry}
\usepackage{amsthm}
\usepackage{url}
\usepackage{microtype}
\usepackage{xcolor}
\usepackage{minted}
\usepackage[tt=false, type1=true]{libertine}
\usepackage[libertine]{newtxmath}
\usepackage[scaled=0.8, lining]{FiraMono}
\usepackage[T1]{fontenc}
\usepackage{setspace}
\usepackage{hyperref}
\setstretch{1.15}
\definecolor[named]{ACMPurple}{cmyk}{0.55,1,0,0.15}
\definecolor[named]{ACMDarkBlue}{cmyk}{1,0.58,0,0.21}
\hypersetup{colorlinks,
linkcolor=ACMPurple,
citecolor=ACMPurple,
urlcolor=ACMDarkBlue,
filecolor=ACMDarkBlue}
\usemintedstyle{xcode}
%inline code styling
\newmintinline[shell]{shell}{fontsize=\normalsize, breaklines}
\newmintinline[asm]{asm}{fontsize=\normalsize, breaklines}
% For illustrations
\usepackage{tikz}
%% Comments
\newif\ifcomment
% Comment this line to remove the comments
\commenttrue
\newcommand{\genericcomment}[2]{
\ifcomment
\begin{center}
\fbox{
\begin{minipage}{4in}
{\bf {#2}'s comment:} {\it #1}
\end{minipage}}
\end{center}
\fi}
\newcommand{\boxit}[1]{
\begin{center}
\fbox{
\begin{minipage}{6in}
#1
\end{minipage}
}
\end{center}
}
\newcommand{\markcomment}[1]{
\genericcomment{#1}{Mark}}
\begin{document}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\title{PintOS Task 0 - Codebase Preview}
\date{}
\author{
COMP50007.1 - Laboratory 2 \\
Department of Computing \\
Imperial College London
}
\maketitle
%%%%%%%%%%%%%%%%%%%%%
\section*{Summary}
%%%%%%%%%%%%%%%%%%%%%
This task is divided into two parts: a codebase preview and a small coding exercise.
The codebase preview has been designed to help you familiarise yourself with how PintOS is structured
and requires you to complete a short MCQ AnswerBook assessment to check your understanding of the provided PintOS code.
The coding exercise has been designed to help you understand how PintOS works
and is concerned with developing a simple feature in PintOS, called Alarm Clock.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Submit by 19:00 on Wednesday 9th October 2024}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{What To Do:}
%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection*{Getting the files required for the exercise}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
You have each been provided with a Git repository on the department's \shell{GitLab} server that contains the files required for this exercise.
To obtain this skeleton repository you will need to clone it into your local workspace.
You can do this with the following command:
%
\begin{minted}{shell}
prompt> git clone https://gitlab.doc.ic.ac.uk/lab2425_autumn/pintos_task0_<login>.git
\end{minted}
%
replacing \shell{<login>} with your normal college login.
You will be prompted for your normal college username and password.
You can also clone the skeleton repository via SSH (and avoid having to type in your username/password for every future clone, pull and push) if you have set up the required public/private keys on GitLab with the command:
%
\begin{minted}{shell}
prompt> git clone git@gitlab.doc.ic.ac.uk:lab2425_autumn/pintos_task0_<login>.git
\end{minted}
%
again, replacing \shell{<login>} with your normal college login.
Please feel free to ask a member of the lab support team for help with this if you want to access \shell{GitLab} via SSH but are unsure of how to set it up.
Using either of these commands will create a directory in your current location called \shell{pintos_task0_<login>}.
For more details about the contents of this repository see section 1.1.1 of the PintOS manual.
This is generally the way that we will hand out all lab exercises this year, so you should ensure that you are comfortable with the process.
\subsection*{Finding out about PintOS}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Everything that you need to know for the whole PintOS project can be found in the PintOS manual,
so it is a good idea to read it all eventually.
However, for the purposes of this codebase preview it should be sufficient that you carefully read sections 1 and 2
as well as appendicies A, C, D and E.
For some of the MCQ AnswerBook questions, examining the PintOS code-base will also be useful,
particularly \shell{thread.c}, \shell{thread.h} and \shell{synch} in the \shell{src/threads/} directory
and \shell{list.c} in the \shell{src/lib/kernel/} directory.\\
\noindent You can find additional guidance on this Task in section 2 of the PintOS manual: ``Task 0: Alarm Clock''
\subsection*{Working on PintOS}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
You should work on the files in your local workspace, making regular commits and pushes back to your \shell{GitLab} Git repository.
Recall that you will first need to add any new/modified files to your local Git workspace with:
%
\begin{minted}{shell}
prompt> git add <filename>
\end{minted}
%
You can then commit your changes to your local index with:
%
\begin{minted}{shell}
prompt> git commit -m "your *meaningful* commit message here"
\end{minted}
%
Finally you will need to push these changes from your local index to the Git repository with:
%
\begin{minted}{shell}
prompt> git push origin master
\end{minted}
%
You can check that a push succeeded by looking at the state of your repository using the \shell{GitLab} webpages:
\url{https://gitlab.doc.ic.ac.uk/}
\noindent (you will need to login with your normal college username and password).
You are of course free to utilise the more advanced features of Git such as branching and tagging.
Further details can be found in your first year notes and at:
\url{https://workspace.imperial.ac.uk/computing/Public/files/Git-Intro.pdf}.\\
{\bf Important:} Your final submission will be taken from your \shell{pintos_task0_<login>} \shell{GitLab} repository,
so you must understand how to push your work to it correctly.
If in any doubt, come and get help from the TF office (room 306) or during one of the lab sessions.
It is {\bf your} responsibility to ensure that you submit the correct version of your work.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Part A - Codebase Preview}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
In this part of the task you will be required to answer a series of MCQs (Multiple Choice Questions) that test your understanding of the basic PintOS concepts and the provided PintOS code-base.
If you have completed the pre-reading suggested above, then you should not find the MCQ AnswerBook test particularly challenging.
The MCQ AnswerBook test will be scheduled on Scientia, and the questions will be based on the following areas of PintOS.
The test will be open-book, so you are advised to answer these questions yourelf ahead of time.
\paragraph{Part 1:}
Which Git command should you run to retrieve a copy of your individual repository for PintOS Task 0 in your local directory? \\
(\textit{Hint: be specific to this task and think about ease of use.})
\paragraph{Part 2:}
Why is using the {\tt strcpy()} function to copy strings usually a bad idea? \\
(\textit{Hint: be sure to clearly identify the problem.})
\paragraph{Part 3:}
If test \shell{src/tests/devices/alarm-multiple} fails, where would you find its output and result logs? \\
Provide both paths and filenames. \\
(\textit{Hint: you might want to run this test and find out.})
\paragraph{Part 4:}
In PintOS, a thread is characterized by a struct and an execution stack. \\
(a) What are the limitations on the size of these data structures? \\
(b) Explain how this relates to stack overflow and how PintOS identifies if a stack overflow has occurred.
\paragraph{Part 5:}
Explain how thread scheduling in PintOS currently works in roughly 300 words.
Include the chain of execution of function calls. \\
(\textit{Hint: we expect you to at least mention which functions participate in a context switch, how they interact, how and when the thread state is modified and the role of interrupts.)}
\paragraph{Part 6:}
In PintOS, what is the default length (in ticks \emph{and} in seconds) of a scheduler time slice? \\
(\textit{Hint: read the Task 0 documentation carefully.})
\paragraph{Part 7:}
In PintOS, how would you print an unsigned 64 bit \shell{int}?
(Consider that you are working with C99). \\
Don't forget to state any inclusions needed by your code.
\paragraph{Part 8:}
Explain the property of {\bf reproducibility} and how the lack of reproducibility will affect debugging.
\paragraph{Part 9:}
In PintOS, locks are implemented on top of semaphores.\\
(a) How do the functions in the API of locks relate to those of semaphores?\\
(b) What extra property do locks have that semaphores do not?
\paragraph{Part 10:}
Define what is meant by a {\bf race-condition}. Why is the test \shell{ if(x \!= null) }
insufficient to prevent a segmentation fault from occurring on an attempted access to a structure through pointer \shell{x}?\\
(\textit{Hint: you should assume that the pointer variable is correctly typed, that the structure was successfully initialised earlier in the program
and that there are other threads running in parallel.})
\pagebreak
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Part B - The Alarm Clock}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
In this part, you are required to implement a simple functionality in PintOS and to answer the design document questions listed below.
\subsection*{Coding the Alarm Clock in PintOS}
Reimplement \shell{timer_sleep()}, defined in '\shell{devices/timer.c}.\\
\noindent Although a working implementation of \shell{timer_sleep()} is provided, it “busy waits,” that is,
it spins in a loop checking the current time and calling \shell{thread_yield()} until enough time has gone by.
You need to reimplement it to avoid busy waiting.
Further instructions and hints can be found in the PintOS manual.\\
\noindent The marks for this part are awarded as follows:
Passing the Automated Tests ({\bf 8 marks}).
Performance in the Code Review ({\bf 12 marks}).
Answering the Design Document Questions below ({\bf 10 marks}).
\subsection*{Task 0 Design Document Questions:}
\subsubsection*{Data Structures}
A1: ({\bf 2 marks}) \\
Copy here the declaration of each new or changed `\shell{struct}' or `\shell{struct}' member,
global or static variable, `\shell{typedef}', or enumeration.
Identify the purpose of each in roughly 25 words.
\subsubsection*{Algorithms}
A2: ({\bf 2 marks}) \\
Briefly describe what happens in a call to \shell{timer_sleep()}, including the actions performed by the timer interrupt handler on each timer tick. \\
\noindent A3: ({\bf 2 marks}) \\
What steps are taken to minimize the amount of time spent in the timer interrupt handler?
\subsubsection*{Synchronization}
A4: ({\bf 1 mark}) \\
How are race conditions avoided when multiple threads call \shell{timer_sleep()} simultaneously? \\
\noindent A5: ({\bf 1 mark}) \\
How are race conditions avoided when a timer interrupt occurs during a call to \shell{timer_sleep()}?
\subsubsection*{Rationale}
A6: ({\bf 2 marks}) \\
Why did you choose this design? \\
In what ways is it superior to another design you considered?
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Testing}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
As you work, you should \emph{add}, \emph{commit} and \emph{push} your changes to your Git repository, as discussed above.
You should also be carefully testing your work throughout the exercise.
You should be used to regularly testing your code locally on your development machine,
but to help you ensure that your code will compile and run as expected in our testing environment,
we have provided you with the Lab Testing Service: \shell{LabTS}.
\shell{LabTS} will clone your \shell{GitLab} repository and run several automated test processes over your work.
This will happen automatically after the deadline, but can also be requested during the course of the exercise (usually on a sub-set of the final tests).
You can access the \shell{LabTS} webpages at:
\url{https://teaching.doc.ic.ac.uk/labts}
\noindent (note that you will be required to log-in with your normal college username and password.)
If you click through to your \shell{pintos_task0_<login>} repository you will see a list of the different versions of your work that you have pushed.
Next to each commit you will see a button that will allow you to request that this version of your work is run through the automated test process.
If you click this button your work will be tested (this may take a few minutes) and the results will appear in the relevant column.\\
{\bf Important:} It is {\bf your} responsibility to ensure that your code behaves as expected in our automated test environment.
Code that fails to compile/run in this environment will score {\bf zero marks} for implementation correctness.
You should find that this environment behaves like the set-up found on our lab machines.
If you are experiencing any problems in this regard then you should seek help from a lab demonstrator or the lab coordinator at the earliest opportunity.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Submission}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Your \shell{GitLab} repository should contain the final submission for your alarm clock implementation.
\shell{LabTS} can be used to test any revision of your work that you wish.
However, you will still need to submit a \emph{revision id} to Scientia so that we know which version of your code you consider to be your final submission.
Prior to submission, you should check the state of your \shell{GitLab} repository using the \shell{LabTS} webpages:
\url{https://teaching.doc.ic.ac.uk/labts}
\noindent If you click through to your \shell{pintos_task0_<login>} repository you will see a list of the different versions of your work that you have pushed.
Next to each commit you will see a link to that commit on \shell{GitLab} as well as a button to submit that version of your code for assessment.
Pressing this button will redirect you to Scientia (automatically submitting your revision id)
and prompt you to upload an answers file and a design document under the usual ``original work'' disclaimer.
You should submit to Scientia the version of your code that you consider to be ``final''.
You can change this later by submitting a different version to Scientia as usual.
The submission button on LabTS will be replaced with a green confirmation label if the submission has been successful.
You should submit your Task 0 design document (\shell{designT0.pdf}) and the chosen version of your code to Scientia by 19:00 on Wednesday 9th October 2024.\\
%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section*{Assessment}
%%%%%%%%%%%%%%%%%%%%%%%%%%%
In total there are {\bf 50 marks} available in this exercise.\\
These are allocated as follows:
%
\begin{center}
\begin{tabular}{l@{\qquad\qquad}l}
Part A: MCQ Answerbook Test & {\bf 20 marks} \\
Part B: Automated Tests & {\bf 8 marks} \\
Part B: Code Review & {\bf 12 marks} \\
Part B: Design Document & {\bf 10 marks} \\
\end{tabular}
\end{center}
%
Any program that does not compile and run will score {\bf 0 marks} for Part B: Automated Tests.\\[-0.8em]
\noindent The marks for Part A will contribute to your COMP50004 Operating Systems coursework grade,
while your marks for Part B will contribute to your COMP50007.1 Laboratory 2 grade.\\
\noindent \textbf{We aim for feedback on this exercise to be returned by Wednesday 25th October 2023.}
\subsubsection*{What should I expect from the Task 0 code-review?}
The code-review for this task will be conducted offline, as it would be logistically
impossible to arrange face-to-face sessions with the whole cohort.
Our Task 0 code-review will cover \textbf{four} main areas:
functional correctness, efficiency, design quality and general coding style.
\begin{itemize}
\item For \textbf{functional correctness}, we will be looking to see if your solution can handle many threads going to sleep or waking-up at the same time, without any unnecessary delays.
We will also be checking if your code for \shell{timer_sleep} and \shell{timer_interrupt} is free of any race conditions.
\item For \textbf{efficiency}, we will be looking at what steps you have taken to minimise the time spent inside your timer interrupt handler. Think about how you store sleeping threads and track how long they must sleep for. We will also be looking at your use of memory.
\item For \textbf{design quality}, we will be looking at how your have integrated your alarm-clock code with the rest of the provided operating system. We want to see clear module boundaries and use of abstraction.
\item For \textbf{general coding style}, we will be paying attention to all of the usual elements of good style that you should be used to from last year (e.g. code layout, appropriate use of comments, avoiding magic numbers, etc.) as well as your use of git (e.g. commit frequency and commit message quality).
\end{itemize}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}

154
doc/bibliography.texi Normal file
View File

@@ -0,0 +1,154 @@
@node Bibliography
@appendix Bibliography
@macro bibdfn{cite}
@noindent @anchor{\cite\}
[\cite\].@w{ }
@end macro
@menu
* Hardware References::
* Software References::
* Operating System Design References::
@end menu
@node Hardware References
@section Hardware References
@bibdfn{IA32-v1}
IA-32 Intel Architecture Software Developer's Manual Volume 1: Basic
Architecture. Basic 80@var{x}86 architecture and programming
environment. Available via @uref{developer.intel.com}. Section numbers
in this document refer to revision 18.
@bibdfn{IA32-v2a}
IA-32 Intel Architecture Software Developer's Manual
Volume 2A: Instruction Set Reference A-M. 80@var{x}86 instructions
whose names begin with A through M. Available via
@uref{developer.intel.com}. Section numbers in this document refer to
revision 18.
@bibdfn{IA32-v2b}
IA-32 Intel Architecture Software Developer's Manual Volume 2B:
Instruction Set Reference N-Z. 80@var{x}86 instructions whose names
begin with N through Z. Available via @uref{developer.intel.com}.
Section numbers in this document refer to revision 18.
@bibdfn{IA32-v3a}
IA-32 Intel Architecture Software Developer's Manual Volume 3A: System
Programming Guide. Operating system support, including segmentation,
paging, tasks, interrupt and exception handling. Available via
@uref{developer.intel.com}. Section numbers in this document refer to
revision 18.
@bibdfn{FreeVGA}
@uref{specs/freevga/home.htm, , FreeVGA Project}. Documents the VGA video
hardware used in PCs.
@bibdfn{kbd}
@uref{specs/kbd/scancodes.html, , Keyboard scancodes}. Documents PC keyboard
interface.
@bibdfn{ATA-3}
@uref{specs/ata-3-std.pdf, , AT Attachment-3 Interface (ATA-3) Working
Draft}. Draft of an old version of the ATA aka IDE interface for the
disks used in most desktop PCs.
@bibdfn{PC16550D}
@uref{specs/pc16550d.pdf, , National Semiconductor PC16550D Universal
Asynchronous Receiver/Transmitter with FIFOs}. Datasheet for a chip
used for PC serial ports.
@bibdfn{8254}
@uref{specs/8254.pdf, , Intel 8254 Programmable Interval Timer}.
Datasheet for PC timer chip.
@bibdfn{8259A}
@uref{specs/8259A.pdf, , Intel 8259A Programmable Interrupt Controller
(8259A/8259A-2)}. Datasheet for PC interrupt controller chip.
@bibdfn{MC146818A}
@uref{specs/mc146818a.pdf, , Motorola MC146818A Real Time Clock Plus
Ram (RTC)}. Datasheet for PC real-time clock chip.
@node Software References
@section Software References
@bibdfn{ELF1}
@uref{specs/elf.pdf, , Tool Interface Standard (TIS) Executable and
Linking Format (ELF) Specification Version 1.2 Book I: Executable and
Linking Format}. The ubiquitous format for executables in modern Unix
systems.
@bibdfn{ELF2}
@uref{specs/elf.pdf, , Tool Interface Standard (TIS) Executable and
Linking Format (ELF) Specification Version 1.2 Book II: Processor
Specific (Intel Architecture)}. 80@var{x}86-specific parts of ELF.
@bibdfn{ELF3}
@uref{specs/elf.pdf, , Tool Interface Standard (TIS) Executable and
Linking Format (ELF) Specification Version 1.2 Book III: Operating
System Specific (UNIX System V Release 4)}. Unix-specific parts of
ELF.
@bibdfn{SysV-ABI}
@uref{specs/sysv-abi-4.1.pdf, , System V Application Binary Interface:
Edition 4.1}. Specifies how applications interface with the OS under
Unix.
@bibdfn{SysV-i386}
@uref{specs/sysv-abi-i386-4.pdf, , System V Application Binary
Interface: Intel386 Architecture Processor Supplement: Fourth
Edition}. 80@var{x}86-specific parts of the Unix interface.
@bibdfn{SysV-ABI-update}
@uref{specs/sysv-abi-update.html/contents.html, , System V Application Binary
Interface---DRAFT---24 April 2001}. A draft of a revised version of
@bibref{SysV-ABI} which was never completed.
@bibdfn{SUSv3}
The Open Group, @uref{http://www.unix.org/single_unix_specification/,
, Single UNIX Specification V3}, 2001.
@bibdfn{Partitions}
A.@: E.@: Brouwer, @uref{specs/partitions/partition_tables.html, ,
Minimal partition table specification}, 1999.
@bibdfn{IntrList}
R.@: Brown, @uref{http://www.ctyme.com/rbrown.htm, , Ralf Brown's
Interrupt List}, 2000.
@node Operating System Design References
@section Operating System Design References
@bibdfn{Christopher}
W.@: A.@: Christopher, S.@: J.@: Procter, T.@: E.@: Anderson,
@cite{The Nachos instructional operating system}.
Proceedings of the @acronym{USENIX} Winter 1993 Conference.
@uref{http://portal.acm.org/citation.cfm?id=1267307}.
@bibdfn{Dijkstra}
E.@: W.@: Dijkstra, @cite{The structure of the ``THE''
multiprogramming system}. Communications of the ACM 11(5):341--346,
1968. @uref{http://doi.acm.org/10.1145/363095.363143}.
@bibdfn{Hoare}
C.@: A.@: R.@: Hoare, @cite{Monitors: An Operating System
Structuring Concept}. Communications of the ACM, 17(10):549--557,
1974. @uref{http://www.acm.org/classics/feb96/}.
@bibdfn{Lampson}
B.@: W.@: Lampson, D.@: D.@: Redell, @cite{Experience with processes and
monitors in Mesa}. Communications of the ACM, 23(2):105--117, 1980.
@uref{http://doi.acm.org/10.1145/358818.358824}.
@bibdfn{McKusick}
M.@: K.@: McKusick, K.@: Bostic, M.@: J.@: Karels, J.@: S.@: Quarterman,
@cite{The Design and Implementation of the 4.4@acronym{BSD} Operating
System}. Addison-Wesley, 1996.
@bibdfn{Wilson}
P.@: R.@: Wilson, M.@: S.@: Johnstone, M.@: Neely, D.@: Boles,
@cite{Dynamic Storage Allocation: A Survey and Critical Review}.
International Workshop on Memory Management, 1995.
@uref{http://www.cs.utexas.edu/users/oops/papers.html#allocsrv}.

634
doc/codebase.texi Normal file
View File

@@ -0,0 +1,634 @@
@node Task 0--Codebase
@chapter Task 0: Alarm Clock
This task is divided into two parts, a codebase preview and a small coding exercise.
The codebase preview has been designed to help you understand how PintOS is structured.
The exercise requires you to answer a short worksheet (handed out through Scientia)
that contains a few questions to check your understanding of the provided PintOS code.
The coding exercise has been designed to help you understand how PintOS works and is structured.
The exercise is concerned with developing a simple feature in PintOS, called Alarm Clock.
@menu
* Task 1 Background::
* Task 0 Requirements::
@end menu
@node Task 1 Background
@section Background
@menu
* Understanding Threads::
* Task 1 Source Files::
* Task 1 Synchronization::
@end menu
@node Understanding Threads
@subsection Understanding Threads
The first step is to read and understand the code for the initial thread
system.
PintOS already implements thread creation and thread completion,
a simple scheduler to switch between threads, and synchronization
primitives (semaphores, locks, condition variables, and optimization
barriers).
Some of this code might seem slightly mysterious. If
you haven't already compiled and run the base system, as described in
the introduction (@pxref{Introduction}), you should do so now. You
can read through parts of the source code to see what's going
on. If you like, you can add calls to @func{printf} almost
anywhere, then recompile and run to see what happens and in what
order. You can also run the kernel in a debugger and set breakpoints
at interesting spots, single-step through code and examine data, and
so on.
When a thread is created, you are creating a new context to be
scheduled. You provide a function to be run in this context as an
argument to @func{thread_create}. The first time the thread is
scheduled and runs, it starts from the beginning of that function
and executes in that context. When the function returns, the thread
terminates. Each thread, therefore, acts like a mini-program running
inside PintOS, with the function passed to @func{thread_create}
acting like @func{main}.
At any given time, exactly one thread runs and the rest, if any,
become inactive. The scheduler decides which thread to
run next. (If no thread is ready to run
at any given time, then the special ``idle'' thread, implemented in
@func{idle}, runs.)
Synchronization primitives can force context switches when one
thread needs to wait for another thread to do something.
The mechanics of a context switch can be found in @file{threads/switch.S}, which is 80@var{x}86 assembly code.
(You don't have to understand it.)
It is enough to know that it saves the state of the currently running thread and restores the state of the thread we're switching to.
Using the GDB debugger on the PintOS kernel (@pxref{GDB}), you can slowly trace through a context switch to see what happens in the C code.
You can set a breakpoint on @func{schedule} to start out, and then
single-step from there.@footnote{GDB might tell you that
@func{schedule} doesn't exist, which is arguably a GDB bug.
You can work around this by setting the breakpoint by filename and
line number, e.g.@: @code{break thread.c:@var{ln}} where @var{ln} is
the line number of the first declaration in @func{schedule}.} Be sure
to keep track of each thread's address
and state, and what procedures are on the call stack for each thread.
You will notice that when one thread calls @func{switch_threads},
another thread starts running, and the first thing the new thread does
is to return from @func{switch_threads}. You will understand the thread
system once you understand why and how the @func{switch_threads} that
gets called is different from the @func{switch_threads} that returns.
@xref{Thread Switching}, for more information.
@strong{Warning}: In PintOS, each thread is assigned a small,
fixed-size execution stack just under @w{4 kB} in size. The kernel
tries to detect stack overflow, but it cannot do so perfectly. You
may cause bizarre problems, such as mysterious kernel panics, if you
declare large data structures as non-static local variables,
e.g. @samp{int buf[1000];}. Alternatives to stack allocation include
the page allocator and the block allocator (@pxref{Memory Allocation}).
@node Task 1 Source Files
@subsection Source Files
Despite PintOS being a tiny operating system, the code volume can be quite discouraging at first sight.
Don't panic: the Alarm Clock exercise for task 0 will help you understand PintOS by working on a small fragment of the code.
The coding required for the later tasks will be more extensive,
but in general should still be limited to a few hundred lines over only a few files.
Here, the hope is that presenting an overview of all source files will give you a start on what
code to look at.
@menu
* devices code::
* thread code::
* lib files::
@end menu
@node devices code
@subsubsection @file{devices} code
The basic threaded kernel includes the following files in the
@file{devices} directory:
@table @file
@item timer.c
@itemx timer.h
System timer that ticks, by default, 100 times per second. You will
modify this code in this task.
@item vga.c
@itemx vga.h
VGA display driver. Responsible for writing text to the screen.
You should have no need to look at this code. @func{printf}
calls into the VGA display driver for you, so there's little reason to
call this code yourself.
@item serial.c
@itemx serial.h
Serial port driver. Again, @func{printf} calls this code for you,
so you don't need to do so yourself.
It handles serial input by passing it to the input layer (see below).
@item block.c
@itemx block.h
An abstraction layer for @dfn{block devices}, that is, random-access,
disk-like devices that are organized as arrays of fixed-size blocks.
Out of the box, PintOS supports two types of block devices: IDE disks
and partitions. Block devices, regardless of type, won't actually be
used until task 2.
@item ide.c
@itemx ide.h
Supports reading and writing sectors on up to 4 IDE disks.
@item partition.c
@itemx partition.h
Understands the structure of partitions on disks, allowing a single
disk to be carved up into multiple regions (partitions) for
independent use.
@item kbd.c
@itemx kbd.h
Keyboard driver. Handles keystrokes passing them to the input layer
(see below).
@item input.c
@itemx input.h
Input layer. Queues input characters passed along by the keyboard or
serial drivers.
@item intq.c
@itemx intq.h
Interrupt queue, for managing a circular queue that both kernel
threads and interrupt handlers want to access. Used by the keyboard
and serial drivers.
@item rtc.c
@itemx rtc.h
Real-time clock driver, to enable the kernel to determine the current
date and time. By default, this is only used by @file{thread/init.c}
to choose an initial seed for the random number generator.
@item speaker.c
@itemx speaker.h
Driver that can produce tones on the PC speaker.
@item pit.c
@itemx pit.h
Code to configure the 8254 Programmable Interrupt Timer. This code is
used by both @file{devices/timer.c} and @file{devices/speaker.c}
because each device uses one of the PIT's output channel.
@end table
@node thread code
@subsubsection @file{thread} code
Here is a brief overview of the files in the @file{threads}
directory.
@table @file
@item loader.S
@itemx loader.h
The kernel loader. Assembles to 512 bytes of code and data that the
PC BIOS loads into memory and which in turn finds the kernel on disk,
loads it into memory, and jumps to @func{start} in @file{start.S}.
@xref{PintOS Loader}, for details. You should not need to look at
this code or modify it.
@item start.S
Does basic setup needed for memory protection and 32-bit
operation on 80@var{x}86 CPUs. Unlike the loader, this code is
actually part of the kernel. @xref{Low-Level Kernel Initialization},
for details.
@item kernel.lds.S
The linker script used to link the kernel. Sets the load address of
the kernel and arranges for @file{start.S} to be near the beginning
of the kernel image. @xref{PintOS Loader}, for details. Again, you
should not need to look at this code
or modify it, but it's here in case you're curious.
@item init.c
@itemx init.h
Kernel initialization, including @func{main}, the kernel's ``main
program.'' You should look over @func{main} at least to see what
gets initialized. You might want to add your own initialization code
here. @xref{High-Level Kernel Initialization}, for details.
@item thread.c
@itemx thread.h
Basic thread support. @file{thread.h} defines @struct{thread}, which you are likely to modify
in all four tasks. See @ref{struct thread} and @ref{Threads} for
more information.
@item switch.S
@itemx switch.h
Assembly language routine for switching threads. Already discussed
above. @xref{Thread Functions}, for more information.
@item palloc.c
@itemx palloc.h
Page allocator, which hands out system memory in multiples of 4 kB
pages. @xref{Page Allocator}, for more information.
@item malloc.c
@itemx malloc.h
A simple implementation of @func{malloc} and @func{free} for
the kernel. @xref{Block Allocator}, for more information.
@item interrupt.c
@itemx interrupt.h
Basic interrupt handling and functions for turning interrupts on and
off. @xref{Interrupt Handling}, for more information.
@item intr-stubs.S
@itemx intr-stubs.h
Assembly code for low-level interrupt handling. @xref{Interrupt
Infrastructure}, for more information.
@item synch.c
@itemx synch.h
Basic synchronization primitives: semaphores, locks, condition
variables, and optimization barriers. You will need to use these for
synchronization in all
four tasks. @xref{Synchronization}, for more information.
@item io.h
Functions for I/O port access. This is mostly used by source code in
the @file{devices} directory that you won't have to touch.
@item vaddr.h
@itemx pte.h
Functions and macros for working with virtual addresses and page table
entries. These will be more important to you in task 3. For now,
you can ignore them.
@item flags.h
Macros that define a few bits in the 80@var{x}86 ``flags'' register.
Probably of no interest. See @bibref{IA32-v1}, section 3.4.3, ``EFLAGS
Register,'' for more information.
@end table
@node lib files
@subsubsection @file{lib} files
Finally, @file{lib} and @file{lib/kernel} contain useful library
routines. (@file{lib/user} will be used by user programs, starting in
task 2, but it is not part of the kernel.) Here's a few more
details:
@table @file
@item ctype.h
@itemx inttypes.h
@itemx limits.h
@itemx stdarg.h
@itemx stdbool.h
@itemx stddef.h
@itemx stdint.h
@itemx stdio.c
@itemx stdio.h
@itemx stdlib.c
@itemx stdlib.h
@itemx string.c
@itemx string.h
A subset of the standard C library. @xref{C99}, for
information
on a few recently introduced pieces of the C library that you might
not have encountered before. @xref{Unsafe String Functions}, for
information on what's been intentionally left out for safety.
@item debug.c
@itemx debug.h
Functions and macros to aid debugging. @xref{Debugging Tools}, for
more information.
@item random.c
@itemx random.h
Pseudo-random number generator. The actual sequence of random values
may vary from one PintOS run to another.
@item round.h
Macros for rounding.
@item syscall-nr.h
System call numbers. Not used until task 2.
@item kernel/list.c
@itemx kernel/list.h
Doubly linked list implementation. Used all over the PintOS code, and
you'll probably want to use it a few places yourself in task 0 and task 1.
@item kernel/bitmap.c
@itemx kernel/bitmap.h
Bitmap implementation. You can use this in your code if you like, but
you probably won't have any need for it in task 0 or task 1.
@item kernel/hash.c
@itemx kernel/hash.h
Hash table implementation. Likely to come in handy for task 3.
@item kernel/console.c
@itemx kernel/console.h
@item kernel/stdio.h
Implements @func{printf} and a few other functions.
@end table
@node Task 1 Synchronization
@subsection Synchronization
Proper synchronization is an important part of the solutions to these
problems. Any synchronization problem can be easily solved by turning
interrupts off: while interrupts are off, there is no concurrency, so
there's no possibility for race conditions. Therefore, it's tempting to
solve all synchronization problems this way, but @strong{don't}.
Instead, use semaphores, locks, and condition variables to solve the
bulk of your synchronization problems. Read the tour section on
synchronization (@pxref{Synchronization}) or the comments in
@file{threads/synch.c} if you're unsure what synchronization primitives
may be used in what situations.
In the PintOS tasks, the only class of problem best solved by
disabling interrupts is coordinating data shared between a kernel thread
and an interrupt handler. Because interrupt handlers can't sleep, they
can't acquire locks. This means that data shared between kernel threads
and an interrupt handler must be protected within a kernel thread by
turning off interrupts.
This task only requires accessing a little bit of thread state from
interrupt handlers. For the alarm clock, the timer interrupt needs to
wake up sleeping threads. Later, in task 1, the advanced scheduler timer
interrupts will need to access a few global and per-thread variables. When
you access these variables from kernel threads, you will need to disable
interrupts to prevent the timer interrupts from interfering with one-another.
When you do turn off interrupts, take care to do so for the least amount
of code possible, or you can end up losing important things such as
timer ticks or input events. Turning off interrupts also increases the
interrupt handling latency, which can make a machine feel sluggish if
taken too far.
The synchronization primitives themselves in @file{synch.c} are
implemented by disabling interrupts. You may need to increase the
amount of code that runs with interrupts disabled here, but you should
still try to keep it to a minimum.
Disabling interrupts can be useful for debugging, if you want to make
sure that a section of code is not interrupted. You should remove
debugging code before turning in your task. (Don't just comment it
out, because that can make the code difficult to read.)
There should be @strong{no} busy waiting in your submission. A tight loop that
calls @func{thread_yield} is one form of busy waiting.
@page
@node Task 0 Requirements
@section Requirements
@menu
* Codebase Preview::
* Alarm Clock Design Document::
* Alarm Clock::
* FAQ::
@end menu
@node Codebase Preview
@subsection Codebase Preview
@menu
* Source Files::
* Questions::
@end menu
For answering the MCQ AnswerBook test questions in the codebase preview you will be expected to have fully read:
@itemize
@item Section 1
@item Section 2.1.1 and 2.1.3
@item Sections A.2-4
@item Sections C, D, E and F
@end itemize
@node Source Files
@subsubsection Source Files
The source files you will have to fully understand:
@table @file
@item src/threads/thread.c
Contains bulk of threading system code
@item src/threads/thread.h
Header file for threads, contains thread struct
@item src/threads/synch.c
Contains the implementation of major synchronisation primitives like
locks and semaphores
@item src/lib/kernel/list.c
Contains PintOS' list implementation
@end table
@node Questions
@subsubsection Task 0 Questions
@include task0_questions.texi
@node Alarm Clock Design Document
@subsection Design Document
When you submit your work for task 0, you must also submit a completed copy of
@uref{devices.tmpl, , the task 0 design document}.
You can find a template design document for this task in @file{pintos/doc/devices.tmpl} and also on Scientia.
You must submit your design document as a @file{.pdf} file.
We recommend that you read the design document template before you start working on the task.
@xref{Task Documentation}, for a sample design document that goes along with a fictitious task.
@node Alarm Clock
@subsection Coding the Alarm Clock
Reimplement @func{timer_sleep}, defined in @file{devices/timer.c}.
Although a working implementation is provided, it ``busy waits,'' that
is, it spins in a loop checking the current time and calling
@func{thread_yield} until enough time has gone by. Reimplement it to
avoid busy waiting.
@deftypefun void timer_sleep (int64_t @var{ticks})
Suspends execution of the calling thread until time has advanced by at
least @w{@var{x} timer ticks}. Unless the system is otherwise idle, the
thread need not wake up after exactly @var{x} ticks. Just put it on
the ready queue after they have waited for the right amount of time.
@func{timer_sleep} is useful for threads that operate in real-time,
e.g.@: for blinking the cursor once per second.
The argument to @func{timer_sleep} is expressed in timer ticks, not in
milliseconds or any another unit. There are @code{TIMER_FREQ} timer
ticks per second, where @code{TIMER_FREQ} is a macro defined in
@code{devices/timer.h}. The default value is 100. We don't recommend
changing this value, because any change is likely to cause many of
the tests to fail.
@end deftypefun
Separate functions @func{timer_msleep}, @func{timer_usleep}, and
@func{timer_nsleep} do exist for sleeping a specific number of
milliseconds, microseconds, or nanoseconds, respectively, but these will
call @func{timer_sleep} automatically when necessary. You do not need
to modify them.
If your delays seem too short or too long, reread the explanation of the
@option{-r} option to @command{pintos} (@pxref{Debugging versus
Testing}).
The alarm clock implementation is needed for Task 1, but is not needed for any later tasks.
@node FAQ
@subsection FAQ
@table @b
@item How much code will I need to write?
Here's a summary of our reference solution, produced by the
@command{diffstat} program. The final row gives total lines inserted
and deleted; a changed line counts as both an insertion and a deletion.
@verbatim
devices/timer.c | 40 ++++++++++++++++++++++++++++++++++++++--
devices/timer.h | 9 +++++++++
2 files changed, 47 insertions(+), 2 deletions(-)
@end verbatim
The reference solution represents just one possible solution. Many
other solutions are also possible and many of those differ greatly from
the reference solution. Some excellent solutions may not modify all the
files modified by the reference solution, and some may modify files not
modified by the reference solution.
@item What does @code{warning: no previous prototype for `@var{func}'} mean?
It means that you defined a non-@code{static} function without
preceding it by a prototype. Because non-@code{static} functions are
intended for use by other @file{.c} files, for safety they should be
prototyped in a header file included before their definition. To fix
the problem, add a prototype in a header file that you include, or, if
the function isn't actually used by other @file{.c} files, make it
@code{static}.
@item What is the interval between timer interrupts?
Timer interrupts occur @code{TIMER_FREQ} times per second. You can
adjust this value by editing @file{devices/timer.h}. The default is
100 Hz.
We don't recommend changing this value, because any changes are likely
to cause many of the tests to fail.
@item How long is a time slice?
There are @code{TIME_SLICE} ticks per time slice. This macro is
declared in @file{threads/thread.c}. The default is 4 ticks.
We don't recommend changing this value, because any changes are likely
to cause many of the tests to fail.
@item How do I run the tests?
@xref{Testing}.
@item Why do I get a test failure in @func{pass}?
@xref{The pass function fails}.
You are probably looking at a backtrace that looks something like this:
@example
0xc0108810: debug_panic (lib/kernel/debug.c:32)
0xc010a99f: pass (tests/threads/tests.c:93)
0xc010bdd3: test_mlfqs_load_1 (...threads/mlfqs-load-1.c:33)
0xc010a8cf: run_test (tests/threads/tests.c:51)
0xc0100452: run_task (threads/init.c:283)
0xc0100536: run_actions (threads/init.c:333)
0xc01000bb: main (threads/init.c:137)
@end example
This is just confusing output from the @command{backtrace} program. It
does not actually mean that @func{pass} called @func{debug_panic}. In
fact, @func{fail} called @func{debug_panic} (via the @func{PANIC}
macro). GCC knows that @func{debug_panic} does not return, because it
is declared @code{NO_RETURN} (@pxref{Function and Parameter
Attributes}), so it doesn't include any code in @func{fail} to take
control when @func{debug_panic} returns. This means that the return
address on the stack looks like it is at the beginning of the function
that happens to follow @func{fail} in memory, which in this case happens
to be @func{pass}.
@xref{Backtraces}, for more information.
@item How do interrupts get re-enabled in the new thread following @func{schedule}?
Every path into @func{schedule} disables interrupts. They eventually
get re-enabled by the next thread to be scheduled. Consider the
possibilities: the new thread is running in @func{switch_thread} (but
see below), which is called by @func{schedule}, which is called by one
of a few possible functions:
@itemize @bullet
@item
@func{thread_exit}, but we'll never switch back into such a thread, so
it's uninteresting.
@item
@func{thread_yield}, which immediately restores the interrupt level upon
return from @func{schedule}.
@item
@func{thread_block}, which is called from multiple places:
@itemize @minus
@item
@func{sema_down}, which restores the interrupt level before returning.
@item
@func{idle}, which enables interrupts with an explicit assembly STI
instruction.
@item
@func{wait} in @file{devices/intq.c}, whose callers are responsible for
re-enabling interrupts.
@end itemize
@end itemize
There is a special case when a newly created thread runs for the first
time. Such a thread calls @func{intr_enable} as the first action in
@func{kernel_thread}, which is at the bottom of the call stack for every
kernel thread but the first.
@item Do I need to account for timer values overflowing?
Don't worry about the possibility of timer values overflowing. Timer
values are expressed as signed 64-bit numbers, which at 100 ticks per
second should be good for almost 2,924,712,087 years. By then, we
expect PintOS to have been phased out of the @value{coursenumber} curriculum.
@item What should I expect from the Task 0 code-review?
The code-review for this task will be conducted offline, as it would be logistically
impossible to arrange face-to-face sessions with the whole cohort.
Our Task 0 code-review will cover @strong{four} main areas:
functional correctness, efficiency, design quality and general coding style.
@itemize @bullet
@item For @strong{functional correctness}, we will be looking to see if your solution can handle many
threads going to sleep or waking-up at the same time, without any unnecessary delays.
We will also be checking if your code for @func{timer_sleep} and @func{timer_interrupt} is free of any race conditions.
@item For @strong{efficiency}, we will be looking at what steps you have taken to minimise the time spent
inside your timer interrupt handler. Think about how you store sleeping threads and track
how long they must sleep for. We will also be looking at your use of memory.
@item For @strong{design quality}, we will be looking at how your have integrated your alarm-clock code with
the rest of the provided operating system. We want to see clear module boundaries and use of abstraction.
@item For @strong{general coding style}, we will be paying attention to all of the usual elements of good style
that you should be used to from last year (e.g. consistent code layout, appropriate use of comments, avoiding magic numbers, etc.)
as well as your use of git (e.g. commit frequency and commit message quality).
@end itemize
@end table

702
doc/debug.texi Normal file
View File

@@ -0,0 +1,702 @@
@node Debugging Tools
@appendix Debugging Tools
Many tools lie at your disposal for debugging PintOS. This appendix
introduces you to a few of them.
@menu
* printf::
* ASSERT::
* Function and Parameter Attributes::
* Backtraces::
* GDB::
* Triple Faults::
* Debugging Tips::
@end menu
@node printf
@section @code{printf()}
Don't underestimate the value of @func{printf}. The way
@func{printf} is implemented in PintOS, you can call it from
practically anywhere in the kernel, whether it's in a kernel thread or
an interrupt handler, almost regardless of what locks are held.
@func{printf} is useful for more than just examining data.
It can also help figure out when and where something goes wrong, even
when the kernel crashes or panics without a useful error message. The
strategy is to sprinkle calls to @func{printf} with different strings
(e.g.@: @code{"<1>"}, @code{"<2>"}, @dots{}) throughout the pieces of
code you suspect are failing. If you don't even see @code{<1>} printed,
then something bad happened before that point, if you see @code{<1>}
but not @code{<2>}, then something bad happened between those two
points, and so on. Based on what you learn, you can then insert more
@func{printf} calls in the new, smaller region of code you suspect.
Eventually you can narrow the problem down to a single statement.
@xref{Triple Faults}, for a related technique.
@node ASSERT
@section @code{ASSERT}
Assertions are useful because they can catch problems early, before
they'd otherwise be noticed. Ideally, each function should begin with a
set of assertions that check its arguments for validity. (Initializers
for functions' local variables are evaluated before assertions are
checked, so be careful not to assume that an argument is valid in an
initializer.) You can also sprinkle assertions throughout the body of
functions in places where you suspect things are likely to go wrong.
They are especially useful for checking loop invariants.
PintOS provides the @code{ASSERT} macro, defined in @file{<debug.h>},
for checking assertions.
@defmac ASSERT (expression)
Tests the value of @var{expression}. If it evaluates to zero (false),
the kernel panics. The panic message includes the expression that
failed, its file and line number, and a backtrace, which should help you
to find the problem. @xref{Backtraces}, for more information.
@end defmac
@node Function and Parameter Attributes
@section Function and Parameter Attributes
These macros defined in @file{<debug.h>} tell the compiler special
attributes of a function or function parameter. Their expansions are
GCC-specific.
@defmac UNUSED
Appended to a function parameter to tell the compiler that the
parameter might not be used within the function. It suppresses the
warning that would otherwise appear.
@end defmac
@defmac NO_RETURN
Appended to a function prototype to tell the compiler that the
function never returns. It allows the compiler to fine-tune its
warnings and its code generation.
@end defmac
@defmac NO_INLINE
Appended to a function prototype to tell the compiler to never emit
the function in-line. Occasionally useful to improve the quality of
backtraces (see below).
@end defmac
@defmac PRINTF_FORMAT (@var{format}, @var{first})
Appended to a function prototype to tell the compiler that the function
takes a @func{printf}-like format string as the argument numbered
@var{format} (starting from 1) and that the corresponding value
arguments start at the argument numbered @var{first}. This lets the
compiler tell you if you pass the wrong argument types.
@end defmac
@node Backtraces
@section Backtraces
When the kernel panics, it prints a ``backtrace,'' that is, a summary
of how your program got where it is, as a list of addresses inside the
functions that were running at the time of the panic. You can also
insert a call to @func{debug_backtrace}, prototyped in
@file{<debug.h>}, to print a backtrace at any point in your code.
@func{debug_backtrace_all}, also declared in @file{<debug.h>},
prints backtraces of all threads.
The addresses in a backtrace are listed as raw hexadecimal numbers,
which are difficult to interpret. We provide a tool called
@command{backtrace} to translate these into function names and source
file line numbers.
Give it the name of your @file{kernel.o} as the first argument and the
hexadecimal numbers composing the backtrace (including the @samp{0x}
prefixes) as the remaining arguments. It outputs the function name
and source file line numbers that correspond to each address.
If the translated form of a backtrace is garbled, or doesn't make
sense (e.g.@: function A is listed above function B, but B doesn't
call A), then it's a good sign that you're corrupting a kernel
thread's stack, because the backtrace is extracted from the stack.
Alternatively, it could be that the @file{kernel.o} you passed to
@command{backtrace} is not the same kernel that produced
the backtrace.
Sometimes backtraces can be confusing without any corruption.
Compiler optimizations can cause surprising behaviour. When a function
has called another function as its final action (a @dfn{tail call}), the
calling function may not appear in a backtrace at all. Similarly, when
function A calls another function B that never returns, the compiler may
optimize such that an unrelated function C appears in the backtrace
instead of A. Function C is simply the function that happens to be in
memory just after A. In the threads task, this is commonly seen in
backtraces for test failures; see @ref{The pass function fails, ,
@func{pass} fails}, for more information.
@menu
* Backtrace Example::
@end menu
@node Backtrace Example
@subsection Example
Here's an example. Suppose that PintOS printed out this following call
stack, which is taken from an actual PintOS submission:
@example
Call stack: 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319
0xc010325a 0x804812c 0x8048a96 0x8048ac8.
@end example
You would then invoke the @command{backtrace} utility like shown below,
cutting and pasting the backtrace information into the command line.
This assumes that @file{kernel.o} is in the current directory. You
would of course enter all of the following on a single shell command
line, even though that would overflow our margins here:
@example
backtrace kernel.o 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67
0xc0102319 0xc010325a 0x804812c 0x8048a96 0x8048ac8
@end example
The backtrace output would then look something like this:
@example
0xc0106eff: debug_panic (lib/debug.c:86)
0xc01102fb: file_seek (filesys/file.c:405)
0xc010dc22: seek (userprog/syscall.c:744)
0xc010cf67: syscall_handler (userprog/syscall.c:444)
0xc0102319: intr_handler (threads/interrupt.c:334)
0xc010325a: intr_entry (threads/intr-stubs.S:38)
0x0804812c: (unknown)
0x08048a96: (unknown)
0x08048ac8: (unknown)
@end example
(You will probably not see exactly the same addresses if you run the
command above on your own kernel binary, because the source code you
compiled and the compiler you used are probably different.)
The first line in the backtrace refers to @func{debug_panic}, the
function that implements kernel panics. Because backtraces commonly
result from kernel panics, @func{debug_panic} will often be the first
function shown in a backtrace.
The second line shows @func{file_seek} as the function that panicked,
in this case as the result of an assertion failure. In the source code
tree used for this example, line 405 of @file{filesys/file.c} is the
assertion
@example
ASSERT (file_ofs >= 0);
@end example
@noindent
(This line was also cited in the assertion failure message.)
Thus, @func{file_seek} panicked because it passed a negative file offset
argument.
The third line indicates that @func{seek} called @func{file_seek},
presumably without validating the offset argument. In this submission,
@func{seek} implements the @code{seek} system call.
The fourth line shows that @func{syscall_handler}, the system call
handler, invoked @func{seek}.
The fifth and sixth lines are the interrupt handler entry path.
The remaining lines are for addresses below @code{PHYS_BASE}. This
means that they refer to addresses in the user program, not in the
kernel. If you know what user program was running when the kernel
panicked, you can re-run @command{backtrace} on the user program, like
so: (typing the command on a single line, of course):
@example
backtrace tests/filesys/extended/grow-too-big 0xc0106eff 0xc01102fb
0xc010dc22 0xc010cf67 0xc0102319 0xc010325a 0x804812c 0x8048a96
0x8048ac8
@end example
The results look like this:
@example
0xc0106eff: (unknown)
0xc01102fb: (unknown)
0xc010dc22: (unknown)
0xc010cf67: (unknown)
0xc0102319: (unknown)
0xc010325a: (unknown)
0x0804812c: test_main (...xtended/grow-too-big.c:20)
0x08048a96: main (tests/main.c:10)
0x08048ac8: _start (lib/user/entry.c:9)
@end example
You can even specify both the kernel and the user program names on
the command line, like so:
@example
backtrace kernel.o tests/filesys/extended/grow-too-big 0xc0106eff
0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319 0xc010325a 0x804812c
0x8048a96 0x8048ac8
@end example
The result is a combined backtrace:
@example
In kernel.o:
0xc0106eff: debug_panic (lib/debug.c:86)
0xc01102fb: file_seek (filesys/file.c:405)
0xc010dc22: seek (userprog/syscall.c:744)
0xc010cf67: syscall_handler (userprog/syscall.c:444)
0xc0102319: intr_handler (threads/interrupt.c:334)
0xc010325a: intr_entry (threads/intr-stubs.S:38)
In tests/filesys/extended/grow-too-big:
0x0804812c: test_main (...xtended/grow-too-big.c:20)
0x08048a96: main (tests/main.c:10)
0x08048ac8: _start (lib/user/entry.c:9)
@end example
Here's an extra tip for anyone who read this far: @command{backtrace}
is smart enough to strip the @code{Call stack:} header and @samp{.}
trailer from the command line if you include them. This can save you
a little bit of trouble in cutting and pasting. Thus, the following
command prints the same output as the first one we used:
@example
backtrace kernel.o Call stack: 0xc0106eff 0xc01102fb 0xc010dc22
0xc010cf67 0xc0102319 0xc010325a 0x804812c 0x8048a96 0x8048ac8.
@end example
@node GDB
@section GDB
You can run PintOS under the supervision of the GDB debugger.
First, start PintOS with the @option{--gdb} option, e.g.@:
@command{pintos --gdb -- run mytest}. Second, open a second terminal on
the same machine and
use @command{pintos-gdb} to invoke GDB on
@file{kernel.o}:@footnote{@command{pintos-gdb} is a wrapper around
@command{gdb} (80@var{x}86) that loads the PintOS macros at startup.}
@example
pintos-gdb kernel.o
@end example
@noindent and issue the following GDB command:
@example
target remote localhost:1234
@end example
@noindent or alternatively issue the following GDB macro:
@example
debugpintos
@end example
Now GDB is connected to the simulator over a local
network connection. You can now issue any normal GDB
commands. If you issue the @samp{c} command, the simulated BIOS will take
control, load PintOS, and then PintOS will run in the usual way. You
can pause the process at any point with @key{Ctrl+C}.
@menu
* Using GDB::
* Example GDB Session::
* GDB FAQ::
@end menu
@node Using GDB
@subsection Using GDB
You can read the GDB manual by typing @code{info gdb} at a
terminal command prompt. Here's a few commonly useful GDB commands:
@deffn {GDB Command} c
Continues execution until @key{Ctrl+C} or the next breakpoint.
@end deffn
@deffn {GDB Command} break function
@deffnx {GDB Command} break file:line
@deffnx {GDB Command} break *address
Sets a breakpoint at @var{function}, at @var{line} within @var{file}, or
@var{address}.
(Use a @samp{0x} prefix to specify an address in hex.)
Use @code{break main} to make GDB stop when PintOS starts running.
@end deffn
@deffn {GDB Command} p expression
Evaluates the given @var{expression} and prints its value.
If the expression contains a function call, that function will actually
be executed.
@end deffn
@deffn {GDB Command} l *address
Lists a few lines of code around @var{address}.
(Use a @samp{0x} prefix to specify an address in hex.)
@end deffn
@deffn {GDB Command} bt
Prints a stack backtrace similar to that output by the
@command{backtrace} program described above.
@end deffn
@deffn {GDB Command} p/a address
Prints the name of the function or variable that occupies @var{address}.
(Use a @samp{0x} prefix to specify an address in hex.)
@end deffn
@deffn {GDB Command} diassemble function
Disassembles @var{function}.
@end deffn
We also provide a set of macros specialized for debugging PintOS,
written by Godmar Back @email{gback@@cs.vt.edu}. You can type
@code{help user-defined} for basic help with the macros. Here is an
overview of their functionality, based on Godmar's documentation:
@deffn {GDB Macro} debugpintos
Attach debugger to a waiting pintos process on the same machine.
Shorthand for @code{target remote localhost:1234}.
@end deffn
@deffn {GDB Macro} dumplist list type element
Prints the elements of @var{list}, which must be passed by reference and should be a @code{struct list}
that contains elements of the given @var{type} (without the word
@code{struct}) in which @var{element} is the @struct{list_elem} member
that links the elements.
Example: @code{dumplist &all_list thread allelem} prints all elements of
@struct{thread} that are linked in @code{struct list all_list} using the
@code{struct list_elem allelem} which is part of @struct{thread}.
@end deffn
@deffn {GDB Macro} dumphash hash type element
Similar to @code{dumplist}. Prints the elements of @var{hash}, which must be passed by reference and should be a @code{struct hash}
that contains elements of the given @var{type} (without the word
@code{struct}) in which @var{element} is the @struct{hash_elem} member
that links the elements.
@end deffn
@deffn {GDB Macro} btthread thread
Shows the backtrace of @var{thread}, which is a pointer to the
@struct{thread} of the thread whose backtrace it should show. For the
current thread, this is identical to the @code{bt} (backtrace) command.
It also works for any thread suspended in @func{schedule},
provided you know where its kernel stack page is located.
@end deffn
@deffn {GDB Macro} btthreadlist list element
Shows the backtraces of all threads in @var{list}, which must be passed by reference and is the @struct{list} in which the threads are kept.
Specify @var{element} as the @struct{list_elem} field used inside @struct{thread} to link the threads together.
Example: @code{btthreadlist &all_list allelem} shows the backtraces of
all threads contained in @code{struct list all_list}, linked together by
@code{allelem}. This command is useful to determine where your threads
are stuck when a deadlock occurs. Please see the example scenario below.
@end deffn
@deffn {GDB Macro} btthreadall
Short-hand for @code{btthreadlist all_list allelem}.
@end deffn
@deffn {GDB Macro} hook-stop
GDB invokes this macro every time the simulation stops, which QEMU will
do for every processor exception, among other reasons. If the
simulation stops due to a page fault, @code{hook-stop} will print a
message that says and explains further whether the page fault occurred
in the kernel or in user code.
If the exception occurred from user code, @code{hook-stop} will say:
@example
pintos-debug: a page fault exception occurred in user mode
pintos-debug: hit 'c' to continue, or 's' to step to intr_handler
@end example
In Task 2, a page fault in a user process leads to the termination of
the process. You should expect those page faults to occur in the
robustness tests where we test that your kernel properly terminates
processes that try to access invalid addresses. To debug those, set a
break point in @func{page_fault} in @file{exception.c}, which you will
need to modify accordingly.
In Task 3, a page fault in a user process no longer automatically
leads to the termination of a process. Instead, it may require reading in
data for the page the process was trying to access, either
because it was swapped out or because this is the first time it's
accessed. In either case, you will reach @func{page_fault} and need to
take the appropriate action there.
If the page fault did not occur in user mode while executing a user
process, then it occurred in kernel mode while executing kernel code.
In this case, @code{hook-stop} will print this message:
@example
pintos-debug: a page fault occurred in kernel mode
@end example
Before Task 3, a page fault exception in kernel code is always a bug
in your kernel, because your kernel should never crash. Starting with
Task 3, the situation will change if you use the @func{get_user} and
@func{put_user} strategy to verify user memory accesses
(@pxref{Accessing User Memory}).
@c ----
@c Unfortunately, this does not work with Bochs's gdb stub.
@c ----
@c If you don't want GDB to stop for page faults, then issue the command
@c @code{handle SIGSEGV nostop}. GDB will still print a message for
@c every page fault, but it will not come back to a command prompt.
@end deffn
@node Example GDB Session
@subsection Example GDB Session
This section narrates a sample GDB session, provided by Godmar Back
(modified by Mark Rutland and Feroz Abdul Salam, and updated by Fidelis Perkonigg).
This example illustrates how one might debug a Task 1 solution in
which occasionally a thread that calls @func{timer_sleep} is not woken
up. With this bug, tests such as @code{mlfqs_load_1} get stuck.
Program output is shown in normal type, user input in @strong{strong}
type.
@noindent First, we start PintOS using the QEMU emulator:
@smallexample
@code{$ pintos -v --qemu --gdb -- -q -mlfqs run mlfqs-load-1}
qemu-system-i386 -drive file=/tmp/GKWoGG8QE6.dsk,index=0,media=disk,format=raw -m 4 -net none -nographic -s -S
@end smallexample
@noindent This starts QEMU but pauses the execution of PintOS immediately to
allow us to attach GDB to PintOS. We open a second window in the same directory
on the same machine and start GDB:
@smallexample
$ @strong{pintos-gdb kernel.o}
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
...
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from kernel.o...done.
The target architecture is assumed to be i386
@end smallexample
@noindent Then, we tell GDB to attach to the waiting PintOS emulator:
@smallexample
(gdb) @strong{debugpintos}
0x0000fff0 in ?? ()
@end smallexample
@noindent Now we instruct GDB to continue the execution of PintOS by using the
command @code{continue} (or the abbreviation @code{c}):
@smallexample
(gdb) @strong{c}
Continuing.
@end smallexample
@noindent Now PintOS will continue and output:
@smallexample
PiLo hda1
Loading..........
Kernel command line: -q -mlfqs run mlfqs-load-1
PintOS booting with 3,968 kB RAM...
367 pages available in kernel pool.
367 pages available in user pool.
Calibrating timer... 838,041,600 loops/s.
Boot complete.
Executing 'mlfqs-load-1':
(mlfqs-load-1) begin
(mlfqs-load-1) spinning for up to 45 seconds, please wait...
@end smallexample
@noindent
... until it gets stuck due to the bug in the code.
We hit @key{Ctrl+C} in the debugger window to stop PintOS.
@smallexample
Program received signal SIGINT, Interrupt.
intr_get_level () at ../../threads/interrupt.c:66
(gdb)
@end smallexample
@noindent
The thread that was running when we stopped PintOS happened to be the main
thread. If we run @code{backtrace}, it shows this backtrace:
@smallexample
(gdb) @strong{bt}
#0 intr_get_level () at ../../threads/interrupt.c:66
#1 0xc0021103 in intr_enable () at ../../threads/interrupt.c:90
#2 0xc0021150 in intr_set_level (level=INTR_ON) at ../../threads/interrupt.c:83
#3 0xc0023422 in timer_ticks () at ../../devices/timer.c:75
#4 0xc002343d in timer_elapsed (then=23) at ../../devices/timer.c:84
#5 0xc002aabf in test_mlfqs_load_1 () at ../../tests/threads/mlfqs-load-1.c:33
#6 0xc002b610 in run_test (name=0xc0007d4c "mlfqs-load-1") at ../../tests/devices/tests.c:72
#7 0xc00201a2 in run_task (argv=0xc00349e8 <argv+8>) at ../../threads/init.c:290
#8 0xc0020687 in run_actions (argv=0xc00349e8 <argv+8>) at ../../threads/init.c:340
#9 main () at ../../threads/init.c:133
@end smallexample
@noindent
Not terribly useful. What we really like to know is what's up with the
other thread (or threads). Since we keep all threads in a linked list
called @code{all_list}, linked together by a @struct{list_elem} member
named @code{allelem}, we can use the @code{btthreadlist} macro.
@code{btthreadlist} iterates through the list of threads and prints the
backtrace for each thread:
@smallexample
(gdb) @strong{btthreadlist &all_list allelem}
pintos-debug: dumping backtrace of thread 'main' @@0xc000e000
#0 intr_get_level () at ../../threads/interrupt.c:66
#1 0xc0021103 in intr_enable () at ../../threads/interrupt.c:90
#2 0xc0021150 in intr_set_level (level=INTR_ON) at ../../threads/interrupt.c:83
#3 0xc0023422 in timer_ticks () at ../../devices/timer.c:75
#4 0xc002343d in timer_elapsed (then=23) at ../../devices/timer.c:84
#5 0xc002aabf in test_mlfqs_load_1 () at ../../tests/threads/mlfqs-load-1.c:33
#6 0xc002b610 in run_test (name=0xc0007d4c "mlfqs-load-1") at ../../tests/devices/tests.c:72
#7 0xc00201a2 in run_task (argv=0xc00349e8 <argv+8>) at ../../threads/init.c:290
#8 0xc0020687 in run_actions (argv=0xc00349e8 <argv+8>) at ../../threads/init.c:340
#9 main () at ../../threads/init.c:133
pintos-debug: dumping backtrace of thread 'idle' @@0xc0103000
#0 0xc0020dc5 in schedule () at ../../threads/thread.c:579
#1 0xc0020e01 in thread_block () at ../../threads/thread.c:235
#2 0xc0020e6d in idle (idle_started_=0xc000ef7c) at ../../threads/thread.c:414
#3 0xc0020efc in kernel_thread (function=0xc0020e45 <idle>, aux=0xc000ef7c)
at ../../threads/thread.c:439
#4 0x00000000 in ?? ()
@end smallexample
@noindent
In this case, there are only two threads, the main thread and the idle
thread. The kernel stack pages (to which the @struct{thread} points)
are at @t{0xc000e000} and @t{0xc0103000}, respectively. The main thread
was in @func{timer_elapsed}, called from @code{test_mlfqs_load_1} when stopped.
Knowing where threads are can be tremendously useful, for instance
when diagnosing deadlocks or unexplained hangs.
@deffn {GDB Macro} loadusersymbols
You can also use GDB to debug a user program running under PintOS.
To do that, use the @code{loadusersymbols} macro to load the program's
symbol table:
@example
loadusersymbols @var{program}
@end example
@noindent
where @var{program} is the name of the program's executable (in the host
file system, not in the PintOS file system). For example, you may issue:
@smallexample
(gdb) @strong{loadusersymbols tests/userprog/exec-multiple}
add symbol table from file "tests/userprog/exec-multiple" at
.text_addr = 0x80480a0
(gdb)
@end smallexample
After this, you should be
able to debug the user program the same way you would the kernel, by
placing breakpoints, inspecting data, etc. Your actions apply to every
user program running in PintOS, not just to the one you want to debug,
so be careful in interpreting the results: GDB does not know
which process is currently active (because that is an abstraction
the PintOS kernel creates). Also, a name that appears in
both the kernel and the user program will actually refer to the kernel
name. (The latter problem can be avoided by giving the user executable
name on the GDB command line, instead of @file{kernel.o}, and then using
@code{loadusersymbols} to load @file{kernel.o}.)
@code{loadusersymbols} is implemented via GDB's @code{add-symbol-file}
command.
@end deffn
@node GDB FAQ
@subsection FAQ
@table @asis
@item GDB can't connect to QEMU (Error: localhost:1234: Connection refused)
If the @command{target remote} command fails, then make sure that both
GDB and @command{pintos} are running on the same machine by
running @command{hostname} in each terminal. If the names printed
differ, then you need to open a new terminal for GDB on the
machine running @command{pintos}.
@item GDB doesn't recognize any of the macros.
If you start GDB with @command{pintos-gdb}, it should load the PintOS
macros automatically. If you start GDB some other way, then you must
issue the command @code{source @var{pintosdir}/src/misc/gdb-macros},
where @var{pintosdir} is the root of your PintOS directory, before you
can use them.
@item Can I debug PintOS with DDD?
Yes, you can. DDD invokes GDB as a subprocess, so you'll need to tell
it to invokes @command{pintos-gdb} instead:
@example
ddd --gdb --debugger pintos-gdb
@end example
@item Can I use GDB inside Emacs?
Yes, you can. Emacs has special support for running GDB as a
subprocess. Type @kbd{M-x gdb} and enter your @command{pintos-gdb}
command at the prompt. The Emacs manual has information on how to use
its debugging features in a section titled ``Debuggers.''
@end table
@node Triple Faults
@section Triple Faults
When a CPU exception handler, such as a page fault handler, cannot be
invoked because it is missing or defective, the CPU will try to invoke
the ``double fault'' handler. If the double fault handler is itself
missing or defective, that's called a ``triple fault.'' A triple fault
causes an immediate CPU reset.
Thus, if you get yourself into a situation where the machine reboots in
a loop, that's probably a ``triple fault.'' In a triple fault
situation, you might not be able to use @func{printf} for debugging,
because the reboots might be happening even before everything needed for
@func{printf} is initialized.
Currently, the only option is ``debugging by infinite loop.''
Pick a place in the PintOS code, insert the infinite loop
@code{for (;;);} there, and recompile and run. There are two likely
possibilities:
@itemize @bullet
@item
The machine hangs without rebooting. If this happens, you know that
the infinite loop is running. That means that whatever caused the
reboot must be @emph{after} the place you inserted the infinite loop.
Now move the infinite loop later in the code sequence.
@item
The machine reboots in a loop. If this happens, you know that the
machine didn't make it to the infinite loop. Thus, whatever caused the
reboot must be @emph{before} the place you inserted the infinite loop.
Now move the infinite loop earlier in the code sequence.
@end itemize
If you move around the infinite loop in a ``binary search'' fashion, you
can use this technique to pin down the exact spot that everything goes
wrong. It should only take a few minutes at most.
@node Debugging Tips
@section Tips
The page allocator in @file{threads/palloc.c} and the block allocator in
@file{threads/malloc.c} clear all the bytes in memory to
@t{0xcc} at time of free. Thus, if you see an attempt to
dereference a pointer like @t{0xcccccccc}, or some other reference to
@t{0xcc}, there's a good chance you're trying to reuse a page that's
already been freed. Also, byte @t{0xcc} is the CPU opcode for ``invoke
interrupt 3,'' so if you see an error like @code{Interrupt 0x03 (#BP
Breakpoint Exception)}, then PintOS tried to execute code in a freed page or
block.

108
doc/devel.texi Normal file
View File

@@ -0,0 +1,108 @@
@node Development Tools
@appendix Development Tools
Here are some tools that you might find useful while developing code.
@menu
* Tags::
* cscope::
* Git::
@ifset recommendvnc
* VNC::
@end ifset
@ifset recommendcygwin
* Cygwin::
@end ifset
@end menu
@node Tags
@section Tags
Tags are an index to the functions and global variables declared in a
program. Many editors, including Emacs and @command{vi}, can use
them. The @file{Makefile} in @file{pintos-ic/src} produces Emacs-style
tags with the command @code{make TAGS} or @command{vi}-style tags with
@code{make tags}.
In Emacs, use @kbd{M-.} to follow a tag in the current window,
@kbd{C-x 4 .} in a new window, or @kbd{C-x 5 .} in a new frame. If
your cursor is on a symbol name for any of those commands, it becomes
the default target. If a tag name has multiple definitions, @kbd{M-0
M-.} jumps to the next one. To jump back to where you were before
you followed the last tag, use @kbd{M-*}.
@node cscope
@section cscope
The @command{cscope} program also provides an index to functions and
variables declared in a program. It has some features that tag
facilities lack. Most notably, it can find all the points in a
program at which a given function is called.
The @file{Makefile} in @file{pintos-ic/src} produces @command{cscope}
indexes when it is invoked as @code{make cscope}. Once the index has
been generated, run @command{cscope} from a shell command line; no
command-line arguments are normally necessary. Then use the arrow
keys to choose one of the search criteria listed near the bottom of
the terminal, type in an identifier, and hit @key{Enter}.
@command{cscope} will then display the matches in the upper part of
the terminal. You may use the arrow keys to choose a particular
match; if you then hit @key{Enter}, @command{cscope} will invoke the
default system editor@footnote{This is typically @command{vi}. To
exit @command{vi}, type @kbd{: q @key{Enter}}.} and position the
cursor on that match. To start a new search, type @key{Tab}. To exit
@command{cscope}, type @kbd{Ctrl-d}.
Emacs and some versions of @command{vi} have their own interfaces to
@command{cscope}. For information on how to use these interface,
visit @url{http://cscope.sourceforge.net, the @command{cscope} home
page}.
@node Git
@section Git
Git is a version-control system. That is, you can use it to keep
track of multiple versions of files. The idea is that you do some
work on your code and test it, then commit it into the version-control
system. If you decide that the work you've done since your last
commit is no good, you can easily revert to the last version.
Furthermore, you can retrieve any old version of your code
as of some given day and time. The version control logs tell you who
made changes and when.
Whilst Git may not be everyone's preferred version control system, it's
free, has a wealth of documentation, and is easy to install on most
Unix-like environments.
For more information, visit the @uref{https://www.git-scm.com/, , Git
home page}.
@include localgitinstructions.texi
@ifset recommendvnc
@node VNC
@section VNC
VNC stands for Virtual Network Computing. It is, in essence, a remote
display system which allows you to view a computing ``desktop''
environment not only on the machine where it is running, but from
anywhere on the Internet and from a wide variety of machine
architectures. It is already installed on the lab machines.
For more information, look at the @uref{http://www.realvnc.com/, , VNC
Home Page}.
@end ifset
@ifset recommendcygwin
@node Cygwin
@section Cygwin
@uref{http://cygwin.com/, ,Cygwin} provides a Linux-compatible environment
for Windows. It includes ssh client and an X11 server, Cygwin/X. If your
primary work environment is Windows, you will find Cygwin/X extremely
useful for these tasks. Install Cygwin/X, then start the X server
and open a new xterm. The X11 server also allows you to run pintos while
displaying the qemu-emulated console on your Windows desktop.
@end ifset
@localdevelopmenttools{}

51
doc/devices.tmpl Normal file
View File

@@ -0,0 +1,51 @@
+----------------------+
| OS 211 |
| TASK 0: ALARMCLOCK |
| DESIGN DOCUMENT |
+----------------------+
---- PRELIMINARIES ----
>> If you have any preliminary comments on your submission, or notes for the
>> markers, please give them here.
>> Please cite any offline or online sources you consulted while preparing your
>> submission, other than the Pintos documentation, course text, lecture notes
>> and course staff.
ALARM CLOCK
===========
---- DATA STRUCTURES ----
>> A1: (2 marks)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration.
>> Identify the purpose of each in roughly 25 words.
---- ALGORITHMS ----
>> A2: (2 marks)
>> Briefly describe what happens in a call to timer_sleep(), including the
>> actions performed by the timer interrupt handler on each timer tick.
>> A3: (2 marks)
>> What steps are taken to minimize the amount of time spent in the timer
>> interrupt handler?
---- SYNCHRONIZATION ----
>> A4: (1 mark)
>> How are race conditions avoided when multiple threads call timer_sleep()
>> simultaneously?
>> A5: (1 mark)
>> How are race conditions avoided when a timer interrupt occurs during a call
>> to timer_sleep()?
---- RATIONALE ----
>> A6: (2 marks)
>> Why did you choose this design?
>> In what ways is it superior to another design you considered?

59
doc/doc.texi Normal file
View File

@@ -0,0 +1,59 @@
@node Task Documentation
@appendix Task Documentation
This chapter presents a sample assignment and a filled-in design
document for one possible implementation. Its purpose is to give you an
idea of what we expect to see in your own design documents.
@menu
* Sample Assignment::
* Sample Design Document::
@end menu
@node Sample Assignment
@section Sample Assignment
Implement @func{thread_join}.
@deftypefun void thread_join (tid_t @var{tid})
Blocks the current thread until thread @var{tid} exits. If @var{A} is
the running thread and @var{B} is the argument, then we say that
``@var{A} joins @var{B}.''
Incidentally, the argument is a thread id, instead of a thread pointer,
because a thread pointer is not unique over time. That is, when a
thread dies, its memory may be, whether immediately or much later,
reused for another thread. If thread @var{A} over time had two children
@var{B} and @var{C} that were stored at the same address, then
@code{thread_join(@var{B})} and @code{thread_join(@var{C})} would be
ambiguous.
A thread may only join its immediate children. Calling
@func{thread_join} on a thread that is not the caller's child should
cause the caller to return immediately. Children are not ``inherited,''
that is, if @var{A} has child @var{B} and @var{B} has child @var{C},
then @var{A} always returns immediately should it try to join @var{C},
even if @var{B} is dead.
A thread need not ever be joined. Your solution should properly free
all of a thread's resources, including its @struct{thread},
whether it is ever joined or not, and regardless of whether the child
exits before or after its parent. That is, a thread should be freed
exactly once in all cases.
Joining a given thread is idempotent. That is, joining a thread
multiple times is equivalent to joining it once, because it has already
exited at the time of the later joins. Thus, joins on a given thread
after the first should return immediately.
You must handle all the ways a join can occur: nested joins (@var{A}
joins @var{B}, then @var{B} joins @var{C}), multiple joins (@var{A}
joins @var{B}, then @var{A} joins @var{C}), and so on.
@end deftypefun
@node Sample Design Document
@section Sample Design Document
@example
@include sample.tmpl.texi
@end example

157
doc/installation.texi Normal file
View File

@@ -0,0 +1,157 @@
@node Installing PintOS
@appendix Installing PintOS
This chapter explains how to install a PintOS development environment on your own machine.
We assume that you have already cloned your pintos git repo onto your machine.
If you are using a PintOS development environment that has been set up by someone else,
you should not need to read this chapter or follow any of these instructions.
The PintOS development environment is targeted at Unix-like systems.
It has been most extensively tested on GNU/Linux, in particular the Debian and Ubuntu distributions, and Solaris.
It is not designed to install under any form of Windows.
@menu
* Mac Specific Initial Set-up::
* Prerequisites::
* Installation::
@end menu
@node Mac Specific Initial Set-up
@section Mac Specific Initial Set-up
This first section is intended to help Mac users prepare to set-up PintOS so that they can coexist with LabTS and your Linux-using friends,
without any on-going hassle.
If you are not attempting to install PintOS on a Mac, then please skip ahead to the next section.
To prepare your Mac for PintOS, you will need to preform the following initial set-up steps:
@itemize
@item Download and unpack a prepared selection of cross-compiled GCC binaries from:
@uref{https://www.doc.ic.ac.uk/~mjw03/OSLab/mac-i686-elf-gcc-binaries.tar}.@*
You can also install these binaries onto your Mac yourself if you prefer.
@item Add the unpacked GCC binaries to your path with a line like:@*
@code{export PATH=$PATH:/your/local/path/here/mac-i686-elf-gcc-binaries/bin}
@end itemize
You should now be ready to follow the remaining instructions in this appendix.
@node Prerequisites
@section Prerequisites
Before attempting to install a PintOS development environment, you should check that the following prerequisites,
on top of standard Unix utilities, are available on your system:
@itemize @bullet
@item
@strong{Required:} @uref{http://gcc.gnu.org/, GCC}.
Version 5.4 or later is preferred.
Version 4.0 or later should work.
If the host machine has an 80@var{x}86 processor (32-bit or 64-bit), then GCC should be available via the command @command{gcc};
otherwise, an 80@var{x}86 cross-compiler should be available via the command @command{i386-elf-gcc}.
If you need a GCC cross-compiler, but one is not already installed on your system, then you will need to search online for an up-to-date installation guide.
@item
@strong{Required:} @uref{http://www.gnu.org/software/binutils/, GNU binutils}.
PintOS uses the Unix utilities @command{addr2line}, @command{ar}, @command{ld}, @command{objcopy}, and @command{ranlib}.
If the host machine does not have an 80@var{x}86 processor, then versions targeting 80@var{x}86 should be available to install with an @samp{i386-elf-} prefix.
@item
@strong{Required:} @uref{http://www.perl.org, Perl}.
Version 5.20.0 or later is preferred.
Version 5.6.1 or later should work.
@item
@strong{Required:} @uref{http://www.gnu.org/software/make/, GNU make}.
Version 4.0 or later is preferred.
Version 3.80 or later should work.
@item
@strong{Required:} @uref{http://fabrice.bellard.free.fr/qemu/, QEMU}.
The QEMU emulator required to run PintOS is @command{qemu-system-i386} which is part of the @command{qemu-system} package on most modern Unix platforms.
We recommend using version 2.10 or later, but at least version 2.5.
@item
@strong{Recommended:} @uref{http://www.gnu.org/software/gdb/, GDB}.
GDB is helpful in debugging (@pxref{GDB}).
If the host machine is not an 80@var{x}86, a version of GDB targeting 80@var{x}86 should be available as @samp{i386-elf-gdb}.
@item
@strong{Recommended:} @uref{http://www.x.org/, X}.
Being able to use an X server makes the virtual machine feel more like a physical machine, but it is not strictly necessary.
@item
@strong{Optional:} @uref{http://www.gnu.org/software/texinfo/, Texinfo}.
Version 4.5 or later.
Texinfo is required to build the PDF version of the main PintOS documentation.
@item
@strong{Optional:} @uref{http://www.tug.org/, @TeX{}}.
@TeX{} is required to build the PDF versions of the support documentation.
@item
@strong{Optional:} @uref{http://www.vmware.com/, VMware Player}.
This is another emulation platform that can be used to run PintOS instead of QEMU.
You will need to search online for an up-to-date installation guide.
@end itemize
@node Installation
@section Installation
Once you have checked that the prerequisites are available,
follow these instructions to install a PintOS development environment:
@enumerate 1
@item
Compile the PintOS utilities in @file{src/utils}.
To do this, open a terminal in the @file{src/utils} directory of your PintOS project and run @command{make}.
@item
Install scripts from @file{src/utils}.
This easiest way to do this is to reconfigure your system's @env{PATH} to include the @file{src/utils} directory of your PintOS project.
You can instead copy the files
@file{backtrace},
@file{pintos},
@file{pintos-gdb},
@file{pintos-mkdisk},
@file{pintos-set-cmdline},
@file{Pintos.pm}
and
@file{squish-pty}
into your system's default @env{PATH}.
If your Perl is older than version 5.8.0, then you will also need to install @file{setitimer-helper}; otherwise, it is unneeded.
@item
Install the GDB macros from @file{src/misc/gdb-macros}.
The easiest way to do this is to use a text editor to update your previously installed copy of @file{pintos-gdb}
so that the definition of @env{GDBMACROS} points to your local @file{gdb-macros} file.
You can instead copy the @file{pintos-gdb} file into a system directory of your choice,
but you will still need to update the definition of @env{GDBMACROS} in your installed copy of @file{pintos-gdb}.
Test the GDB macro installation by running @command{pintos-gdb} without any arguments.
If it does not complain about missing @file{gdb-macros}, it is installed correctly.
@item
PintOS should now be ready for use.
To test your installation, open a terminal in the @file{src/devices} directory of your PintOS project and run @command{make check}.
This will run the tests for Task 0 and should take no more than a few minutes.
@item
@strong{Optional:} Install alternative emulation software.
To support VMware Player, install @file{squish-unix} (from the @file{src/utils} directory); otherwise it is unneeded.
@item
@strong{Optional:} Build the PintOS documentation.
Open a terminal in the @file{doc} directory of your PintOS project and run @command{make dist}.
This will create a @file{WWW} subdirectory within @file{doc} that contains both HTML and PDF versions of the documentation,
plus the design document templates and various hardware specifications referenced by the documentation.
@end enumerate

564
doc/intro.texi Normal file
View File

@@ -0,0 +1,564 @@
@node Introduction
@chapter Introduction
Welcome to PintOS. PintOS is a simple operating system framework for
the 80@var{x}86 architecture. It supports kernel threads, loading and
running user programs, and a file system, but it implements all of
these in a very simple way. During the PintOS tasks, you and your
group will strengthen its support in two of these areas.
You will also add a virtual memory implementation.
PintOS could, theoretically, run on a regular IBM-compatible PC.
Unfortunately, it is impractical to supply every student
with a dedicated PC for use with PintOS. Therefore, we will be running PintOS
in a system simulator, that is, a program that simulates an 80@var{x}86
CPU and its peripheral devices accurately enough that unmodified operating
systems and software can run under it. In particular, we will be using the
@uref{http://fabrice.bellard.free.fr/qemu/, ,
QEMU} simulator. PintOS has also been tested with the
@uref{http://www.vmware.com/, , VMware Player}.
These tasks are hard. The PintOS exercise have a reputation of taking a lot of
time, and deservedly so. We will do what we can to reduce the workload, such
as providing a lot of support material, but there is plenty of
hard work that needs to be done. We welcome your
feedback. If you have suggestions on how we can reduce the unnecessary
overhead of assignments, cutting them down to the important underlying
issues, please let us know.
This version of the exercise has been adapted for use at Imperial College
London, and is significantly different to the original exercise designed at
Stanford University. It's recommended that you only use the Imperial version
of the documentation to avoid unnecessary confusion.
This chapter explains how to get started working with PintOS. You
should read the entire chapter before you start work on any of the
tasks.
@menu
* Getting Started::
* Testing::
* Submission::
* Grading::
* Legal and Ethical Issues::
* Acknowledgements::
* Trivia::
@end menu
@comment ----------------------------------------------------------------------
@node Getting Started
@section Getting Started
To get started, you'll have to log into a machine that PintOS can be
built on.
@localmachines{}
We will test your code on these machines, and the instructions given
here assume this environment. We do not have the manpower to provide support for installing
and working on PintOS on your own machine, but we provide instructions
for doing so nonetheless (@pxref{Installing PintOS}).
If you are using bash (the default shell for CSG-run machines), several PintOS
utilities will already be in your PATH. If you are not using bash on a CSG-run machine,
you will need to add these utilities manually.
@localpathsetup{}
@menu
* Source Tree Overview::
* Building PintOS::
* Running PintOS::
@end menu
@comment ----------------------------------------------------------------------
@node Source Tree Overview
@subsection Source Tree Overview
For Task 0 each student has been provided with a Git repository on the department's @code{GitLab}
server that contains the files needed for this exercise.
To obtain this initial skeleton repository you will need to clone it into your local workspace.
You can do this with the following command:
@example
git clone @value{localindivgitpath}
@end example
@noindent replacing @code{<login>} with your normal college login.
For the remaining tasks, each group will be provided with a Git repository on the department's @code{GitLab}
server that contains the files needed for the entire PintOS project.
To obtain this skeleton repository you will need to clone it into your local workspace.
You can do this with the following command:
@example
git clone @value{localgitpath}
@end example
@noindent replacing @code{<gnum>} with your group number, which can be found on the @code{GitLab} website.
You should work on the files in your local workspace, making regular commits back to the corresponding Git repository.
Your final submissions will be taken from these @code{GitLab} repositories, so make sure that you push your work to them correctly.
Let's take a look at what's inside the full PintOS repository.
Here's the directory structure that you should see in @file{pintos/src}:
@table @file
@item devices/
Source code for I/O device interfacing: keyboard, timer, disk, etc.
You will modify the timer implementation in task 0. Otherwise
you should have no need to change this code.
@item threads/
Source code for the base kernel, which you will modify in
task 1.
@item userprog/
Source code for the user program loader, which you will modify
in task 2.
@item vm/
An almost empty directory. You will implement virtual memory here in
task 3.
@item filesys/
Source code for a basic file system. You will use this file system
in tasks 2 and 3.
@item lib/
An implementation of a subset of the standard C library. The code in
this directory is compiled into both the PintOS kernel and, starting
from task 2, user programs that run under it. In both kernel code
and user programs, headers in this directory can be included using the
@code{#include <@dots{}>} notation. You should have little need to
modify this code.
@item lib/kernel/
Parts of the C library that are included only in the PintOS kernel.
This also includes implementations of some data types that you are
free to use in your kernel code: bitmaps, doubly linked lists, and
hash tables. In the kernel, headers in this
directory can be included using the @code{#include <@dots{}>}
notation.
@item lib/user/
Parts of the C library that are included only in PintOS user programs.
In user programs, headers in this directory can be included using the
@code{#include <@dots{}>} notation.
@item tests/
Tests for each task. You can modify this code if it helps you test
your submission, but we will replace it with the originals before we run
the tests.
@item examples/
Example user programs for use in tasks 2 and 3.
@item misc/
@itemx utils/
These files may come in handy if you decide to try working with PintOS
on your own machine. Otherwise, you can ignore them.
@end table
@comment ----------------------------------------------------------------------
@node Building PintOS
@subsection Building PintOS
As the next step, build the source code supplied for
the first task. First, @command{cd} into the @file{devices}
directory. Then, issue the @samp{make} command. This will create a
@file{build} directory under @file{devices}, populate it with a
@file{Makefile} and a few subdirectories, and then build the kernel
inside. The entire build should take less than 30 seconds.
@localcrossbuild{}
After the build has completed, you will find the following interesting files in the
@file{build} directory:
@table @file
@item Makefile
A copy of @file{pintos/src/Makefile.build}. It describes how to build
the kernel. @xref{Adding Source Files}, for more information.
@item kernel.o
Object file for the entire kernel. This is the result of linking
object files compiled from each individual kernel source file into a
single object file. It contains debug information, so you can run
GDB (@pxref{GDB}) or @command{backtrace} (@pxref{Backtraces}) on it.
@item kernel.bin
Memory image of the kernel, that is, the exact bytes loaded into
memory to run the PintOS kernel. This is just @file{kernel.o} with
debug information stripped out, which saves a lot of space, which in
turn keeps the kernel from bumping up against a @w{512 kB} size limit
imposed by the kernel loader's design.
@item loader.bin
Memory image for the kernel loader, a small chunk of code written in
assembly language that reads the kernel from disk into memory and
starts it up. It is exactly 512 bytes long, a size fixed by the
PC BIOS.
@end table
Subdirectories of @file{build} contain object files (@file{.o}) and
dependency files (@file{.d}), both produced by the compiler. The
dependency files tell @command{make} which source files need to be
recompiled when other source or header files are changed.
@comment ----------------------------------------------------------------------
@node Running PintOS
@subsection Running PintOS
We've supplied a program for conveniently running PintOS in a simulator,
called @command{pintos}. In the simplest case, you can invoke
@command{pintos} as @code{pintos @var{argument}@dots{}}. Each
@var{argument} is passed to the PintOS kernel for it to act on.
Try it out. First @command{cd} into the newly created @file{build}
directory. Then issue the command @code{pintos run alarm-multiple},
which passes the arguments @code{run alarm-multiple} to the PintOS
kernel. In these arguments, @command{run} instructs the kernel to run a
test and @code{alarm-multiple} is the test to run.
PintOS boots and runs the @code{alarm-multiple} test
program, which outputs a few screenfulls of text.
You can log serial output to a file by redirecting at the
command line, e.g.@: @code{pintos run alarm-multiple > logfile}.
The @command{pintos} program offers several options for configuring the
simulator or the virtual hardware. If you specify any options, they
must precede the commands passed to the PintOS kernel and be separated
from them by @option{--}, so that the whole command looks like
@code{pintos @var{option}@dots{} -- @var{argument}@dots{}}. Invoke
@code{pintos} without any arguments to see a list of available options.
You can run the simulator with a debugger (@pxref{GDB}). You can also set the
amount of memory to give the VM.
The PintOS kernel has commands and options other than @command{run}.
These are not very interesting for now, but you can see a list of them
using @option{-h}, e.g.@: @code{pintos -h}.
@comment ----------------------------------------------------------------------
@page
@node Testing
@section Testing
To help you ensure that your code will compile and run as expected in our testing environment we have provided you with a Lab Testing Service: LabTS. LabTS will clone your git repository and run several automated test process over your work. This will happen automatically when you submit your work, but can also be requested during the course of each task.
You can access the LabTS webspages at @file{https://teaching.doc.ic.ac.uk/labts}.
Note that you will be required to log-in with your normal college username and password.
If you click through to the @code{pintos} exercise you will see a list of the different versions of your work that you have pushed.
Next to each commit you will see a button that will allow you to request that this version of your work is run through the automated test process for the currently viewed milestone. If you click on this button your work will be tested (this may take a few minutes) and the results will appear om the relevant column.
@cartouche
@noindent@strong{Important:} submitted code that fails to compile and run on LabTS will be awarded @strong{0 marks} for the automated tests grade!
You should be periodically (but not continuously) testing your code on LabTS.
If you are experiencing problems with the compilation or execution of your code then please seek help/advice as soon as possible.
@end cartouche
Your automated test result grade will be based on our test suite.
Each task has several tests, each of which has a name beginning with @file{tests}.
To completely test your submission, invoke @code{make check} from the task @file{build} directory.
This will build and run each test and print a ``pass'' or ``fail'' message for each one. When a test fails,
@command{make check} also prints some details of the reason for failure.
After running all the tests, @command{make check} also prints a summary of the test results.
You can run @command{make grade} to see the automated test results output in the same format as will be presented to the markers.
You can also run individual tests one at a time.
A given test @file{@var{t}} writes its output to @file{@var{t}.output},
then a script scores the output as ``pass'' or ``fail'' and writes the verdict to @file{@var{t}.result}.
To run and grade a single test,
@command{make} the @file{.result} file explicitly from the @file{build} directory, e.g.@: @code{make tests/devices/alarm-multiple.result}.
If @command{make} says that the test result is up-to-date, but you want to re-run it anyway,
either run @code{make clean} or delete the @file{.output} file by hand.
By default, each test provides feedback only at completion, not during its run.
If you prefer, you can observe the progress of each test by specifying @option{VERBOSE=1} on the @command{make} command line,
as in @code{make check VERBOSE=1}.
You can also provide arbitrary options to the @command{pintos} run by the tests with @option{PINTOSOPTS='@dots{}'}.
All of the tests and related files can be found in @file{pintos/src/tests}.
Before we test your submission, we will replace the contents of this directory by a pristine, unmodified copy, to ensure that the correct tests are used.
Thus, you can freely modify any of the tests if that helps in your debugging, but we will run our automated tests on the originals.
All software has bugs, so it is possible that some of our tests may be flawed.
If you think a test failure is a bug in the test, not a bug in your code, please point it out.
We will look at it and fix it if necessary.
Please don't try to take advantage of our generosity in giving out the full test suite.
Your code has to work properly in the general case and not just for the test cases we supply.
We will be asking questions about the general case during the code review sessions, so you won't be able to get away with it.
For example, it would be unacceptable to explicitly base the kernel's behaviour on the name of the running test case.
Such attempts to side-step the test cases will be spotted during the code review process and will receive no credit.
If you think your solution may be in a gray area here, please ask us about it.
@menu
* Debugging versus Testing::
@end menu
@comment ----------------------------------------------------------------------
@node Debugging versus Testing
@subsection Debugging versus Testing
The QEMU simulator you will be using to run PintOS only supports real-time
simulations. This has ramifications with regards to both testing and debugging.
Whilst reproducibility is in general extremely useful for debugging, running PintOS in QEMU is not necessarily deterministic.
You should keep this in mind when testing for bugs in your code.
In each run, timer interrupts will come at irregularly spaced intervals, meaning that bugs may appear and disappear with repeated tests.
Therefore, it's very important that you run your tests at a least few times.
No number of runs can guarantee that your synchronisation is perfect,
but the more you do, the more confident you can be that your code doesn't have major flaws.
@cartouche
@noindent@strong{Important:} the PintOS kernel is written for a single-cored CPU,
which helps to limit the possible interleavings of concurrently executing threads.
However, as you have no control over the occurence of timer interrupts,
you will still need to consider the implications of your code being interrupted at almost any arbitrary point.
Much of our assessment will be conducted as a ``demonic'' scheduler that chooses the ``worst-case'' possibilities.
@end cartouche
@comment ----------------------------------------------------------------------
@node Submission
@section Submission
As you work, you should @code{add}, @code{commit} and @code{push} your changes to your git repository.
Your @code{GitLab} repository should contain the source code, header files and make files for your OS.
Prior to submission, you should check the state of your @code{GitLab} repository using the @code{LabTS} webpages at
@file{https://teaching.doc.ic.ac.uk/labts}.
If you click through to the @code{pintos} exercise you will see a list of the different versions of your work that you have pushed to the master branch of your repository.
Next to each commit you will see a link to that commit on @code{GitLab} as well as a button to submit that version of your code for assessment.
You should submit the version of your code that you consider to be "final" for each task.
You can change this later, as usual, by submitting a different version of your code.
The submission button on LabTS will be replaced with a green confirmation message if the submission has been sucessful.
For each @code{pintos} task you will also need to submit a design document (@code{designT#.pdf}) directly to Scientia.
Your submission must be signed off as a group on Scientia in the usual way.
@comment ----------------------------------------------------------------------
@node Grading
@section Grading
We will grade each @code{pintos} task over 3 catagories:
@itemize
@item @strong{automated tests}: your score from the automated test results.
@item @strong{code review}: an assessment of your design quality and efficiency.
@item @strong{design document}: your answers to the task's design document questions.
@end itemize
The marks for each @code{pintos} task will contribute to both your @value{coursenumber} Operating Systems coursework mark and your @value{labnumber} Computing Practical 2 exercises mark.
For @code{pintos} task 0, part A will make up all of the task's Operating Systems coursework grade, while part B will make up all of the task's Computing Practical 2 grade.
For all other @code{pintos} tasks, the automated tests will count for 40% of each task's Computing Practical 2 grade with the code review making up the other 60%.
The design document will count for 100% of the Operating Systems coursework grade for each of these tasks.
Note that some of the automated tests may be zero-weighted. These tests help us to identify likely design issues in your code and will probably affect your code review mark.
The weighting of the @code{pintos} tasks is 10%, 20%, 30% and 40% for each of task 0, task 1, task 2 and task 3 respectively.
JMC students are not assessed on task 3, but have the same relative weighting for task 0, task 1 and task 2.
@menu
* Design::
@end menu
@comment ----------------------------------------------------------------------
@node Design
@subsection Design
We will judge your design based on the design document and the source code that you submit.
We will read your entire design document and much of your source code.
@cartouche
@noindent@strong{Important:} Don't forget that design quality and efficiency will account for 60% of each task's @value{labnumber} Computing Practical 2 grade
and that the design documents will make up your entire @value{coursenumber} Operating Systems coursework mark.
It is, therefore, better to spend a day or two writing a good design document and thinking about the efficiency and edge-cases of your code,
than it is to spend that time trying to get the last 5% of the points for the automated tests
and then having to rush through writing the design document in the last 15 minutes.
@end cartouche
@menu
* Design Document::
* Source Code::
@end menu
@comment ----------------------------------------------------------------------
@node Design Document
@subsubsection Design Document
We will provide you with a design document template for each task.
For each significant part of a task, the template asks questions in four areas:
@table @strong
@item Data Structures
The instructions for this section are always the same:
@quotation
Copy here the declaration of each new or changed @code{struct} or @code{struct} member, global or static variable, @code{typedef}, or enumeration.
Identify the purpose of each in roughly 25 words.
@end quotation
The first part is mechanical.
Just copy new or modified declarations into the design document to highlight for us the actual changes to data structures.
Each declaration should include the comment that should accompany it in the source code (see below).
We also ask for a very brief description of the purpose of each new or changed data structure.
The suggestion of 25 words is a guideline intended to save your time and avoid duplication with later areas of the design document.
@item Algorithms
This is where you tell us how your code works, through questions that probe your understanding of your code.
We might not be able to easily figure it out from the code alone, because many creative solutions exist for most OS problems.
Help us out a little.
Your answers should be at a level below the high level description of requirements given in the assignment.
We have read the assignment too, so it is unnecessary to repeat or rephrase what is stated there.
On the other hand, your answers should be at a level above the low level of the code itself.
Don't give a line-by-line run-down of what your code does.
Instead, use your answers to explain how your code works to implement the requirements.
@item Synchronization
An operating system kernel is a complex, multithreaded program, in which synchronizing multiple threads can be difficult.
This section asks about how you chose to synchronize this particular type of activity.
@item Rationale
Whereas the other sections primarily ask ``what'' and ``how,'' the rationale section concentrates on ``why''.
This is where we ask you to justify some of your design decisions, by explaining why the choices you made are better than alternatives you considered.
You may be able to state these justifications in terms of time and space complexity, which can be made as rough or informal arguments (formal language or proofs are unnecessary).
@end table
Any incomplete, evasive, or non-responsive answers to design document questions or those that stray from the provided template without good reason may be penalised.
Additionally, any design docuement that does not match the reality of your implementation may be penalised unless any descrepencies are clearly stated and explained.
Incorrect capitalization, punctuation, spelling, or grammar may also cost points if this impedes our reading of your design document.
@xref{Task Documentation}, for an example design document for a fictitious task.
@cartouche
@noindent@strong{Important:} You should carefully read the design document for a task before you begin writing any code.
The questions we ask should help you identify some of the tricky corner cases that your implementation will be expected to handle.
@end cartouche
@comment ----------------------------------------------------------------------
@node Source Code
@subsubsection Source Code
Your design will also be judged by reviewing your source code with you during interactive code review sessions.
We will typically look at the differences between the original PintOS source tree and your submission,
based on the output of a command like @code{diff -urpb pintos.orig pintos.submitted} or reviewing the Git commits directly on @code{GitLab}.
We will try to match up your description of the design with the code submitted.
Important discrepancies between the description and the actual code will be penalised, as will be any bugs we find by spot checks during the code review sessions.
The most important aspects of source code design are those that specifically relate to the operating system issues at stake in the task.
It is important that you consider the efficiency of your operating system design choices, but other issues are much more important.
For example, multiple PintOS design problems call for a ``priority queue'', that is,
a dynamic collection from which the minimum (or maximum) item can quickly be extracted.
Fast priority queues can be implemented many ways, but we do not expect you to build a fancy data structure even if it might improve performance.
Instead, you are welcome to use a linked list (and PintOS even provides one with convenient functions for sorting and finding minimums and maximums).
PintOS is written in a consistent style.
Your additions and modifications do not have to be in the same style as the existing PintOS source files,
but you should ensure that your code style is self-consistent.
There should not be a patchwork of different styles that makes it obvious that three or four different people wrote the code.
Use horizontal and vertical white space to make code readable.
Add a brief comment on every structure, structure member, global or static variable, typedef, enumeration, and function definition.
Use phase-level comments within fuctions to help explain longer, or more complicated, behaviour.
Update existing comments as you modify code.
Don't comment out or use the preprocessor to ignore blocks of code (instead, remove it entirely - remember you have Git if you need to get it back).
Use assertions to document key invariants.
Decompose code into functions for clarity.
Code that is difficult to understand because it violates these or other ``common sense'' software engineering practices will be penalised during the code review sessions.
In the end, remember your audience.
Code is written primarily to be read by humans.
It has to be acceptable to the compiler too, but the compiler doesn't care about how it looks or how well it is written.
@xref{Coding Standards} for additional guidance.
@comment ----------------------------------------------------------------------
@page
@node Legal and Ethical Issues
@section Legal and Ethical Issues
PintOS is distributed under a liberal license that allows free use, modification, and distribution of this material.
Students and others who work on PintOS own the code that they write and may use it for any purpose.
PintOS comes with NO WARRANTY, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@xref{License}, for details of the license and lack of warranty.
@localhonorcodepolicy{}
@comment ----------------------------------------------------------------------
@node Acknowledgements
@section Acknowledgements
The PintOS core kernel and this documentation were originally written by Ben
Pfaff @email{blp@@cs.stanford.edu}.
Additional features were contributed by Anthony Romano
@email{chz@@vt.edu}.
The GDB macros supplied with PintOS were written by Godmar Back
@email{gback@@cs.vt.edu}, and their documentation is adapted from his
work.
The original structure and form of PintOS was inspired by the Nachos
instructional operating system from the University of California,
Berkeley (@bibref{Christopher}).
The PintOS tasks and documentation originated with those designed for
Nachos by current and former CS 140 teaching assistants at Stanford
University, including at least Yu Ping, Greg Hutchins, Kelly Shaw, Paul
Twohey, Sameer Qureshi, and John Rector.
Example code for monitors (@pxref{Monitors}) is
from classroom slides originally by Dawson Engler and updated by Mendel
Rosenblum.
@localcredits{}
@comment ----------------------------------------------------------------------
@node Trivia
@section Trivia
PintOS originated as a replacement for Nachos with a similar design.
Since then PintOS has greatly diverged from the Nachos design.
PintOS differs from Nachos in two important ways:
@itemize
@item First, PintOS runs on real or simulated 80@var{x}86 hardware, but Nachos runs as a process on a host operating system.
@item Second, PintOS is written in C like most real-world operating systems, but Nachos is written in C++.
@end itemize
@noindent@strong{So, why the name ``PintOS''?}
@itemize
@item First, like nachos, pinto beans are a common Mexican food.
@item Second, PintOS is small and a ``pint'' is a small amount.
@item Third, like drivers of the eponymous car, students are likely to have trouble with blow-ups.
@end itemize

62
doc/license.texi Normal file
View File

@@ -0,0 +1,62 @@
@node License
@appendix License
PintOS, including its documentation, is subject to the following
license:
@quotation
Copyright @copyright{} 2004, 2005, 2006 Board of Trustees, Leland
Stanford Jr.@: University. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@end quotation
A few individual files in PintOS were originally derived from other
projects, but they have been extensively modified for use in PintOS.
The original code falls under the original license, and modifications
for PintOS are additionally covered by the PintOS license above.
In particular, code derived from Nachos is subject to the following
license:
@quotation
Copyright @copyright{} 1992-1996 The Regents of the University of California.
All rights reserved.
Permission to use, copy, modify, and distribute this software
and its documentation for any purpose, without fee, and
without written agreement is hereby granted, provided that the
above copyright notice and the following two paragraphs appear
in all copies of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO
ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE
AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN ``AS IS''
BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
@end quotation

View File

@@ -0,0 +1,96 @@
@c
@c Instructions on how to set up a group environment, permissions,
@c Git repository, dealing with issues etc.
@c
@c While some of the discussion may apply to more than one environment,
@c no attempt was made to untangle and split the discussion.
@c
@menu
* Setting Up Git::
* Using Git::
@end menu
@node Setting Up Git
@subsection Setting Up Git
To make your Git logs easier to read, you should set the user.name and
user.email variables in your .gitconfig file:
@verbatim
[user]
name = Firstname Surname
email = example@doc.ic.ac.uk
@end verbatim
Note that we will be checking your Git logs as part of your submission.
You should ensure that you use meaningful commit messages and make it clear
who was responsible for each commit (especially if you are using pair-programming).
To work on the source code, you must create a clone of your group's provided @file{GitLab} repository.
This can be done by running the following command:
@example
git clone @value{localgitpath}
@end example
replacing @code{<gnum>} with your group number, which can be found on the @code{Gitlab} website.
@node Using Git
@subsection Using Git
Once you've cloned the repository, you can start working in your clone
straight away. At any point you can see what files you've modified with
@samp{git status}, and check a file in greater detail with
@samp{git diff @var{filename}}. You view more detailed information using
tools such as @samp{tig}
Git uses an intermediary area between the working filesystem and the actual
repository, known as the staging area (or index). This allows you to perform
tasks such as committing only a subset of your changes, without modifying your
copy of the filesystem. Whilst the uses of the staging area are outside the
scope of this guide, it is important that you are aware of its existence.
When you want to place your modifications into the repository, you must
first update the staging area with your changes (@samp{git add @var{filename}},
and then use this to update the repository, using @samp{git commit}. Git
will open a text editor when committing, allowing you to provide a description
of your changes. This can be useful later for reviewing the repository,
so be sensible with your commit messages.
When you want to share your changes with the rest of your group you will need to
run @samp{git push} to send your commits back to the shared @file{labranch} repository.
Note that the very first time you push you will need to run the command:
@example
git push origin master
@end example
to tell Git which branch of your local repository to push to which remote repository
(in this case from branch @code{master} to the @code{origin} repository).
Sometimes your group members may make confliting changes to your repository,
which Git is unable to solve.
These problems can be solved using @samp{git mergetool},
but its use is outside the scope of this dicussion.
You can view the history of a file @var{foo} in your working directory,
including the log messages, with @samp{git log @var{foo}}.
You can give a particular set of file versions a name called a
@dfn{tag}. Simply execute @samp{git tag @var{name}}. It's best
to have no local changes in the working copy when you do this, because
the tag will not include uncommitted changes. To recover the tagged
commit later, simply execute @samp{git checkout @var{tag}}.
If you add a new file to the source tree, you'll need to add it to the
repository with @samp{git add @var{file}}. This command does not have
lasting effect until the file is committed later with @samp{git
commit}.
To remove a file from the source tree, first remove it from the file
system with @samp{git rm @var{file}}. Again, only @samp{git commit}
will make the change permanent.
To discard your local changes for a given file, without committing
them, use @samp{git checkout @var{file} -f}.
For more information, visit the @uref{https://www.git-scm.com/, , Git
home page}.

73
doc/localsettings.texi Normal file
View File

@@ -0,0 +1,73 @@
@c Local settings
@set coursenumber COMP50004
@set labnumber COMP50007/500012
@set localpintosgitpath /vol/lab/secondyear/osexercise/pintos.git
@set localpintosbindir /vol/lab/secondyear/bin/
@set localgitpath https://gitlab.doc.ic.ac.uk/lab2425_autumn/pintos_<gnum>.git
@set localindivgitpath https://gitlab.doc.ic.ac.uk/lab2425_autumn/pintos_task0_<login>.git
@set recommendvnc
@clear recommendcygwin
@macro localmachines{}
The machines officially supported for PintOS development are
the Linux machines in the labs managed by CSG, as described on
the @uref{http://www.doc.ic.ac.uk/csg/facilities/lab/workstations, ,
CSG webpage}.
@end macro
@macro localpathsetup{}
The PintOS utilities can be located at @value{localpintosbindir} on CSG-run
lab machines.
@end macro
@macro localcrossbuild{}
Watch the commands executed during the build.
On the Linux machines, the ordinary system tools are used.
@end macro
@macro localhonorcodepolicy{}
Please respect the college's plagiarism policy by refraining from reading any coursework solutions available online or elsewhere.
You must also refrain from posting any of your code or solutions publically online (such as on GitHub) or sharing them with your classmates.
Reading the source code for other operating system kernels, such as Linux or FreeBSD, is allowed,
but do not copy code from them literally.
You must cite any code that inspired your own in your design documentation.
@end macro
@macro localcredits{}
Additional modifications have been made to the documentation, code and task structure when adapting and developing the material
for use at Imperial College London by Mark Rutland, Feroz Abdul Salam, Mark Wheelhouse, Fabio Luporini and Fidelis Perkonigg.
A number of DoC students have also made valuable contributions to the ongoing development of the @code{pintos}
project@footnote{If you have suggestions for improving the @code{pintos} tasks, spot and fix a bug or contribute new material to the project, then you too could be added to the above list. If interested, please discuss with Dr Mark Wheelhouse.},
and we thank them here:
@itemize
@item Dragos Dumitrache (2015) - created the first version of the ``pintos for Mac'' guide.
@item Nandor Licker (2015) - spotted an upcoming change to QEMU in 2015 that would have interfered with the @code{pintos} shutdown code.
@item Levente Kurusa (2017) - updated the ``pintos for Mac'' guide for more recent versions of MacOS and created the original Mac installation patch files (now merged into the main repo).
@item Emma Gospodinova (2019) - spotted the need to add the @code{-fno-ptr} and @code{-fno-pie} flags to @code{gcc} calls in the @code{pintos} makefiles, which would otherwise lead to key parts of the user-programs code being optimised out.
@item Moritz Langenstein (2019) - identified the need for additional explicit type conversions in numerous test cases to support stronger @code{gcc} warning flags.
@item Alex Tasos (2021) - provided a linker script @code{loaderfix.ld} to fix a bug in linking the @code{pintos} loader (@code{loader.bin}) on Arch Linux systems.
@item Bartlomiej Cieslar (2021) - spotted a potential double-free in the @code{load_segment} function in @code{src/userprog/process.c}.
@item Charlie Lidbury (2021) - spotted a potential issue with setting the writable flag for overlapping pages in the @code{load_segment} function in @code{src/userprog/process.c}.
@item Chun Wong (2023) - spotted a potential race-condition on @code{ready_list} in the @code{threads_ready} function in @code{src/threads/thread.c}.
@item Luke Moran (2023) - suggested adding div-by-zero checks to Task 2 (including @code{multi-oom}).
@item Reuben Cartwright (2023) - spotted a counter increment bug in the @code{pt-overflowstk} test.
@end itemize
@end macro
@macro localgitpolicy{}
Instead, we recommend integrating your team's changes early and often
using Git (@pxref{Git}).
This is less likely to produce surprises, because everyone can see everyone else's code as it is written, instead of just when it is finished.
Version control also makes it possible to review changes and, when a change introduces a bug, drop back to working versions of code.
@end macro
@macro localdevelopmenttools{}
@c Descriptions of additional, local development tools can be inserted here
@end macro

92
doc/pintos-ic.texi Normal file
View File

@@ -0,0 +1,92 @@
\input texinfo @c -*- texinfo -*-
@c %**start of header
@setfilename pintos-ic.info
@settitle PintOS Tasks
@c %**end of header
@c @bibref{} macro
@iftex
@macro bibref{cite}
[\cite\]
@end macro
@afourpaper
@end iftex
@ifinfo
@ifnotplaintext
@macro bibref{cite}
@ref{\cite\}
@end macro
@end ifnotplaintext
@ifplaintext
@macro bibref{cite}
[\cite\]
@end macro
@end ifplaintext
@end ifinfo
@ifhtml
@macro bibref{cite}
[@ref{\cite\}]
@end macro
@end ifhtml
@macro func{name}
@code{\name\()}
@end macro
@macro struct{name}
@code{struct \name\}
@end macro
@finalout
@titlepage
@title PintOS (Imperial College Edition)
Version 2.5.1
@author Originally by Ben Pfaff
@end titlepage
@shortcontents
@contents
@ifnottex
@node Top, Introduction, (dir), (dir)
@top PintOS Tasks
@end ifnottex
@menu
* Introduction::
* Task 0--Codebase::
* Task 1--Threads::
* Task 2--User Programs::
* Task 3--Virtual Memory::
* Reference Guide::
* 4.4BSD Scheduler::
* Coding Standards::
* Task Documentation::
* Debugging Tools::
* Development Tools::
* Installing PintOS::
* Bibliography::
* License::
@end menu
@c institution-local settings
@include localsettings.texi
@include intro.texi
@include codebase.texi
@include threads.texi
@include userprog.texi
@include vm.texi
@include reference.texi
@include 44bsd.texi
@include standards.texi
@include doc.texi
@include debug.texi
@include devel.texi
@include installation.texi
@include bibliography.texi
@include license.texi
@bye

16
doc/pintos-t2h.init Normal file
View File

@@ -0,0 +1,16 @@
sub T2H_InitGlobals
{
# Set the default body text, inserted between <BODY ... >
$T2H_BODYTEXT = '';
# text inserted after <BODY ...>
$T2H_AFTER_BODY_OPEN = '';
#text inserted before </BODY>
$T2H_PRE_BODY_CLOSE = '';
# this is used in footer
$T2H_ADDRESS = "<I>$T2H_USER</I> " if $T2H_USER;
$T2H_ADDRESS .= "on <I>$T2H_TODAY</I>";
# this is added inside <HEAD></HEAD> after <TITLE> and some META NAME stuff
# can be used for <style> <script>, <meta> tags
$T2H_EXTRA_HEAD = "<LINK REL=\"stylesheet\" HREF=\"pintos.css\">";
}
1;

76
doc/pintos.css Normal file
View File

@@ -0,0 +1,76 @@
body {
background: white;
color: black;
padding: 0em 1em 0em 3em;
margin: 0;
margin-left: auto;
margin-right: auto;
max-width: 8in;
text-align: justify
}
body>p {
margin: 0pt 0pt 0pt 0em;
text-align: justify
}
body>p + p {
margin: .75em 0pt 0pt 0pt
}
H1 {
font-size: 150%;
margin-left: -1.33em
}
H2 {
font-size: 125%;
font-weight: bold;
margin-left: -.8em
}
H3 {
font-size: 100%;
font-weight: bold;
margin-left: -.5em }
H4 {
font-size: 100%;
margin-left: 0em
}
H1, H2, H3, H4, H5, H6 {
font-family: sans-serif;
color: blue
}
H1, H2 {
text-decoration: underline
}
html {
margin: 0;
font-weight: lighter
}
tt, code {
font-family: sans-serif
}
b, strong {
font-weight: bold
}
a:link {
color: blue;
text-decoration: none;
}
a:visited {
color: gray;
text-decoration: none;
}
a:active {
color: black;
text-decoration: none;
}
a:hover {
text-decoration: underline
}
address {
font-size: 90%;
font-style: normal
}
HR {
display: none
}

2616
doc/reference.texi Normal file

File diff suppressed because it is too large Load Diff

104
doc/sample.tmpl Normal file
View File

@@ -0,0 +1,104 @@
+-----------------+
| CS 140 |
| SAMPLE TASK |
| DESIGN DOCUMENT |
+-----------------+
---- GROUP ----
Ben Pfaff <blp@stanford.edu>
---- PRELIMINARIES ----
>> If you have any preliminary comments on your submission, notes for
>> the TAs, or extra credit, please give them here.
(This is a sample design document.)
>> Please cite any offline or online sources you consulted while
>> preparing your submission, other than the PintOS documentation,
>> course text, and lecture notes.
None.
JOIN
====
---- DATA STRUCTURES ----
>> Copy here the declaration of each new or changed `struct' or `struct'
>> member, global or static variable, `typedef', or enumeration.
>> Identify the purpose of each in 25 words or less.
A "latch" is a new synchronization primitive. Acquires block
until the first release. Afterward, all ongoing and future
acquires pass immediately.
/* Latch. */
struct latch
{
bool released; /* Released yet? */
struct lock monitor_lock; /* Monitor lock. */
struct condition rel_cond; /* Signaled when released. */
};
Added to struct thread:
/* Members for implementing thread_join(). */
struct latch ready_to_die; /* Release when thread about to die. */
struct semaphore can_die; /* Up when thread allowed to die. */
struct list children; /* List of child threads. */
list_elem children_elem; /* Element of `children' list. */
---- ALGORITHMS ----
>> Briefly describe your implementation of thread_join() and how it
>> interacts with thread termination.
thread_join() finds the joined child on the thread's list of
children and waits for the child to exit by acquiring the child's
ready_to_die latch. When thread_exit() is called, the thread
releases its ready_to_die latch, allowing the parent to continue.
---- SYNCHRONIZATION ----
>> Consider parent thread P with child thread C. How do you ensure
>> proper synchronization and avoid race conditions when P calls wait(C)
>> before C exits? After C exits? How do you ensure that all resources
>> are freed in each case? How about when P terminates without waiting,
>> before C exits? After C exits? Are there any special cases?
C waits in thread_exit() for P to die before it finishes its own
exit, using the can_die semaphore "down"ed by C and "up"ed by P as
it exits. Regardless of whether whether C has terminated, there
is no race on wait(C), because C waits for P's permission before
it frees itself.
Regardless of whether P waits for C, P still "up"s C's can_die
semaphore when P dies, so C will always be freed. (However,
freeing C's resources is delayed until P's death.)
The initial thread is a special case because it has no parent to
wait for it or to "up" its can_die semaphore. Therefore, its
can_die semaphore is initialized to 1.
---- RATIONALE ----
>> Critique your design, pointing out advantages and disadvantages in
>> your design choices.
This design has the advantage of simplicity. Encapsulating most
of the synchronization logic into a new "latch" structure
abstracts what little complexity there is into a separate layer,
making the design easier to reason about. Also, all the new data
members are in `struct thread', with no need for any extra dynamic
allocation, etc., that would require extra management code.
On the other hand, this design is wasteful in that a child thread
cannot free itself before its parent has terminated. A parent
thread that creates a large number of short-lived child threads
could unnecessarily exhaust kernel memory. This is probably
acceptable for implementing kernel threads, but it may be a bad
idea for use with user processes because of the larger number of
resources that user processes tend to own.

195
doc/standards.texi Normal file
View File

@@ -0,0 +1,195 @@
@node Coding Standards
@appendix Coding Standards
All of you should be familiar with good coding standards by now.
This project will be much easier to complete and grade if you maintain a consistent code style and employ sensible variable naming policies.
Code style makes up a significant part of your final grade for this work, and will be scrutinised carefully.
We want to stress that aside from the fact that we are explicitly basing part of your grade on this,
good coding practices will also improve the quality of your code.
This makes it easier for your team-mates to interact with it and, ultimately, will improve your chances of having a good working program.
The rest of this appendix will discuss the coding standards used in the existing PintOS codebase and how we expect you to interact with this.
@menu
* Coding Style::
* C99::
* Unsafe String Functions::
@end menu
@comment ----------------------------------------------------------------------
@node Coding Style
@section Style
Style, for the purposes of our grading, refers to how readable your
code is. At minimum, this means that your code is well formatted, your
variable names are descriptive and your functions are decomposed and
well commented. Any other factors which make it hard (or easy) for us
to read or use your code will be reflected in your style grade.
The existing PintOS code is written in the GNU style and largely
follows the @uref{http://www.gnu.org/prep/standards_toc.html, , GNU
Coding Standards}. We encourage you to follow the applicable parts of
them too, especially chapter 5, ``Making the Best Use of C.'' Using a
different style won't cause actual problems so long as you are self-consistent in your additions.
It is ugly to see gratuitous differences in style from one function to another.
If your code is too ugly, it will cost you points.
Please limit C source file lines to at most 80 characters long.
PintOS comments sometimes refer to external standards or
specifications by writing a name inside square brackets, like this:
@code{[IA32-v3a]}. These names refer to the reference names used in
this documentation (@pxref{Bibliography}).
If you remove existing PintOS code, please delete it from your source
file entirely. Don't just put it into a comment or a conditional
compilation directive, because that makes the resulting code hard to
read. Version control software will allow you to recover the code if
necessary later.
We're only going to do a compile in the directory for the task being
submitted. You don't need to make sure that the previous tasks also
compile.
Task code should be written so that all of the subproblems for the
task function together, that is, without the need to rebuild with
different macros defined, etc.
If you decide to do any work beyond the spec that
changes normal PintOS behaviour so as to interfere with grading, then
you must implement it so that it only acts that way when given a
special command-line option of the form @option{-@var{name}}, where
@var{name} is a name of your choice. You can add such an option by
modifying @func{parse_options} in @file{threads/init.c}.
The introduction section (@pxref{Source Code}) describes some additional high-level coding style requirements.
@comment ----------------------------------------------------------------------
@page
@node C99
@section C99
The PintOS source code uses a few features of the ``C99'' standard
library that were not in the original 1989 standard for C.
Many programmers are unaware of these features, so we will describe them.
The new features used in PintOS are mostly in new headers:
@table @file
@item <stdbool.h>
Defines macros @code{bool}, a 1-bit type that takes on only the values
0 and 1, @code{true}, which expands to 1, and @code{false}, which
expands to 0.
@item <stdint.h>
On systems that support them, this header defines types
@code{int@var{n}_t} and @code{uint@var{n}_t} for @var{n} = 8, 16, 32,
64, and possibly other values. These are 2's complement signed and unsigned
types, respectively, with the given number of bits.
On systems where it is possible, this header also defines types
@code{intptr_t} and @code{uintptr_t}, which are integer types big
enough to hold a pointer.
On all systems, this header defines types @code{intmax_t} and
@code{uintmax_t}, which are the system's signed and unsigned integer
types with the widest ranges.
For every signed integer type @code{@var{type}_t} defined here, as well
as for @code{ptrdiff_t} defined in @file{<stddef.h>}, this header also
defines macros @code{@var{TYPE}_MAX} and @code{@var{TYPE}_MIN} that
give the type's range. Similarly, for every unsigned integer type
@code{@var{type}_t} defined here, as well as for @code{size_t} defined
in @file{<stddef.h>}, this header defines a @code{@var{TYPE}_MAX}
macro giving its maximum value.
@item <inttypes.h>
@file{<stdint.h>} provides no straightforward way to format
the types it defines with @func{printf} and related functions. This
header provides macros to help with that. For every
@code{int@var{n}_t} defined by @file{<stdint.h>}, it provides macros
@code{PRId@var{n}} and @code{PRIi@var{n}} for formatting values of
that type with @code{"%d"} and @code{"%i"}. Similarly, for every
@code{uint@var{n}_t}, it provides @code{PRIo@var{n}},
@code{PRIu@var{n}}, @code{PRIx@var{n}}, and @code{PRIX@var{n}}.
You use these something like this, taking advantage of the fact that
the C compiler concatenates adjacent string literals:
@example
#include <inttypes.h>
@dots{}
int32_t value = @dots{};
printf ("value=%08"PRId32"\n", value);
@end example
@noindent
(note that the @code{%08} format string above pads the output int to 8 significant figures).
The @samp{%} is not supplied by the @code{PRI} macros.
As shown above, you supply it yourself and follow it by any flags, field width, etc.
@item <stdio.h>
The @func{printf} function has some new type modifiers for printing
standard types:
@table @samp
@item j
For @code{intmax_t} (e.g.@: @samp{%jd}) or @code{uintmax_t} (e.g.@:
@samp{%ju}).
@item z
For @code{size_t} (e.g.@: @samp{%zu}).
@item t
For @code{ptrdiff_t} (e.g.@: @samp{%td}).
@end table
PintOS @func{printf} also implements a nonstandard @samp{'} flag that
groups large numbers with commas to make them easier to read.
@end table
@comment ----------------------------------------------------------------------@page
@node Unsafe String Functions
@section Unsafe String Functions
A few of the string functions declared in the standard
@file{<string.h>} and @file{<stdio.h>} headers are notoriously unsafe.
The worst offenders are intentionally not included in the PintOS C
library:
@table @code
@item strcpy()
When used carelessly this function can overflow the buffer reserved
for its output string. Use @func{strlcpy} instead. Refer to
comments in its source code in @code{lib/string.c} for documentation.
@item strncpy()
This function can leave its destination buffer without a null string
terminator. It also has performance problems. Again, use
@func{strlcpy}.
@item strcat()
Same issue as @func{strcpy}. Use @func{strlcat} instead.
Again, refer to comments in its source code in @code{lib/string.c} for
documentation.
@item strncat()
The meaning of its buffer size argument is surprising.
Again, use @func{strlcat}.
@item strtok()
Uses global data, so it is unsafe in threaded programs such as
kernels. Use @func{strtok_r} instead, and see its source code in
@code{lib/string.c} for documentation and an example.
@item sprintf()
Same issue as @func{strcpy}. Use @func{snprintf} instead. Refer
to comments in @code{lib/stdio.h} for documentation.
@item vsprintf()
Same issue as @func{strcpy}. Use @func{vsnprintf} instead.
@end table
If you try to use any of these functions, the error message will give
you a hint by referring to an identifier like
@code{dont_use_sprintf_use_snprintf}.

84
doc/task0_questions.texi Normal file
View File

@@ -0,0 +1,84 @@
@strong{Part A - Codebase Preview: Questions to Prepare for the MCQ AnswerBook Test}
@enumerate
@item Which Git command should you run to retrieve a copy of your individual repository for PintOS Task 0 in your local directory?
(@dfn{Hint: be specific to this task and think about ease of use.})
@item Why is using the strcpy() function to copy strings usually a bad idea?
(@dfn{Hint: be sure to clearly identify the problem.})
@item If test @file{src/tests/devices/alarm-multiple} fails, where would you find its output and result logs? Provide both paths and file names.
(@dfn{Hint: you might want to run this test to find out.})
@item In PintOS, a thread is characterized by a struct and an execution stack.
(a) What are the limitations on the size of these data structures?
(b) Explain how this relates to stack overflow and how PintOS identifies it.
@item Explain how thread scheduling in PintOS currently works in roughly 300 words. Include the chain of execution of function calls.
(@dfn{Hint: we expect you to at least mention which functions participate in a context switch, how they interact, how and when the thread state is modified and the role of interrupts.})
@item In PintOS, what is the default length (in ticks and in seconds) of a scheduler time slice?
(@dfn{Hint: read the Task 0 documentation carefully.})
@item In PintOS, how would you print an unsigned 64 bit @code{int}?
(Consider that you are working with C99). Don't forget to state any inclusions needed by your code.
@item Explain the property of @strong{reproducibility} and how the lack of reproducibility will affect debugging.
@item In PintOS, locks are implemented on top of semaphores.
(a) How do the functions in the API of locks relate to those of semaphores?
(b) What extra property do locks have that semaphores do not?
@item Define what is meant by a @strong{race-condition}. Why is the test @code{if(x != null)} insufficient to prevent a segmentation fault from occurring on an attempted access to a structure through the pointer @code{x}?
(@dfn{Hint: you should assume that the pointer variable is correctly typed, that the structure was successfully initialised earlier in the program and that there are other threads running in parallel.})
@end enumerate
@strong{Part B - The Alarm Clock}
Reimplement @code{timer_sleep()}, defined in @file{devices/timer.c}.
(@b{30 marks})
Although a working implementation of @code{timer_sleep} is provided, it "busy waits", that is, it spins in a loop checking the current time and calling @code{thread_yield()} until enough time has gone by.
You need to reimplement it to avoid busy waiting.
Further instructions and hints can be found in the PintOS manual.
The marks for this question are awarded as follows:
Passing the Automated Tests (@b{8 marks}).
Performance in the Code Review (@b{12 marks}).
Answering the Design Document Questions below (@b{10 marks}).
@itemize @w{}
@item @b{Data Structures}
A1: Copy here the declaration of each new or changed `@code{struct}' or `@code{struct}' member, global or static variable, `@code{typedef}', or enumeration. Identify the purpose of each in roughly 25 words. (@b{2 marks})
@item @b{Algorithms}
A2: Briefly describe what happens in a call to @code{timer_sleep()}, including the actions performed by the timer interrupt handler on each timer tick. (@b{2 marks})
A3: What steps are taken to minimize the amount of time spent in the timer interrupt handler? (@b{2 marks})
@item @b{Synchronization}
A4: How are race conditions avoided when multiple threads call @code{timer_sleep()} simultaneously? (@b{1 mark})
A5: How are race conditions avoided when a timer interrupt occurs during a call to @code{timer_sleep()}? (@b{1 mark})
@item @b{Rationale}
A6: Why did you choose this design?
In what ways is it superior to another design you considered? (@b{2 marks})
@end itemize

11
doc/task0_sheet.texi Normal file
View File

@@ -0,0 +1,11 @@
\input texinfo @c -*- texinfo -*-
@c %**start of header
@setfilename task0_sheet.info
@settitle PintOS Task 0
@c %**end of header
@chapter PintOS-IC Task 0 Questions
@include task0_questions.texi
@bye

6346
doc/texi2html Executable file

File diff suppressed because it is too large Load Diff

6976
doc/texinfo.tex Normal file

File diff suppressed because it is too large Load Diff

501
doc/threads.texi Normal file
View File

@@ -0,0 +1,501 @@
@node Task 1--Threads
@chapter Task 1: Scheduling
In this assignment, we give you a minimally functional thread system.
Your job is to extend the functionality of this system to gain a
better understanding of synchronization problems.
You will be working primarily in the @file{threads} directory for
this assignment. Compilation should be done in the @file{threads} directory.
Before you read the description of this task, you should read all of
the following sections: @ref{Introduction}, @ref{Task 0--Codebase}, @ref{Coding Standards},
@ref{Debugging Tools}, and @ref{Development Tools}. You should at least
skim the material from @ref{PintOS Loading} through @ref{Memory
Allocation}, especially @ref{Synchronization}. To complete this task
you will also need to read @ref{4.4BSD Scheduler}.
You must build task 1 on top of a working task 0 submission
as some of the task 1 test rely on a non-busy waiting implementation of @code{timer_sleep()}.
@menu
* Background::
* Development Suggestions::
* Task 1 Requirements::
* Task 1 FAQ::
@end menu
@node Background
@section Background
Now that you've become familiar with PintOS and its thread package, it's time to work on one of the most critical component of an operating system: the scheduler.
Working on the scheduler requires you to have grasped the main concepts of both the threading system and synchronization primitives. If you still feel uncertain about these topics, you are warmly invited to refer back to @ref{Understanding Threads} and @ref{Synchronization} and to carefully read the code in the corresponding source files.
@node Development Suggestions
@section Development Suggestions
In the past, many groups divided the assignment into pieces, then each
group member worked on his or her piece until just before the
deadline, at which time the group reconvened to combine their code and
submit. @strong{This is a bad idea. We do not recommend this
approach.} Groups that do this often find that two changes conflict
with each other, requiring lots of last-minute debugging. Some groups
who have done this have turned in code that did not even compile or
boot, much less pass any tests.
@localgitpolicy{}
You should expect to run into bugs that you simply don't understand
while working on this and subsequent tasks. When you do,
reread the appendix on debugging tools, which is filled with
useful debugging tips that should help you to get back up to speed
(@pxref{Debugging Tools}). Be sure to read the section on backtraces
(@pxref{Backtraces}), which will help you to get the most out of every
kernel panic or assertion failure.
@node Task 1 Requirements
@section Requirements
@menu
* Task 1 Design Document::
* Setting and Inspecting Priorities::
* Priority Scheduling::
* Priority Donation::
* Advanced Scheduler::
@end menu
@node Task 1 Design Document
@subsection Design Document
When you submit your work for task 1, you must also submit a completed copy of
@uref{threads.tmpl, , the task 1 design document}.
You can find a template design document for this task in @file{pintos/doc/threads.tmpl} and also on CATe.
You are free to submit your design document as either a @file{.txt} or @file{.pdf} file.
We recommend that you read the design document template before you start working on the task.
@xref{Task Documentation}, for a sample design document that goes along with a fictitious task.
@node Setting and Inspecting Priorities
@subsection Setting and Inspecting Priorities
Implement the following functions that allow a thread to examine and modify its own priority.
Skeletons for these functions are provided in @file{threads/thread.c}.
@deftypefun int thread_get_priority (void)
Returns the current thread's effective priority.
@end deftypefun
@deftypefun void thread_set_priority (int @var{new_priority})
Sets the current thread's priority to @var{new_priority}.
If the current thread no longer has the highest priority, yields.
@end deftypefun
@node Priority Scheduling
@subsection Priority Scheduling
Implement priority scheduling in PintOS.
When a thread is added to the ready list that has a higher priority
than the currently running thread, the current thread should
immediately yield the processor to the new thread. Similarly, when
threads are waiting for a lock, semaphore, or condition variable, the
highest priority waiting thread should be awakened first. A thread
may raise or lower its own priority at any time, but lowering its
priority such that it no longer has the highest priority must cause it
to immediately yield the CPU. In both the priority scheduler and the
advanced scheduler you will write later, the running thread should
be that with the highest priority.
Thread priorities range from @code{PRI_MIN} (0) to @code{PRI_MAX} (63).
Lower numbers correspond to lower priorities, so that priority 0
is the lowest priority and priority 63 is the highest.
The initial thread priority is passed as an argument to
@func{thread_create}. If there's no reason to choose another
priority, new threads should use @code{PRI_DEFAULT} (31). The @code{PRI_} macros are
defined in @file{threads/thread.h}, and you should not change their
values.
@node Priority Donation
@subsection Priority Donation
One issue with priority scheduling is ``priority inversion''. Consider
high, medium, and low priority threads @var{H}, @var{M}, and @var{L},
respectively. If @var{H} needs to wait for @var{L} (for instance, for a
lock held by @var{L}), and @var{M} is on the ready list, then @var{H}
will never get the CPU because the low priority thread will not get any
CPU time. A partial fix for this problem is for @var{H} to ``donate''
its priority to @var{L} while @var{L} is holding the lock, then recall
the donation once @var{L} releases (and thus @var{H} acquires) the lock.
Implement priority donation. You will need to account for all different
situations in which priority donation is required. In particular, be sure to handle:
@itemize
@item @strong{multiple donations}: multiple priorities can be donated to a single thread.
@item @strong{nested donations}: if @var{H} is waiting on
a lock that @var{M} holds and @var{M} is waiting on a lock that @var{L}
holds, then both @var{M} and @var{L} should be boosted to @var{H}'s
priority. If necessary, you may impose a reasonable limit on depth of
nested priority donation, such as 8 levels.
@end itemize
You must implement priority donation for locks.
You do not need to implement priority donation for the other PintOS synchronization constructs.
However, you do need to implement priority scheduling in all cases.
Finally, you should review your implementations of @code{thread_get_priority} and @code{thread_set_priority}
to make sure that they exhibit the correct behaviour in the presence of dontations.
In particular, in the presence of priority donations @code{thread_get_priority} must return the highest donated priority.
You do not need to provide any interface to allow a thread to directly modify other threads' priorities.
The priority scheduler is also not used in any later task.
@node Advanced Scheduler
@subsection Advanced Scheduler
Implement a multilevel feedback queue scheduler similar to the
4.4@acronym{BSD} scheduler to
reduce the average response time for running jobs on your system.
@xref{4.4BSD Scheduler}, for detailed requirements.
Like the priority scheduler, the advanced scheduler chooses the thread
to run based on priorities. However, the advanced scheduler does not do
priority donation. Thus, we recommend that you have the priority
scheduler working, except possibly for priority donation, before you
start work on the advanced scheduler.
You must write your code to allow us to choose a scheduling algorithm
policy at PintOS startup time. By default, the priority scheduler
must be active, but we must be able to choose the 4.4@acronym{BSD}
scheduler
with the @option{-mlfqs} kernel option. Passing this
option sets @code{thread_mlfqs}, declared in @file{threads/thread.h}, to
true when the options are parsed by @func{parse_options}, which happens
early in @func{main}.
When the 4.4@acronym{BSD} scheduler is enabled, threads no longer
directly control their own priorities. The @var{priority} argument to
@func{thread_create} should be ignored, as well as any calls to
@func{thread_set_priority}, and @func{thread_get_priority} should return
the thread's current priority as set by the scheduler.
The advanced scheduler is not used in any later task.
@node Task 1 FAQ
@section FAQ
@table @b
@item How much code will I need to write?
Here's a summary of our reference solution, produced by the
@command{diffstat} program. The final row gives total lines inserted
and deleted; a changed line counts as both an insertion and a deletion.
@verbatim
threads/fixed-point.h | 120 ++++++++++++++++++
threads/synch.c | 88 ++++++++++++-
threads/thread.c | 196 ++++++++++++++++++++++++++----
threads/thread.h | 19 ++
4 files changed, 397 insertions(+), 26 deletions(-)
@end verbatim
The reference solution represents just one possible solution. Many
other solutions are also possible and many of those differ greatly from
the reference solution. Some excellent solutions may not modify all the
files modified by the reference solution, and some may modify files not
modified by the reference solution.
@file{fixed-point.h} is a new file added by the reference solution.
@item Do we need a working Task 0 to implement Task 1?
Yes.
@item How do I update the @file{Makefile}s when I add a new source file?
@anchor{Adding Source Files}
To add a @file{.c} file, edit the top-level @file{Makefile.build}.
Add the new file to variable @samp{@var{dir}_SRC}, where
@var{dir} is the directory where you added the file. For this
task, that means you should add it to @code{threads_SRC} or
@code{devices_SRC}. Then run @code{make}. If your new file
doesn't get
compiled, run @code{make clean} and then try again.
When you modify the top-level @file{Makefile.build} and re-run
@command{make}, the modified
version should be automatically copied to
@file{threads/build/Makefile}. The converse is
not true, so any changes will be lost the next time you run @code{make
clean} from the @file{threads} directory. Unless your changes are
truly temporary, you should prefer to edit @file{Makefile.build}.
A new @file{.h} file does not require editing the @file{Makefile}s.
@item What does @code{warning: no previous prototype for `@var{func}'} mean?
It means that you defined a non-@code{static} function without
preceding it by a prototype. Because non-@code{static} functions are
intended for use by other @file{.c} files, for safety they should be
prototyped in a header file included before their definition. To fix
the problem, add a prototype in a header file that you include, or, if
the function isn't actually used by other @file{.c} files, make it
@code{static}.
@item What is the interval between timer interrupts?
Timer interrupts occur @code{TIMER_FREQ} times per second. You can
adjust this value by editing @file{devices/timer.h}. The default is
100 Hz.
We don't recommend changing this value, because any changes are likely
to cause many of the tests to fail.
@item How long is a time slice?
There are @code{TIME_SLICE} ticks per time slice. This macro is
declared in @file{threads/thread.c}. The default is 4 ticks.
We don't recommend changing this value, because any changes are likely
to cause many of the tests to fail.
@item How do I run the tests?
@xref{Testing}.
@item Why do I get a test failure in @func{pass}?
@anchor{The pass function fails}
You are probably looking at a backtrace that looks something like this:
@example
0xc0108810: debug_panic (lib/kernel/debug.c:32)
0xc010a99f: pass (tests/threads/tests.c:93)
0xc010bdd3: test_mlfqs_load_1 (...threads/mlfqs-load-1.c:33)
0xc010a8cf: run_test (tests/threads/tests.c:51)
0xc0100452: run_task (threads/init.c:283)
0xc0100536: run_actions (threads/init.c:333)
0xc01000bb: main (threads/init.c:137)
@end example
This is just confusing output from the @command{backtrace} program. It
does not actually mean that @func{pass} called @func{debug_panic}. In
fact, @func{fail} called @func{debug_panic} (via the @func{PANIC}
macro). GCC knows that @func{debug_panic} does not return, because it
is declared @code{NO_RETURN} (@pxref{Function and Parameter
Attributes}), so it doesn't include any code in @func{fail} to take
control when @func{debug_panic} returns. This means that the return
address on the stack looks like it is at the beginning of the function
that happens to follow @func{fail} in memory, which in this case happens
to be @func{pass}.
@xref{Backtraces}, for more information.
@item How do interrupts get re-enabled in the new thread following @func{schedule}?
Every path into @func{schedule} disables interrupts. They eventually
get re-enabled by the next thread to be scheduled. Consider the
possibilities: the new thread is running in @func{switch_thread} (but
see below), which is called by @func{schedule}, which is called by one
of a few possible functions:
@itemize @bullet
@item
@func{thread_exit}, but we'll never switch back into such a thread, so
it's uninteresting.
@item
@func{thread_yield}, which immediately restores the interrupt level upon
return from @func{schedule}.
@item
@func{thread_block}, which is called from multiple places:
@itemize @minus
@item
@func{sema_down}, which restores the interrupt level before returning.
@item
@func{idle}, which enables interrupts with an explicit assembly STI
instruction.
@item
@func{wait} in @file{devices/intq.c}, whose callers are responsible for
re-enabling interrupts.
@end itemize
@end itemize
There is a special case when a newly created thread runs for the first
time. Such a thread calls @func{intr_enable} as the first action in
@func{kernel_thread}, which is at the bottom of the call stack for every
kernel thread but the first.
@item What should I expect from the Task 1 code-review?
The code-review for this task will be conducted with each group in-person.
Our Task 1 code-review will cover @strong{four} main areas:
functional correctness, efficiency, design quality and general coding style.
@itemize @bullet
@item For @strong{functional correctness}, we will be looking to see if your implementation of priority scheduling strictly obeys the rule that "the highest priority ready thread will always be running" and that all cases of priority inversion are being correctly handled by your system for priority donations.
We will also be checking if your updated code for locks is free of any race conditions, paying specific attention to the @func{lock_acquire} and @func{lock_release} functions, as well as the interplay between them.
@item For @strong{efficiency}, we will be looking at the complexity characteristics of your modified code for semaphores, as well
the steps you have taken to minimise the time spent inside your timer interrupt handler.
@item For @strong{design quality}, we will be looking at the stability and robustness of any changes you have made to the core PintOS kernel (e.g. @func{thread_block}, @func{thread_unblock} and @func{thread_yield}) and the accuracy of the priority updates in your BSD scheduler.
@item For @strong{general coding style}, we will be paying attention to all of the usual elements of good style
that you should be used to from last year (e.g. consistent code layout, appropriate use of comments, avoiding magic numbers, etc.)
as well as your use of git (e.g. commit frequency and commit message quality).
In this task, we will be paying particular attention to the readability of your fixed-point mathematics abstraction within your BSD scheduler.
@end itemize
@end table
@menu
* Priority Scheduling FAQ::
* Advanced Scheduler FAQ::
@end menu
@node Priority Scheduling FAQ
@subsection Priority Scheduling FAQ
@table @b
@item Doesn't priority scheduling lead to starvation?
Yes, strict priority scheduling can lead to starvation
because a thread will not run if any higher-priority thread is runnable.
The advanced scheduler introduces a mechanism for dynamically
changing thread priorities.
Strict priority scheduling is valuable in real-time systems because it
offers the programmer more control over which jobs get processing
time. High priorities are generally reserved for time-critical
tasks. It's not ``fair,'' but it addresses other concerns not
applicable to a general-purpose operating system.
@item What thread should run after a lock has been released?
When a lock is released, the highest priority thread waiting for that
lock should be unblocked and put on the list of ready threads.
The scheduler should then run the highest priority thread on the ready list.
@item If the highest-priority thread yields, does it continue running?
Yes. If there is a single highest-priority thread, it continues
running until it blocks or finishes, even if it calls
@func{thread_yield}.
If multiple threads have the same highest priority,
@func{thread_yield} should switch among them in ``round robin'' order.
@item What happens to the priority of a donating thread?
Priority donation only changes the priority of the donee
thread. The donor thread's priority is unchanged.
Priority donation is not additive: if thread @var{A} (with priority 5) donates
to thread @var{B} (with priority 3), then @var{B}'s new priority is 5, not 8.
@item Can a thread's priority change while it is on the ready queue?
Yes. Consider a ready, low-priority thread @var{L} that holds a lock.
High-priority thread @var{H} attempts to acquire the lock and blocks,
thereby donating its priority to ready thread @var{L}.
@item Can a thread's priority change while it is blocked?
Yes. While a thread that has acquired lock @var{L} is blocked for any
reason, its priority can increase by priority donation if a
higher-priority thread attempts to acquire @var{L}. This case is
checked by the @code{priority-donate-sema} test.
@item Can a thread added to the ready list preempt the processor?
Yes. If a thread added to the ready list has higher priority than the
running thread, the correct behaviour is to immediately yield the
processor. It is not acceptable to wait for the next timer interrupt.
The highest priority thread should run as soon as it is runnable,
preempting whatever thread is currently running.
@item How does @func{thread_set_priority} affect a thread receiving donations?
It sets the thread's base priority. The thread's effective priority
becomes the higher of the newly set priority or the highest donated
priority. When the donations are released, the thread's priority
becomes the one set through the function call. This behaviour is checked
by the @code{priority-donate-lower} test.
@item Doubled test names in output make them fail.
Suppose you are seeing output in which some test names are doubled,
like this:
@example
(alarm-priority) begin
(alarm-priority) (alarm-priority) Thread priority 30 woke up.
Thread priority 29 woke up.
(alarm-priority) Thread priority 28 woke up.
@end example
What is happening is that output from two threads is being
interleaved. That is, one thread is printing @code{"(alarm-priority)
Thread priority 29 woke up.\n"} and another thread is printing
@code{"(alarm-priority) Thread priority 30 woke up.\n"}, but the first
thread is being preempted by the second in the middle of its output.
This problem indicates a bug in your priority scheduler. After all, a
thread with priority 29 should not be able to run while a thread with
priority 30 has work to do.
Normally, the implementation of the @code{printf()} function in the
PintOS kernel attempts to prevent such interleaved output by acquiring
a console lock during the duration of the @code{printf} call and
releasing it afterwards. However, the output of the test name,
e.g., @code{(alarm-priority)}, and the message following it is output
using two calls to @code{printf}, resulting in the console lock being
acquired and released twice.
@end table
@node Advanced Scheduler FAQ
@subsection Advanced Scheduler FAQ
@table @b
@item How does priority donation interact with the advanced scheduler?
It doesn't have to. We won't test priority donation and the advanced
scheduler at the same time.
@item Can I use one queue instead of 64 queues?
Yes. In general, your implementation may differ from the description,
as long as its behaviour is the same.
@item Some scheduler tests fail and I don't understand why. Help!
If your implementation mysteriously fails some of the advanced
scheduler tests, try the following:
@itemize
@item
Read the source files for the tests that you're failing, to make sure
that you understand what's going on. Each one has a comment at the
top that explains its purpose and expected results.
@item
Double-check your fixed-point arithmetic routines and your use of them
in the scheduler routines.
@item
Consider how much work your implementation does in the timer
interrupt. If the timer interrupt handler takes too long, then it
will take away most of a timer tick from the thread that the timer
interrupt preempted. When it returns control to that thread, it
therefore won't get to do much work before the next timer interrupt
arrives. That thread will therefore get blamed for a lot more CPU
time than it actually got a chance to use. This raises the
interrupted thread's recent CPU count, thereby lowering its priority.
It can cause scheduling decisions to change. It also raises the load
average.
@end itemize
@end table

108
doc/threads.tmpl Normal file
View File

@@ -0,0 +1,108 @@
+----------------------+
| OS 211 |
| TASK 1: SCHEDULING |
| DESIGN DOCUMENT |
+----------------------+
---- GROUP ----
>> Fill in the names and email addresses of your group members.
FirstName LastName <email@domain.example>
FirstName LastName <email@domain.example>
FirstName LastName <email@domain.example>
---- PRELIMINARIES ----
>> If you have any preliminary comments on your submission, or notes for the
>> markers, please give them here.
>> Please cite any offline or online sources you consulted while preparing your
>> submission, other than the PintOS documentation, course text, lecture notes
>> and course staff.
PRIORITY SCHEDULING
===================
---- DATA STRUCTURES ----
>> A1: (2 marks)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration.
>> Identify the purpose of each in roughly 25 words.
>> A2: (4 marks)
>> Draw a diagram that illustrates a nested donation in your structure and
>> briefly explain how this works.
---- ALGORITHMS ----
>> A3: (3 marks)
>> How do you ensure that the highest priority waiting thread wakes up first for
>> a (i) semaphore, (ii) lock, or (iii) condition variable?
>> A4: (3 marks)
>> Describe the sequence of events when a call to lock_acquire() causes a
>> priority donation.
>> How is nested donation handled?
>> A5: (3 marks)
>> Describe the sequence of events when lock_release() is called on a lock that
>> a higher-priority thread is waiting for.
---- SYNCHRONIZATION ----
>> A6: (2 marks)
>> How do you avoid a race condition in thread_set_priority() when a thread
>> needs to recompute its effective priority, but the donated priorities
>> potentially change during the computation?
>> Can you use a lock to avoid the race?
---- RATIONALE ----
>> A7: (3 marks)
>> Why did you choose this design?
>> In what ways is it superior to another design you considered?
ADVANCED SCHEDULER
==================
---- DATA STRUCTURES ----
>> B1: (2 marks)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration.
>> Identify the purpose of each in roughly 25 words.
---- ALGORITHMS ----
>> B2: (3 marks)
>> Suppose threads A, B, and C have nice values 0, 1, and 2 and each has a
>> recent_cpu value of 0.
>> Fill in the table below showing the scheduling decision, the priority and the
>> recent_cpu values for each thread after each given number of timer ticks:
timer recent_cpu priority thread
ticks A B C A B C to run
----- -- -- -- -- -- -- ------
0
4
8
12
16
20
24
28
32
36
>> B3: (2 marks)
>> Did any ambiguities in the scheduler specification make values in the table
>> uncertain?
>> If so, what rule did you use to resolve them?
---- RATIONALE ----
>> B4: (3 marks)
>> Briefly critique your design, pointing out advantages and disadvantages in
>> your design choices.

1241
doc/userprog.texi Normal file

File diff suppressed because it is too large Load Diff

116
doc/userprog.tmpl Normal file
View File

@@ -0,0 +1,116 @@
+-------------------------+
| OS 211 |
| TASK 2: USER PROGRAMS |
| DESIGN DOCUMENT |
+-------------------------+
---- GROUP ----
>> Fill in the names and email addresses of your group members.
FirstName LastName <email@domain.example>
FirstName LastName <email@domain.example>
FirstName LastName <email@domain.example>
---- PRELIMINARIES ----
>> If you have any preliminary comments on your submission, or notes for the
>> markers, please give them here.
>> Please cite any offline or online sources you consulted while preparing your
>> submission, other than the PintOS documentation, course text, lecture notes
>> and course staff.
ARGUMENT PASSING
================
---- DATA STRUCTURES ----
>> A1: (1 mark)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration.
>> Identify the purpose of each in roughly 25 words.
---- ALGORITHMS ----
>> A2: (2 marks)
>> How does your argument parsing code avoid overflowing the user's stack page?
>> What are the efficiency considerations of your approach?
---- RATIONALE ----
>> A3: (2 marks)
>> PintOS does not implement strtok() because it is not thread safe.
>> Explain the problem with strtok() and how strtok_r() avoids this issue.
>> A4: (3 marks)
>> In PintOS, the kernel separates commands into an executable name and arguments.
>> In Unix-like systems, the shell does this separation.
>> Identify three advantages of the Unix approach.
SYSTEM CALLS
============
---- DATA STRUCTURES ----
>> B1: (6 marks)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration.
>> Identify the purpose of each in roughly 25 words.
---- ALGORITHMS ----
>> B2: (2 marks)
>> Describe how your code ensures safe memory access of user provided data from
>> within the kernel.
>> B3: (3 marks)
>> Suppose that we choose to verify user provided pointers by validating them
>> before use (i.e. using the first method described in the spec).
>> What is the least and the greatest possible number of inspections of the page
>> table (e.g. calls to pagedir_get_page()) that would need to be made in the
>> following cases?
>> a) A system call that passes the kernel a pointer to 10 bytes of user data.
>> b) A system call that passes the kernel a pointer to a full page
>> (4,096 bytes) of user data.
>> c) A system call that passes the kernel a pointer to 4 full pages
>> (16,384 bytes) of user data.
>> You must briefly explain the checking tactic you would use and how it applies
>> to each case to generate your answers.
>> B4: (2 marks)
>> When an error is detected during a system call handler, how do you ensure
>> that all temporarily allocated resources (locks, buffers, etc.) are freed?
>> B5: (8 marks)
>> Describe your implementation of the "wait" system call and how it interacts
>> with process termination for both the parent and child.
---- SYNCHRONIZATION ----
>> B6: (2 marks)
>> The "exec" system call returns -1 if loading the new executable fails, so it
>> cannot return before the new executable has completed loading.
>> How does your code ensure this?
>> How is the load success/failure status passed back to the thread that calls
>> "exec"?
>> B7: (5 marks)
>> Consider parent process P with child process C.
>> How do you ensure proper synchronization and avoid race conditions when:
>> i) P calls wait(C) before C exits?
>> ii) P calls wait(C) after C exits?
>> iii) P terminates, without waiting, before C exits?
>> iv) P terminates, without waiting, after C exits?
>> Additionally, how do you ensure that all resources are freed regardless of
>> the above case?
---- RATIONALE ----
>> B8: (2 marks)
>> Why did you choose to implement safe access of user memory from the kernel in
>> the way that you did?
>> B9: (2 marks)
>> What advantages and disadvantages can you see to your design for file
>> descriptors?

835
doc/vm.texi Normal file
View File

@@ -0,0 +1,835 @@
@node Task 3--Virtual Memory
@chapter Task 3: Virtual Memory
By now you should have some familiarity with the inner workings of
PintOS. Your OS can properly handle multiple threads of execution with proper
synchronization, and can load multiple user programs at once. However,
the number and size of programs that can run is limited by the machine's
main memory size. In this assignment, you will remove that limitation.
You will build this assignment on top of the last one. Test programs
from task 2 should also work with task 3. You should take care to
fix any bugs in your task 2 submission before you start work on
task 3, because those bugs will most likely cause the same problems
in task 3.
You will continue to handle PintOS disks and file systems the same way
you did in the previous assignment (@pxref{Using the File System}).
@menu
* Task 3 Background::
* Task 3 Suggested Order of Implementation::
* Task 3 Requirements::
* Task 3 FAQ::
@end menu
@node Task 3 Background
@section Background
@menu
* Task 3 Source Files::
* Memory Terminology::
* Resource Management Overview::
* Managing the Supplemental Page Table::
* Managing the Frame Table::
* Accessed and Dirty Bits::
* Managing the Table of File Mappings::
* Managing the Swap Partition::
* Managing Memory Mapped Files Back::
@end menu
@node Task 3 Source Files
@subsection Source Files
You will work in the @file{vm} directory for this task. The
@file{vm} directory contains only @file{Makefile}s. The only
change from @file{userprog} is that this new @file{Makefile} turns on
the setting @option{-DVM}. All code you write will be in new
files or in files introduced in earlier tasks.
You will probably be encountering just a few files for the first time:
@table @file
@item devices/block.h
@itemx devices/block.c
Provides sector-based read and write access to block devices.
@item devices/swap.h
@itemx devices/swap.c
Provides page-based read and write access to the swap partition.
You will use this interface to access the swap partition, as wrapper around a block device.
@end table
@node Memory Terminology
@subsection Memory Terminology
Careful definitions are needed to keep discussion of virtual memory from
being confusing. Thus, we begin by presenting some terminology for
memory and storage. Some of these terms should be familiar from task
2 (@pxref{Virtual Memory Layout}), but much of it is new.
@menu
* Pages::
* Frames::
* Page Tables::
* Swap Slots::
@end menu
@node Pages
@subsubsection Pages
A @dfn{page}, sometimes called a @dfn{virtual page}, is a continuous
region of virtual memory 4,096 bytes (the @dfn{page size}) in length. A
page must be @dfn{page-aligned}, that is, start on a virtual address
evenly divisible by the page size. Thus, a 32-bit virtual address can
be divided into a 20-bit @dfn{page number} and a 12-bit @dfn{page
offset} (or just @dfn{offset}), like this:
@example
@group
31 12 11 0
+-------------------+-----------+
| Page Number | Offset |
+-------------------+-----------+
Virtual Address
@end group
@end example
Each process has an independent set of @dfn{user virtual pages}, which
are those pages below virtual address @code{PHYS_BASE}, typically
@t{0xc0000000} (3 GB). The set of @dfn{kernel virtual pages}, on the
other hand, is global, remaining the same regardless of what thread or
process is active. The kernel may access both user virtual and kernel virtual pages,
but a user process may access only its own user virtual pages. @xref{Virtual
Memory Layout}, for more information.
PintOS provides several useful functions for working with virtual
addresses. @xref{Virtual Addresses}, for details.
@node Frames
@subsubsection Frames
A @dfn{frame}, sometimes called a @dfn{physical frame} or a @dfn{page
frame}, is a continuous region of physical memory. Like pages, frames
must be page-size and page-aligned. Thus, a 32-bit physical address can
be divided into a 20-bit @dfn{frame number} and a 12-bit @dfn{frame
offset} (or just @dfn{offset}), like this:
@example
@group
31 12 11 0
+-------------------+-----------+
| Frame Number | Offset |
+-------------------+-----------+
Physical Address
@end group
@end example
The 80@var{x}86 doesn't provide any way to directly access memory at a
physical address. PintOS works around this by mapping kernel virtual
memory directly to physical memory: the first page of kernel virtual
memory is mapped to the first frame of physical memory, the second page
to the second frame, and so on. Thus, frames can be accessed through
kernel virtual memory.
PintOS provides functions for translating between physical addresses and
kernel virtual addresses. @xref{Virtual Addresses}, for details.
@node Page Tables
@subsubsection Page Tables
In PintOS, a @dfn{page table} is a data structure that the CPU uses to
translate a virtual address to a physical address, that is, from a page
to a frame. The page table format is dictated by the 80@var{x}86
architecture. PintOS provides page table management code in
@file{pagedir.c} (@pxref{Page Table}).
The diagram below illustrates the relationship between pages and frames.
The virtual address, on the left, consists of a page number and an
offset. The page table translates the page number into a frame number,
which is combined with the unmodified offset to obtain the physical
address, on the right.
@example
@group
+----------+
.--------------->|Page Table|-----------.
/ +----------+ |
31 | 12 11 0 31 | 12 11 0
+---------+----+ +---------+----+
|Page Nr | Ofs| |Frame Nr | Ofs|
+---------+----+ +---------+----+
Virt Addr | Phys Addr |
\_______________________________________/
@end group
@end example
@node Swap Slots
@subsubsection Swap Slots
A @dfn{swap slot} is a continuous, page-size region of disk space in the
swap partition. Although hardware limitations dictating the placement of
slots are looser than for pages and frames, swap slots should be
page-aligned because there is no downside in doing so.
@node Resource Management Overview
@subsection Resource Management Overview
You will need to design the following data structures:
@table @asis
@item Supplemental page table
Enables page fault handling by supplementing the page table.
@xref{Managing the Supplemental Page Table}.
@item Frame table
Allows efficient implementation of eviction policy.
@xref{Managing the Frame Table}.
@item Table of file mappings
Processes may map files into their virtual memory space. You need a
table to track which files are mapped into which pages.
@end table
You do not necessarily need to implement three completely distinct data
structures: it may be convenient to wholly or partially merge related
resources into a unified data structure.
For each data structure, you need to determine what information each
element should contain. You also need to decide on the data structure's
scope, either local (per-process) or global (applying to the whole
system), and how many instances are required within its scope.
To simplify your design, you may store these data structures in
non-pageable memory (i.e. kernel space).
That means that you can be sure that pointers among them will remain valid.
Possible choices of data structures include arrays, lists, bitmaps, and
hash tables. An array is often the simplest approach, but a sparsely
populated array wastes memory. Lists are also simple, but traversing a
long list to find a particular position wastes time. Both arrays and
lists can be resized, but lists more efficiently support insertion and
deletion in the middle.
PintOS includes a bitmap data structure in @file{lib/kernel/bitmap.c}
and @file{lib/kernel/bitmap.h}. A bitmap is an array of bits, each of
which can be true or false. Bitmaps are typically used to track usage
in a set of (identical) resources: if resource @var{n} is in use, then
bit @var{n} of the bitmap is true. PintOS bitmaps are fixed in size,
although you could extend their implementation to support resizing.
PintOS also includes a hash table data structure (@pxref{Hash Table}).
PintOS hash tables efficiently support insertions and deletions over a
wide range of table sizes.
Although more complex data structures may yield performance or other
benefits, they may also needlessly complicate your implementation.
Thus, we do not recommend implementing any advanced data structure
(e.g.@: a balanced binary tree) as part of your design.
@node Managing the Supplemental Page Table
@subsection Managing the Supplemental Page Table
The @dfn{supplemental page table} extends the page table with
additional data about each page. It is needed because of the
limitations imposed by the page table's format. Such a data structure
is also often referred to as a ``page table''; we add the word ``supplemental''
to reduce confusion.
The supplemental page table is used for at least two purposes. Most
importantly, on a page fault, the kernel looks up the virtual page that
faulted in the supplemental page table to find out what data should be
there. Second, the kernel consults the supplemental page table when a
process terminates, to decide what resources to free.
You may organize the supplemental page table as you wish. There are at
least two basic approaches to its organization: in terms of segments or
in terms of pages. Optionally, you may use the page table itself as an
index to track the members of the supplemental page table. You will
have to modify the PintOS page table implementation in @file{pagedir.c}
to do so. We recommend this approach for advanced students only.
@xref{Page Table Entry Format}, for more information.
The most important user of the supplemental page table is the page fault
handler. In task 2, a page fault always indicated a bug in the
kernel or a user program. In task 3, this is no longer true. Now, a
page fault might only indicate that the page must be brought in from a
file or swap. You will have to implement a more sophisticated page
fault handler to handle these cases. Your page fault handler, which you
should implement by modifying @func{page_fault} in
@file{userprog/exception.c}, needs to do roughly the following:
@enumerate 1
@item
Locate the page that faulted in the supplemental page table. If the
memory reference is valid, use the supplemental page table entry to
locate the data that goes in the page, which might be in the file
system, or in a swap slot, or it might simply be an all-zero page. When
you implement sharing, the page's data might even already be in a page
frame, but not in the page table.
If the supplemental page table indicates that the user process should
not expect any data at the address it was trying to access, or if the
page lies within kernel virtual memory, or if the access is an attempt
to write to a read-only page, then the access is invalid. Any invalid
access terminates the process and thereby frees all of its resources.
@item
Obtain a frame to store the page. @xref{Managing the Frame Table}, for
details.
When you implement sharing, the data you need may already be in a frame,
in which case you must be able to locate that frame.
@item
Fetch the data into the frame, by reading it from the file system or
swap, zeroing it, etc.
When you implement sharing, the page you need may already be in a frame,
in which case no action is necessary in this step.
@item
Point the page table entry for the faulting virtual address to the frame.
You can use the functions in @file{userprog/pagedir.c}.
@end enumerate
@node Managing the Frame Table
@subsection Managing the Frame Table
The @dfn{frame table} contains one entry for each frame that contains a
user page. Each entry in the frame table contains a pointer to the
page, if any, that currently occupies it, and other data of your choice.
The frame table allows PintOS to efficiently implement an eviction
policy, by choosing a page to evict when no frames are free.
The frames used for user pages should be obtained from the ``user
pool,'' by calling @code{palloc_get_page(PAL_USER)}. You must use
@code{PAL_USER} to avoid allocating from the ``kernel pool,'' which
could cause some test cases to fail unexpectedly (@pxref{Why
PAL_USER?}). If you modify @file{palloc.c} as part of your frame table
implementation, be sure to retain the distinction between the two pools.
The most important operation on the frame table is obtaining an unused
frame. This is easy when a frame is free. When none is free, a frame
must be made free by evicting some page from its frame.
If no frame can be evicted without allocating a swap slot, but swap is
full, panic the kernel. Real OSes apply a wide range of policies to
recover from or prevent such situations, but these policies are beyond
the scope of this task.
The process of eviction comprises roughly the following steps:
@enumerate 1
@item
Choose a frame to evict, using your page replacement algorithm. The
``accessed'' and ``dirty'' bits in the page table, described below, will
come in handy.
@item
Remove references to the frame from any page table that refers to it.
Until you have implemented sharing, only a single page should refer to
a frame at any given time.
@item
If necessary, write the page to the file system or to swap.
@end enumerate
The evicted frame may then be used to store a different page.
@node Accessed and Dirty Bits
@subsubsection Accessed and Dirty Bits
80@var{x}86 hardware provides some assistance for implementing page
replacement algorithms, through a pair of bits in the page table entry
(PTE) for each page. On any read or write to a page, the CPU sets the
@dfn{accessed bit} to 1 in the page's PTE, and on any write, the CPU
sets the @dfn{dirty bit} to 1. The CPU never resets these bits to 0,
but the OS may do so.
You need to be aware of @dfn{aliases}, that is, two (or more) pages that
refer to the same frame. When an aliased frame is accessed, the
accessed and dirty bits are updated in only one page table entry (the
one for the page used for access). The accessed and dirty bits for the
other aliases are not updated.
In PintOS, every user virtual page is aliased to its kernel virtual
page. You must manage these aliases somehow. For example, your code
could check and update the accessed and dirty bits for both addresses.
Alternatively, the kernel could avoid the problem by only accessing user
data through the user virtual address.
Other aliases should only arise once you implement sharing, or if there is a bug in your code.
@xref{Page Table Accessed and Dirty Bits}, for details of the functions
to work with accessed and dirty bits.
@node Managing the Table of File Mappings
@subsection Managing the Table of File Mappings
In order to implement sharing of read-only executable pages, you will need to track which files are mapped to which page.
We suggest that you create a table, or nested data-structure, to store this information.
This table only needs to store details about read-only executable pages.
Do not confuse this with memory-mapped files, which you will probably want to manage separately.
There are a couple of functions in @file{filesys/file.c} that you might find very helpful when impelementing sharing.
The @func{file_compare} function can be used to check if two file structs (@code{file1} and @code{file2})
are referencing the same underlying file (i.e. inode).
The @func{file_hash} function is a hashing function that also operates on the internal underlying file representation.
@node Managing the Swap Partition
@subsection Managing the Swap Partition
PintOS provides a complete impelentation of a swap partition manager, that wraps around a block device.
This includes an internal swap table to track in-use and free swap slots.
The @func{swap_out} function can be used to pick an unused swap slot when evicting a page @code{vaddr} from its frame 'out' to the swap partition.
The @func{swap_in} function can be used to restore a page 'in' to memory at @code{vaddr} and free its swap @code{slot}.
You can also use the @func{swap_drop} function to free a swap @code{slot}, for example when the owning process is terminated.
Internally, the swap partition makes use of the @code{BLOCK_SWAP} block device for swapping.
It obtainins the @struct{block} that represents it by calling @func{block_get_role}.
From the @file{vm/build} directory, use the command @code{pintos-mkdisk swap.dsk
--swap-size=@var{n}} to create an disk named @file{swap.dsk} that contains a @var{n}-MB swap partition.
Afterward, @file{swap.dsk} will automatically be attached as an extra disk when you run @command{pintos}.
Alternatively, you can tell @command{pintos} to use a temporary @var{n}-MB swap disk for a single
run with @option{--swap-size=@var{n}}.
Swap slots should be allocated lazily, that is, only when they are actually required by eviction.
Reading data pages from the executable and writing them to swap immediately at process startup is not lazy.
Swap slots should also not be reserved to store particular pages.
@node Managing Memory Mapped Files Back
@subsection Managing Memory Mapped Files
The file system is most commonly accessed with @code{read} and
@code{write} system calls. A secondary interface is to ``map'' the file
into virtual pages, using the @code{mmap} system call. The program can
then use memory instructions directly on the file data.
Suppose file @file{foo} is @t{0x1000} bytes (4 kB, or one page) long.
If @file{foo} is mapped into memory starting at address @t{0x5000}, then
any memory accesses to locations @t{0x5000}@dots{}@t{0x5fff} will access
the corresponding bytes of @file{foo}.
Here's a program that uses @code{mmap} to print a file to the console.
It opens the file specified on the command line, maps it at virtual
address @t{0x10000000}, writes the mapped data to the console (fd 1),
and unmaps the file.
@example
#include <stdio.h>
#include <syscall.h>
int main (int argc UNUSED, char *argv[])
@{
void *data = (void *) 0x10000000; /* @r{Address at which to map.} */
int fd = open (argv[1]); /* @r{Open file.} */
mapid_t map = mmap (fd, data); /* @r{Map file.} */
write (1, data, filesize (fd)); /* @r{Write file to console.} */
munmap (map); /* @r{Unmap file (optional).} */
return 0;
@}
@end example
A similar program with full error handling is included as @file{mcat.c}
in the @file{examples} directory, which also contains @file{mcp.c} as a
second example of @code{mmap}.
Your submission must be able to track what memory is used by memory
mapped files. This is necessary to properly handle page faults in the
mapped regions and to ensure that mapped files do not overlap any other
segments within the process.
@node Task 3 Suggested Order of Implementation
@section Suggested Order of Implementation
We suggest the following initial order of implementation:
@enumerate 1
@item
Frame table (@pxref{Managing the Frame Table}). Change @file{process.c}
to use your frame table allocator.
Do not implement swapping yet. If you run out of frames, fail the
allocator or panic the kernel.
After this step, your kernel should still pass all the task 2 test
cases.
@item
Supplemental page table and page fault handler (@pxref{Managing the Supplemental Page Table}).
Change @file{process.c} to lazy-load a process's executable
by recording the necessary information for each page in the supplemental page table during @code{load_segment}.
Implement the actual loading of these code and data segments in the page fault handler.
For now, consider only valid accesses.
After this step, your kernel should pass all of the task 2
functionality test cases, but only some of the robustness tests.
@item
From here, you can implement stack growth, mapped files, sharing and page
reclamation on process exit in parallel.
@item
The next step is to implement eviction (@pxref{Managing the Frame
Table}). Initially you could choose the page to evict randomly. At
this point, you need to consider how to manage accessed and dirty bits
and aliasing of user and kernel pages. Synchronization is also a
concern: how do you deal with it if process A faults on a page whose
frame process B is in the process of evicting?
@end enumerate
@node Task 3 Requirements
@section Requirements
This assignment is an open-ended design problem. We are going to say as
little as possible about how to do things. Instead we will focus on
what functionality we require your OS to support. We will expect
you to come up with a design that makes sense. You will have the
freedom to choose how to handle page faults, how to organize the swap
partition, how to implement paging, etc.
@menu
* Task 3 Design Document::
* Paging::
* Stack Growth::
* Memory Mapped Files::
@end menu
@node Task 3 Design Document
@subsection Design Document
When you submit your work for task 3, you must also submit a completed copy of
@uref{vm.tmpl, , the task 3 design document template}.
You can find a template design document for this task in @file{pintos/doc/vm.tmpl} and also on CATe.
You are free to submit your design document as either a @file{.txt} or @file{.pdf} file.
We recommend that you read the design document template before you start working on the task.
@xref{Task Documentation}, for a sample design document that goes along with a fictitious task.
@node Paging
@subsection Paging
Implement paging for segments loaded from executables. All of these
pages should be loaded lazily, that is, only as the kernel intercepts
page faults for them. Upon eviction, pages modified since load (e.g. data
segment pages), as indicated by the ``dirty bit'', should be written to swap.
Unmodified pages, including read-only pages, should never be written to
swap because they can always be read back from the executable.
Your design should allow for parallelism. If one page fault requires
I/O, in the meantime processes that do not fault should continue
executing and other page faults that do not require I/O should be able
to complete. This will require some synchronization effort.
You'll need to modify the core of the program loader, which is the loop
in @func{load_segment} in @file{userprog/process.c}. Each time around
the loop, @code{page_read_bytes} receives the number of bytes to read
from the executable file and @code{page_zero_bytes} receives the number
of bytes to initialize to zero following the bytes read. The two always
sum to @code{PGSIZE} (4,096). The handling of a page depends on these
variables' values:
@itemize @bullet
@item
If @code{page_read_bytes} equals @code{PGSIZE}, the page should be demand
paged from the underlying file on its first access.
@item
If @code{page_zero_bytes} equals @code{PGSIZE}, the page does not need to
be read from disk at all because it is all zeroes. You should handle
such pages by creating a new page consisting of all zeroes at the
first page fault.
@item
Otherwise, neither @code{page_read_bytes} nor @code{page_zero_bytes}
equals @code{PGSIZE}. In this case, an initial part of the page is to
be read from the underlying file and the remainder zeroed.
@end itemize
Watch out for executable segments that share a page in memory, and thus overlap in the page-table.
The provided code in @file{userprog/process.c} already handles this by checking during @code{load_segment} if any @code{upage} has already been installed. In such a case, rather than allocating/installing a new page of memory, the existing page is updated instead.
You will need to do something similar in your supplemental page table.
@node Stack Growth
@subsection Stack Growth
Implement stack growth.
In task 2, the stack was limited a single page at the top of the user virtual address space and user programs would crash if they exceeded this limit.
Now, if the stack grows past its current size, you should allocate additional pages as necessary.
You should allocate additional stack pages only if the corresponding page fault ``appears'' to be a stack access.
To this end, you will need to devise a heuristic that attempts to distinguish stack accesses from other accesses.
User programs are buggy if they write to the stack below the stack
pointer, because typical real OSes may interrupt a process at any time
to deliver a ``signal,'' which pushes data on the stack.@footnote{This rule is
common but not universal. One modern exception is the
@uref{http://www.x86-64.org/documentation/abi.pdf, @var{x}86-64 System V
ABI}, which designates 128 bytes below the stack pointer as a ``red
zone'' that may not be modified by signal or interrupt handlers.}
However, the 80@var{x}86 @code{PUSH} instruction checks access
permissions before it adjusts the stack pointer, so it may cause a page
fault 4 bytes below the stack pointer. (Otherwise, @code{PUSH} would
not be restartable in a straightforward fashion.) Similarly, the
@code{PUSHA} instruction pushes 32 bytes at once, so it can fault 32
bytes below the stack pointer.
You will need to be able to obtain the current value of the user
program's stack pointer. Within a system call or a page fault generated
by a user program, you can retrieve it from the @code{esp} member of the
@struct{intr_frame} passed to @func{syscall_handler} or
@func{page_fault}, respectively. If you verify user pointers before
accessing them (@pxref{Accessing User Memory}), these are the only cases
you need to handle. On the other hand, if you depend on page faults to
detect invalid memory access, you will need to handle another case,
where a page fault occurs in the kernel. Since the processor only
saves the stack pointer when an exception causes a switch from user
to kernel mode, reading @code{esp} out of the @struct{intr_frame}
passed to @func{page_fault} would yield an undefined value, not the
user stack pointer. You will need to arrange another way, such as
saving @code{esp} into @struct{thread} on the initial transition
from user to kernel mode.
You should impose some absolute limit on stack size, as do most OSes.
Some OSes make the limit user-adjustable, e.g.@: with the
@command{ulimit} command on many Unix systems.
On many GNU/Linux systems, the default limit is 8 MB.
The first stack page need not be allocated lazily. You can allocate
and initialize it with the command line arguments at load time, with
no need to wait for it to be faulted in.
All stack pages should be candidates for eviction. An evicted stack
page should be written to swap.
@node Memory Mapped Files
@subsection Memory Mapped Files
Implement memory mapped files, including the following system calls.
@deftypefn {System Call} mapid_t mmap (int @var{fd}, void *@var{addr})
Maps the file open as @var{fd} into the process's virtual address
space. The entire file is mapped into consecutive virtual pages
starting at @var{addr}.
Your VM system must lazily load pages in @code{mmap} regions and use the
@code{mmap}ed file itself as backing store for the mapping. That is,
evicting a page mapped by @code{mmap} writes it back to the file it was
mapped from.
If the file's length is not a multiple of @code{PGSIZE}, then some
bytes in the final mapped page ``stick out'' beyond the end of the
file. Set these bytes to zero when the page is faulted in from the
file system,
and discard them when the page is written back to disk.
If successful, this function returns a ``mapping ID'' that
uniquely identifies the mapping within the process. On failure,
it must return -1, which otherwise should not be a valid mapping id,
and the process's mappings must be unchanged.
A call to @code{mmap} may fail if the file open as @var{fd} has a
length of zero bytes. It must fail if @var{addr} is not page-aligned
or if the range of pages mapped overlaps any existing set of mapped
pages, including the space reserved for the stack
or pages mapped at executable load time.
It must also fail if @var{addr} is 0, because some PintOS code assumes
virtual page 0 is not mapped. Finally, file descriptors 0 and 1,
representing console input and output, are not mappable.
@end deftypefn
@deftypefn {System Call} void munmap (mapid_t @var{mapping})
Unmaps the mapping designated by @var{mapping}, which must be a
mapping ID returned by a previous call to @code{mmap} by the same
process that has not yet been unmapped.
@end deftypefn
All mappings are implicitly unmapped when a process exits, whether via
@code{exit} or by any other means. When a mapping is unmapped, whether
implicitly or explicitly, all pages written to by the process are
written back to the file, and pages not written must not be. The pages
are then removed from the process's list of virtual pages.
Closing or removing a file does not unmap any of its mappings. Once
created, a mapping is valid until @code{munmap} is called or the process
exits, following the Unix convention. @xref{Removing an Open File}, for
more information. You should use the @code{file_reopen} function to
obtain a separate and independent reference to the file for each of
its mappings.
If two or more processes map the same file, there is no requirement that
they see consistent data. Unix handles this by making the two mappings
share the same physical page, but the Unix @code{mmap} system call also has
an argument allowing the client to specify whether the page is shared or
private (i.e.@: copy-on-write).
@subsection Accessing User Memory
You will need to adapt your code to access user memory (@pxref{Accessing
User Memory}) while handling a system call. Just as user processes may
access pages whose content is currently in a file or in swap space, so
can they pass addresses that refer to such non-resident pages to system
calls. Moreover, unless your kernel takes measures to prevent this,
a page may be evicted from its frame even while it is being accessed
by kernel code. If kernel code accesses such non-resident user pages,
a page fault will result.
While accessing user memory, your kernel must either be prepared to handle
such page faults, or it must prevent them from occurring. The kernel
must prevent such page faults while it is holding resources it would
need to acquire to handle these faults. In PintOS, such resources include
locks acquired by the device driver(s) that control the device(s) containing
the file system and swap space. As a concrete example, you must not
allow page faults to occur while a device driver accesses a user buffer
passed to @code{file_read}, because you would not be able to invoke
the driver while handling such faults.
Preventing such page faults requires cooperation between the code within
which the access occurs and your page eviction code. For instance,
you could extend your frame table to record when a page contained in
a frame must not be evicted. (This is also referred to as ``pinning''
or ``locking'' the page in its frame.) Pinning restricts your page
replacement algorithm's choices when looking for pages to evict, so be
sure to pin pages no longer than necessary, and avoid pinning pages when
it is not necessary.
@node Task 3 FAQ
@section FAQ
@table @b
@item How much code will I need to write?
Here's a summary of our reference solution, produced by the
@command{diffstat} program. The final row gives total lines inserted
and deleted; a changed line counts as both an insertion and a deletion.
@verbatim
Makefile.build | 4 +-
threads/init.c | 5 +
threads/interrupt.c | 2 +
threads/thread.c | 26 +-
threads/thread.h | 37 ++-
userprog/exception.c | 12 +-
userprog/pagedir.c | 10 +-
userprog/process.c | 355 +++++++++++++-----
userprog/syscall.c | 612 ++++++++++++++++++++++++++++++-
userprog/syscall.h | 1 +
vm/frame.c | 162 +++++++++
vm/frame.h | 23 +
vm/page.c | 293 ++++++++++++++++
vm/page.h | 51 ++
14 files changed, 1489 insertions(+), 104 deletions(-)
@end verbatim
This summary is relative to the PintOS base code, but the reference
solution for task 3 starts from the reference solution to task 2.
@xref{Task 2 FAQ}, for the summary of task 2.
The reference solution represents just one possible solution. Many
other solutions are also possible and many of those differ greatly from
the reference solution. Some excellent solutions may not modify all the
files modified by the reference solution, and some may modify files not
modified by the reference solution.
@item Do we need a working Task 2 to implement Task 3?
Yes.
@item How complex does our page replacement algorithm need to be?
@anchor{VM Extra Credit}
If you implement an advanced page replacement algorithm,
such as the ``second chance'' or the ``clock'' algorithms,
then you will get more marks for this part of the task.
You should also implement sharing: when multiple processes are created that use
the same executable file, share read-only pages among those processes
instead of creating separate copies of read-only segments for each
process. If you carefully designed your data structures,
sharing of read-only pages should not make this part significantly
harder.
@item Do we need to handle paging for both user virtual memory and kernel virtual memory?
No, you only need to implement paging for user virtual memory.
One of the golden rules of OS development is ``Don't page out the paging code!''
@item How do we resume a process after we have handled a page fault?
Returning from @func{page_fault} resumes the current user process
(@pxref{Internal Interrupt Handling}).
It will then retry the instruction to which the instruction pointer points.
@item Why do user processes sometimes fault above the stack pointer?
You might notice that, in the stack growth tests, the user program faults
on an address that is above the user program's current stack pointer,
even though the @code{PUSH} and @code{PUSHA} instructions would cause
faults 4 and 32 bytes below the current stack pointer.
This is not unusual. The @code{PUSH} and @code{PUSHA} instructions are
not the only instructions that can trigger user stack growth.
For instance, a user program may allocate stack space by decrementing the
stack pointer using a @code{SUB $n, %esp} instruction, and then use a
@code{MOV ..., m(%esp)} instruction to write to a stack location within
the allocated space that is @var{m} bytes above the current stack pointer.
Such accesses are perfectly valid, and your kernel must grow the
user program's stack to allow those accesses to succeed.
@item Does the virtual memory system need to support data segment growth?
No. The size of the data segment is determined by the linker. We still
have no dynamic allocation in PintOS (although it is possible to
``fake'' it at the user level by using memory-mapped files). Supporting
data segment growth should add little additional complexity to a
well-designed system.
@item Why should I use @code{PAL_USER} for allocating page frames?
@anchor{Why PAL_USER?}
Passing @code{PAL_USER} to @func{palloc_get_page} causes it to allocate
memory from the user pool, instead of the main kernel pool. Running out
of pages in the user pool just causes user programs to page, but running
out of pages in the kernel pool will cause many failures because so many
kernel functions need to obtain memory.
You can layer some other allocator on top of @func{palloc_get_page} if
you like, but it should be the underlying mechanism.
Also, you can use the @option{-ul} kernel command-line option to limit
the size of the user pool, which makes it easy to test your VM
implementation with various user memory sizes.
@item What should we do if the stack grows into a @code{mmap} file?
This should not be possible.
The specification of @code{mmap()} rules out creating mappings within the possible stack space,
so you should abort any attempt to create a mapping within that space.
The stack should also not be able to grow beyond it's reserved stack space,
thus ruling out the possibility of any such overlap.
@item What should I expect from the Task 3 code-review?
The code-review for this task will be conducted with each group in-person.
Our Task 3 code-review will cover @strong{four} main areas:
functional correctness, efficiency, design quality and general coding style.
@itemize @bullet
@item For @strong{functional correctness}, we will be looking to see if your code for page sharing accurately tracks the accessed/dirty status of each shared page and if your stack-fault heuristic is correct.
We will also be checking if your code for page allocation, page fault handling and memory mapping/unmapping is free of any race conditions.
@item For @strong{efficiency}, we will be making sure that you only load executable code segments on demand (lazy loading).
We will also be checking to make sure that you have made efficient use of the swap space and that your code is free of any memory leaks.
@item For @strong{design quality}, we will be looking to see if you have implemented an advanced eviction algorithm
(i.e. an algorithm that considers the properties of the pages in memory in order to chose a good eviction candidate).
@item For @strong{general coding style}, we will be paying attention to all of the usual elements of good style
that you should be used to from last year (e.g. consistent code layout, appropriate use of comments, avoiding magic numbers, etc.)
as well as your use of git (e.g. commit frequency and commit message quality).
In this task, we will be paying particular attention to any additional efficiency improvements you have made to your eviction algorithm (e.g. encouraging fairness) or the system's overall use of memory (e.g. increased page sharing).
We will also be looking at any use of hash tables, specifically checking that your hash functions are chosen to avoid frequent collisions.
@end itemize
@end table

130
doc/vm.tmpl Normal file
View File

@@ -0,0 +1,130 @@
+--------------------------+
| OS 211 |
| TASK 3: VIRTUAL MEMORY |
| DESIGN DOCUMENT |
+--------------------------+
---- GROUP ----
>> Fill in the names and email addresses of your group members.
FirstName LastName <email@domain.example>
FirstName LastName <email@domain.example>
FirstName LastName <email@domain.example>
---- PRELIMINARIES ----
>> If you have any preliminary comments on your submission, or notes for the
>> markers, please give them here.
>> Please cite any offline or online sources you consulted while preparing your
>> submission, other than the PintOS documentation, course text, lecture notes
>> and course staff.
PAGE TABLE MANAGEMENT AND LAZY LOADING
======================================
---- DATA STRUCTURES ----
>> A1: (2 marks)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration that relates to your
>> supplemental page table and table of file mappings.
>> Identify the purpose of each in roughly 25 words.
---- ALGORITHMS ----
>> A2: (2 marks)
>> Describe your code for finding the location of a given page that is not
>> currently loaded into memory.
>> A3: (2 marks)
>> How have you implemented sharing of read only pages?
>> A4: (2 marks)
>> When a process P obtains a frame that was previously used by a process Q,
>> how do you adjust the page directory of process Q (and any other data
>> structures) to reflect the frame Q no longer has?
---- SYNCHRONIZATION ----
>> A5: (2 marks)
>> Explain how you handle access to user pages that are not present when a
>> system call is made.
---- RATIONALE ----
>> A6: (2 marks)
>> Why did you choose the data structure(s) that you did for representing the
>> supplemental page table and table of file mappings?
FRAME TABLE MANAGEMENT AND EVICTION
===================================
---- DATA STRUCTURES ----
>> B1: (1 marks)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration that relates to your
>> frame table.
>> Identify the purpose of each in roughly 25 words.
---- ALGORITHMS ----
>> B2: (2 marks)
>> When a frame is required but none is free, some frame must be evicted.
>> Describe your code for choosing a frame to evict.
---- SYNCHRONIZATION ----
>> B3: (2 marks)
>> When two user processes both need a new frame at the same time, how are
>> races avoided?
>> You should consider both when there are and are not free frames
>> available in memory.
>> B4: (2 marks)
>> A page fault in process P can cause another process Q's frame to be evicted.
>> How do you ensure that Q cannot access or modify that page during the
>> eviction process?
>> B5: (2 marks)
>> A page fault in process P can cause another process Q's frame to be evicted.
>> How do you avoid a race between P evicting Q's frame and Q faulting the page
>> back in?
>> B6: (2 marks)
>> Explain how your synchronization design prevents deadlock.
>> (You may want to refer to the necessary conditions for deadlock.)
---- RATIONALE ----
>> B7: (2 marks)
>> There is an obvious trade-off between parallelism and the complexity of your
>> synchronisation methods.
>> Explain where your design falls along this continuum and why you chose to
>> design it this way.
MEMORY MAPPED FILES
===================
---- DATA STRUCTURES ----
>> C1: (2 marks)
>> Copy here the declaration of each new or changed `struct' or `struct' member,
>> global or static variable, `typedef', or enumeration that relates to your
>> file mapping table.
>> Identify the purpose of each in roughly 25 words.
---- ALGORITHMS ----
>> C2: (2 marks)
>> Explain how you determine whether a new file mapping overlaps with any
>> existing segment and how you handle such a case.
---- RATIONALE ----
>> C3: (1 mark)
>> Mappings created with "mmap" have similar semantics to those of data
>> demand-paged from executables.
>> How does your code-base take advantage of this?

View File

@@ -0,0 +1,59 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA Feedback</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Feedback Form&nbsp;
<HR WIDTH="100%"></CENTER>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Note - this form requires that
www.goodnet.com be reachable from your client in order to be sent. If it
does not return with a success message, check the connection and try sending
again.
<BR><FORM ACTION="http://www.goodnet.com/~tinara/cgi-bin/feedback.cgi" METHOD="POST"><B>Name:</B>
<BR><INPUT TYPE="text" NAME="NAME" SIZE=30>
<BR><B>Email:</B>
<BR><INPUT TYPE="text" NAME="FROM" SIZE=30>
<BR><B>Project/Company/Program:</B>
<BR><INPUT TYPE="text" NAME="PROJECT" SIZE=40>
<BR><B>Application of Information:</B>
<BR><INPUT TYPE="radio" NAME="USE" VALUE="none" CHECKED>Just Curious
<BR><INPUT TYPE="radio" NAME="USE" VALUE="game">Game Programming
<BR><INPUT TYPE="radio" NAME="USE" VALUE="demo">Demo Programming
<BR><INPUT TYPE="radio" NAME="USE" VALUE="os">OS Development
<BR><INPUT TYPE="radio" NAME="USE" VALUE="driver">Driver Development
<BR><INPUT TYPE="radio" NAME="USE" VALUE="other">Other
<BR><B>Type of Software:</B>
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="n/a" CHECKED>Not Applicable
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="personal use">Personal Use
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="public domain">Public Domain
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="freeware">Freeware
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="shareware">Shareware
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="GNU/other">GNU or other
free license
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="commercial">Commercial
<BR><INPUT TYPE="radio" NAME="PROGTYPE" VALUE="other">Other
<CENTER><B>Body of Message:</B></CENTER>
<CENTER><TEXTAREA NAME="BODY" ROWS=24 COLS=60></TEXTAREA></CENTER>
<CENTER><INPUT TYPE="submit" value=" Send Mail "></CENTER>
</FORM>
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

255
specs/freevga/freevga.htm Normal file
View File

@@ -0,0 +1,255 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA--About the FreeVGA Project</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#completeness">Completeness</A>
<A HREF="#contrib">Contribution</A> <A HREF="#membership">Membership</A>
<A HREF="#questions">Questions</A> <A HREF="home.htm">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>About the FreeVGA Project&nbsp;
<HR WIDTH="100%"></CENTER>
<P><A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; As a software programmer
for the PC architecture I have noticed that there is plenty of free information
existing on the Internet for programming PC hardware, with the notable
exception of video adapters, MPEG cards and the like. When the VGA was
the standard adapter card in PC's, programming was relatively straightforward.
However, when SVGA adapters appeared on the market, there was little standardization
between separate vendor's products. For this reason, applications and graphical
user interface systems required specialized drivers to utilize the extended
capabilities of the SVGA adapters. Either these specialized drivers were
written by the video card vendor or they had to be written by the application
vendor. Unfortunately due to the cost of specifications and complexity
of hardware, most free or shareware programs supported only the standard
VGA. The goal of this project, under my direction, is to explore the area
of low-level video programming and provide information for programmers
of free software throughout the world.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; With the growing popularity
of the free software concept, more and more specialized applications are
written every day. Many of these applications could take advantage of the
specialized features of the video hardware but often the information required
is not available. This projects goal is to make that information available
By gaining the cooperation of both programmers and hardware manufacturers
an excellent reference can be developed. Internet technology makes it possible
to provide a free resource updated in a timely fashion as opposed to printed
matter which takes time to print and deliver.
<P><A NAME="completeness"></A><B>Completeness</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Why would a low-level programmer
need this reference rather than simply use datasheets and chipset specifications
from the manufacturers themselves? First, the manufacturers may no longer
provide literature on "obsolete" chipsets. Second, such datasheets are
often aimed at hardware designers rather than programmers. Programmers
are trying to implement software on existing hardware rather design hardware.
Many of the details needed to program the hardware are dependent on the
implementation of the video adapter. Datasheets typically only provide
information on one particular component of the video hardware. It is necessary
to understand how the components in the adapter are "wired" together to
be able to program the adapter. This information is rarely found in datasheets
or manufacturer's documentation. Third, as demonstrated on the VGA and
some specific SVGA hardware, there are always programmers who can find
ways to cleverly program the hardware to provide capabilities unimagined
by the manufacturer. To do this, it requires the programmer to have intimate
knowledge of the hardware, as BIOS services provide a "lowest common denominator"
of capability.
<P><A NAME="contrib"></A><B>Contribution</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>This section is for
those interested in contributing to the FreeVGA Project. The primary objective
of this project is to gather information about video hardware, to verify
this information as best as possible, then to organize the information
in a form usable for any application, and finally to make this information
freely available to all programmers. Because of the non-profit nature of
this project, all information provided is the result of generous contribution
by myself or others. The primary resources required by this project are:
chipset datasheets/documentation, developer kits for video boards, video
adapter boards used for testing and verifying information, and finally
"postcards from the bleeding edge" i.e. information about the real world
problems and their workarounds from video programmers. If you can provide
any of these resources to the project or any other related assistance myself
and other programmers who benefit give thanks to your generosity. Your
name will be forever enshrined on the list of contributors, along with
a link to your homepage if you so desire.
<BR>&nbsp;&nbsp;&nbsp;&nbsp; I can be reached via the <A HREF="feedback.htm">feedback
form</A>. If you wish to donate hardware or documentation, please send
it, along with your name and the link you wish to include in the list of
contributors to:
<P>Joshua Neal
<BR>FreeVGA Project
<BR>925 N. Coronado Dr.
<BR>Gilbert, AZ 85234
<P><A NAME="membership"></A><B>Membership</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Because of the nature of
this project, any contributor can consider themselves a member if they
wish to do so. As the founder of this project I am willing to donate my
time and resources to ensuring the continuing organization, accuracy, and
usability of the FreeVGA Project's documentation. I will continue to do
this indefinitely, although if the task becomes overwhelming I will solicit
volunteers to assist with the project. There may at some point in the future
be special considerations for vendors that choose to support the projects
goals.
<P><A NAME="questions"></A><B>Open-Ended Questions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The problem of documenting
video card operation and behavior is difficult because of the large amount
of information available, and because video hardware is constantly evolving,
making documentation a problem of hitting a moving target. Another problem
is that because video cards are projects of human endeavor and due to their
complexity, their implementation often differs from published specifications.
Even two manufacturer's products based upon the same chipset can contain
enough variation to make them separate cases from a programmer's viewpoint.
The FreeVGA Project attempts to provide answers to the following questions:
<UL>
<LI>
<B>How does one detect what VGA/SVGA adapter is present even when no access
to BIOS is available?</B></LI>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Because video hardware was developed
by many independent vendors along separate evolutionary paths, there is
very little knowledge about how to identify the particular model of video
card present in a machine. Because identifying the particular model is
crucial to utilizing the advanced features of a specific model, this is
an important task that nearly all software written for the SVGA needs to
perform. In many cases, such as when writing programs under an operating
system other than MS-DOS/Windows, it may not be possible nor is it good
practice to access BIOS for determining the specific model. Furthermore,
the more recent PCI bus design is being incorporated into many systems
with non-80x86 chips, such as the PowerPC, Alpha, and even high end workstations.
However, the manufacturers of the hardware may only support Mac and PC
versions of their cards, considering other platforms too much of a niche
market to support. Since their inception in the PC market, most video cards
have had the capability to work with another card (albeit different) in
the same machine. Some newer PCI cards allow multiple cards to be used
in one machine. Until recently this capability has been unsupported by
operating systems and programs. For debugging video routines there is no
equal to having a second monitor attached--one monitor can display the
program's output while the other provides the debugging interface. Note
that the need for a second monitor could be reduced somewhat if better
virtualization of the display hardware was implemented. This project aims
to give programmers the skills and knowledge to better utilize the video
hardware.
<UL>
<LI>
<B>How does one perform standard video operations on a particular card
without utilizing the video BIOS interface?</B></LI>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BIOS was designed to support
MS-DOS programs on the 8086. Computers have progressed far beyond that
point but BIOS has remained basically the same (with the exception of VESA
BIOS.) Even then, most facilities provided by the video BIOS are not particularly
useful. An example is the BIOS Read and Write Pixel commands. These are
the only BIOS provided method of accessing video memory other than text
functions. Anyone like myself who started learning 8086 assembler to speed
up their graphics discovered this function, and said "Cool. This is going
to be easy." I then ran my first program and discovered that I had just
lost a few orders of magnitude of performance. Thus I started to learn
to interact with the video card hardware directly. VESA BIOS is better,
although I have seen very few on-board implementations that work properly
(if present), usually resulting in the user having to run a TSR program
that provides VESA services in RAM. While VESA BIOS does provide some facilities
for non-real mode problems it still does place a function call penalty
on video code. My biggest complaint is that with VESA BIOS you are restricted
to programming to the lowest common denominator of all video hardware,
and thus to utilize any special features of a chipset, you still have to
learn to program the card directly. Many video cards are now considered
"obsolete" by their manufacturer (or the manufacturer has joined the great
corporation in the sky...) and developer support is no longer available.
The unfortunate problem is that these "obsolete" cards are the same cards
being used by non-profit organizations and schools who could otherwise
reap the benefits of a wide variety of free software.
<UL>
<LI>
<B>What are the specialized hardware features (2D/3D acceleration, hardware
cursor, video acceleration, etc.) does a particular card have and how does
one utilize these features?</B></LI>
</UL>
<B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>This is probably the area where
the documentation is most important. These features are programmed differently
on each vendor's video hardware, but can improve the performance of a particular
application by several orders of magnitude. Programmers such as video game
programmers and assembly demo programmers have demonstrated that by pushing
hardware to its limits, previously inconceivable animation and special
effects are possible. Recent advances in 3D acceleration have made virtual
reality on the desktop a possibility. It is crucial to developers that
they be able to thoroughly understand the hardware's operation to maximize
its performance.
<UL>
<LI>
<B>What are the differences between specific implementations of particular
chipsets, and if so how does one write software that works with these differences?</B></LI>
</UL>
<B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>Even programmers programming for
the relatively standard VGA hardware can run into problems in this area.
This is the reason so many packages state support for IBM VGA or 100% compatible.
Frequently programmers encounter slight differences in hardware that, under
specific circumstances can cause their programs to fail to operate properly.
If programmers had detailed documentation of the hardware differences of
specific implementations, programmers could, and are generally willing
to, write workarounds in their code in order to provide support for this
hardware. Occasionally subtle hardware problems arise in a particular version
of a board and is corrected in a later revision (possibly by simply revising
the BIOS.) It is important to recognize the earlier version and be able
to write software that can deal with its particular problem. In addition,
many chipsets are designed in such a way that they can work with a variety
of support devices such as clock generators and Video DACs. It is important
to know how to detect and control these support devices, which may (and
usually is) be different in every implementation. Some of these devices
could be interchanged with pin-compatible devices which could provide additional
functionality. However, this would require special programming to utilize
the device's features.
<UL>
<LI>
<B>How does one perform diagnostics on a particular video card in order
to identify inoperative, semi-inoperative, and improperly configured hardware?</B></LI>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; While testing and verifying the operation
of various video boards. I discovered some cards that did not respond properly
to my programming. My initial thought was that I was doing something wrong
and tried to figure out what was wrong. However, further testing on another
identical card demonstrated that the first board had simply failed. There
is little diagnostic software for the VGA and SVGA adapters particularly
when dealing with some of the more esoteric features. This is primarily
because little has been identified about the correct behavior of video
cards. Many manufacturers fail to include a thorough diagnostics utility
with their hardware, and the diagnostics that are provided are usually
specific to one operating system.
<UL>
<LI>
<B>How does one properly emulate a particular VGA/SVGA adapter in order
to properly implement compatibility for legacy full-screen applications?</B></LI>
</UL>
<B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>This is a particular
are of interest to myself and others. This knowledge can be used to create
a virtual machine capable of multitasking legacy applications. Particular
features that could be provided are the ability to execute a full-screen
program in the background, execute a full-screen program in a virtual window
on a desktop, emulate a particular video adapter and translate its output
to a form compatible with the hardware on the machine, provide the ability
to remotely view an applications screen across a network, provide the ability
to debug a full-screen application without having to use a dual monitor
system or attached text terminal. Huge benefits can be reaped, but all
of the details of a particular hardware configuration must be known for
proper emulation/virtualization. For example, programs that attempt to
autodetect the hardware often rely on undocumented behaviors of video adapters.
These undocumented behaviors must be emulated properly for the application
to work properly.
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.&nbsp;<IMG SRC="http://www.goodnet.com/~tinara/cgi-bin/imgserv.cgi?logo2.gif" >
</BODY>
</HTML>

100
specs/freevga/glossary.htm Normal file
View File

@@ -0,0 +1,100 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA - Video Programming Glossary</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="home.htm#background">Back</A></CENTER>
<CENTER># | A | B | <A HREF="#C">C</A> | <A HREF="#D">D</A> | E | <A HREF="#F">F</A>
| G | H | I | J | K | L | M | N | O | <A HREF="#P">P</A> | Q | <A HREF="#R">R</A>
| <A HREF="#S">S</A> | T | U | <A HREF="#V">V</A> | W | X | Y | Z</CENTER>
<CENTER>
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>Video Programming Glossary&nbsp;
<HR></CENTER>
<B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This page is a glossary
covering video programming related terms.&nbsp; It is extremely difficult
for me to determine which terms should be included in this page, thus if
you have come here looking for a particular term and are dismayed at not
finding it listed here, please send a note with the <A HREF="feedback.htm">Feedback
Form</A> including the term in the body of the message, and it will be
added here.
<CENTER><A NAME="C"></A><B>------ C ------</B></CENTER>
<P><B>CLUT</B> -- see <A HREF="#CLUT">Color Look-Up Table</A>
<P><A NAME="CLUT"></A><B>Color Look-Up Table</B> -- <A HREF="#PLUT">see
Palette Look-Up Table</A>
<BR>&nbsp;
<BR>&nbsp;
<CENTER><A NAME="D"></A><B>------ D ------</B></CENTER>
<P><A NAME="DAC"></A><B>DAC</B> -- acronym for Digital to Analog Converter,
which is a integrated circuit that converts intensity values to analog
signal values.&nbsp; This is used in video chipsets to produce the analog
signals that are sent to the monitor.&nbsp; Some DACs, known as RAMDACs
contain a palette look-up table.
<P><B>Digital to Analog Converter</B> -- see <A HREF="#DAC">DAC</A>
<CENTER><A NAME="F"></A><B>------ F ------</B></CENTER>
<P><B>Frame Buffer</B> -- RAM that is part of the graphics hardware that
stores the pixel values that are converted into color intensity.
<CENTER><A NAME="P"></A><B>------ P ------</B></CENTER>
<P><A NAME="PLUT"></A><B>Palette Look-Up Table</B> -- a small table of
RAM that contains a set of <A HREF="#RGB">RGB</A> intensity values for
each index, of which there are 256 locations.&nbsp; The information in
this table is used by the <A HREF="#DAC">DAC</A> to generate the analog
signal. Also known as a Color Look-Up Table or CLUT.
<CENTER><A NAME="R"></A><B>------ R ------</B></CENTER>
<P><B>RAMDAC</B> -- A <A HREF="#DAC">DAC</A> that contains a built-in <A HREF="#PLUT">palette
look-up table</A>.
<P><A NAME="RGB"></A><B>RGB</B> -- acronym for Red, Blue &amp; Green, which
describes the three primary colors of light that a CRT generates to produce
the range of visible colors.
<CENTER><A NAME="S"></A><B>------ S ------</B></CENTER>
<P><B>Super VGA</B> -- see <A HREF="SVGA">SVGA</A>
<P><A NAME="SVGA"></A><B>SVGA </B>-- acronym for Super-<A HREF="#VGA">VGA</A>,
which is a term applied to chipsets and the advanced functionality of those
chipsets that are above and beyond the capabilities of the original IBM
<A HREF="#VGA">VGA</A> chipset.
<CENTER><A NAME="V"></A><B>------ V ------</B></CENTER>
<P><A NAME="VGA"></A><B>VGA</B> -- acronym for Video Graphics Array, which
is the term for IBM's successor to the EGA graphics chipset.&nbsp; This
term is also used when describing register compatible functions of other
chipsets such as SVGA chipsets.
<P><B>Video Graphics Array</B> -- see <A HREF="VGA">VGA</A>
<BR>&nbsp;
<BR>&nbsp;
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

92
specs/freevga/hardovr.htm Normal file
View File

@@ -0,0 +1,92 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA - Overview of Video Hardware Functionality</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="#intro">Introduction</A> <A HREF="#frame">Frame
Buffer</A> <A HREF="#graphics">Graphics Controller</A> <A HREF="#display generation">Display
Generation</A> <A HREF="home.htm#background">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>Overview of Video Hardware Functionality&nbsp;
<HR></CENTER>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This page contains a general
overview of the functionality of VGA and SVGA cards into various sections,
and gives a description of the functions of each section.&nbsp; This is
intended to be a general description for those unfamiliar to the functionality
and capabilities of graphics hardware.&nbsp; The basic function of graphics
hardware is to allow the CPU to manipulate memory specific to the graphics
hardware, and to take the information stored in that memory and output
it in a form that a monitor or LCD panel can use.
<P><A NAME="frame"></A><B>Frame Buffer</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This is the component of
the video hardware that stores the pixels and information to be displayed
on the monitor.&nbsp; This is the center of the video hardware, as nearly
all operations are performed on or using this data.&nbsp; The frame buffer
is a form of RAM, which is typically located outside the main graphics
chip and are implemented using DRAM chips; however, more sophisticated
forms of RAM that are ideal for video hardware applications, such as VRAM.&nbsp;
The amount of video memory that is present determines the maximum resolution
that the hardware can generate.&nbsp; The frame buffer is usually mapped
into a region of the host CPU's address space allowing it to be accessed
as if it were a portion of the main memory.&nbsp; For example, in the VGA,
this memory is mapped into the lower 1M of the CPU address space, allowing
it to be directly accessable to real mode applications, which cannot directly
access the remaining memory.&nbsp; In the VGA, this memory is broken up
into 4 separate color planes, which are recombined to produce the actual
pixel values at the time of display generation.
<P><A NAME="graphics"></A><B>Graphics Controller</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This is the video chipset's
host interface to the frame buffer, and is part of the main graphics chip
or chips.&nbsp; It allows the host CPU to manipulate the frame buffer in
a fashion suited to the task of graphics operations.&nbsp; It allows certain
methods of access that are designed to reduced the CPU requirements for
performing standard video operations, particularly in accelerated chipsets,
which can have a quite complicated set of access methods which can include
line drawing, area and pattern fill, color conversion/expansion, and even
3d rendering acceleration.&nbsp; For example, in the VGA the graphics controller
allows one write by the CPU to its mapped memory region below 1M to affect
all four color planes, as well as allowing faster transfers of video data
from one region to another in video memory.
<P><A NAME="display generation"></A><B>Display Generation</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This portion of the graphics
hardware is involved in taking the data in the frame buffer, converting
the pixel or character information stored by the graphics controller, and
converting it into the analog signals required by the monitor or lcd display.&nbsp;
The pixel data is first sequenced, or read serially from the frame buffer,
then converted into analog color information, either by a palette look-up
table, or by directly converting into red, green, and blue components.&nbsp;
The CRT controller at the same time adds timing signals that allow the
monitor to display the analog color information on the display.&nbsp; For
example, in the VGA these components are made up of the sequencer, attribute
controller, CRT controller, DAC, and palette table.&nbsp; The sequencer
reads the information from the frame buffer, and converts it into pixel
color information, as well as sends signals to the CRT controller such
that it can provide the timing signals the monitor requires.&nbsp; This
color information is formatted by the attribute controller in such a way
that the pixel values can be submitted to the DAC.&nbsp; The DAC then looks
up these values in its palette table which contains red, green, and blue
intensities for each of the colors that the attribute controller generates,
then converts it into an analog signal that is output to the VGA connector
along with the timing signals generated by the CRT controller.&nbsp; If
the display is an LCD panel such as found in laptops, the DAC and associated
support hardware convert the pixel values to signals that the LCD panel
displays directly.
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
</BODY>
</HTML>

127
specs/freevga/hardrec.htm Normal file
View File

@@ -0,0 +1,127 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA - Product Recommendations for Video Developers</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="#intro">Introduction</A> <A HREF="#monitors">Recommended</A>
<A HREF="#failures">Failed</A> <A HREF="#test">Test</A> <A HREF="home.htm#product">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Product Recommendations for Video Developers&nbsp;
<HR WIDTH="100%"></CENTER>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This page is to provide
hardware recommendations for those implementing the information on this
site.&nbsp; There are no recommendations for video cards, as the goal is
to increase programmer support for all cards, existing or otherwise, rather
than try to influence people to buy a specific video card implementation.&nbsp;
I will, however recommend hardware, other than the video cards themselves
that are helpful in the development of software for video cards in general.
Monitors are a strong issue to me, both for safety concerns, and financial
concerns, as it is usually advantageous to buy an new, indestructable monitor
than to burn through many cheap, expendable monitors.
<P><B>&nbsp;<A NAME="monitors"></A>Monitors Recommended</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For a monitor to be recommended
it must meet all of the following criteria:
<UL>
<LI>
It should be able to tolerate improperly formed video inputs for an extended
period of time without the possibility of being damaged.&nbsp; It should
also be tolerant to extremely frequent mode changes.&nbsp; Damage due to
this kind of operation should not be excluded by the standard manufacturer's
warranty.&nbsp; This is critical due to the replacement cost of high-performance
monitors, and due to the possible safety and fire hazards failing monitors
may cause.</LI>
<LI>
It should be able to synchronize to a wide variety of properly formed signals,
including both standard and custom video timings.&nbsp; This important
for developing the modes required for special applications.</LI>
<LI>
It should handle the maximum frequencies/resolutions that can be generated
by current and future (to a reasonable extent) video chipsets.</LI>
<LI>
It should be compliant to all levels of display to host communication and
power mamagement so code can be developed that implements these features
of the video hardware.</LI>
<LI>
If the monitor allows the picture controls to be saved/restored on changes
in mode, it should be allowed to defeat this feature so that the generated
video timings can be adjusted to minimize the visible effects of mode change.</LI>
<LI>
It should be currently available on the market and covered by manufacturers
warranty for the period of time required to develop the desired application.</LI>
<LI>
It has been put through my own personal monitor torture tests, as well
as operated for an extended period of time under conditions related to
video software development.</LI>
</UL>
The following monitors have been evaluated by myself personally, and have
been determined to meet all these criteria.
<UL>
<LI>
At this time, there are no monitors that I have determined meet all these
criteria.</LI>
</UL>
<A NAME="failures"></A><B>Monitor Failures</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section lists monitors
that have either died for me while testing, or have died for others in
a fashion that would imply that the programmer was responsible for their
failure.&nbsp; This does not imply that the programmer was at fault, as
these things naturally happen when developing drivers.&nbsp; I strongly
recommend the purchase of one of the recommended monitors, to avoid damaging
a valuable monitor
<P><B>Compaq VGA (not SVGA)</B> -- I do not know the model specifically.&nbsp;
It was a fixed frequency model, and the horizontal circuitry was damaged.&nbsp;
The problem was repeatable after repairs were made, so I believe that the
monitor can be damaged by normal mode testing. I have met others who claim
to have experienced this same problem.&nbsp; Not recommended.
<P><B>CTX CMS-1561LR</B> -- The problem with this monitor occured when
driving the monitor at the high end of its frequency envelope.&nbsp; The
monitor synced to the frequency, but may have been slightly overdriven.&nbsp;
The horizontal output transistor and some capacitors were replaced and
the monitor was restored to working order.&nbsp; The problem has not been
repeated, so ordinary failure is likely.
<P><B>NCR MBR 2321</B> -- This one comes from a friend in Fayetteville,
AR, whose monitor blew caps while writing a svgalib video driver.&nbsp;
The explosion from the capacitors shattered the rear of the picture tube,
damaging the monitor beyond repair.&nbsp; Not recommended due to the catastrophic
nature of the failure.&nbsp; The operation being performed when the failure
occurred was frequent mode changing.
<P><A NAME="test"></A><B>Test Equipment Recommended</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; There are certain pieces
of test equipment that can come in handy when working with video cards.&nbsp;
This can be especially important when verifying that the video signal being
generated is, in fact the one intended by the programmer.&nbsp; Failure
to do this can cause catastrophic failure when the driver is used in conjunction
with a fixed-frequency or other monitor that can be damaged by improper
inputs.
<UL>
<LI>
At this time, I cannot recommend any test equipment other than a good frequency
counter, as this is really not in my area of expertise.&nbsp; If you can
help me in my research into this, I would be greatly appreciative.</LI>
</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.&nbsp;<IMG SRC="http://www.goodnet.com/~tinara/cgi-bin/imgserv.cgi?logo3.gif" >
</BODY>
</HTML>

486
specs/freevga/home.htm Normal file
View File

@@ -0,0 +1,486 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA Project Home - Hardware level VGA and SVGA programming info</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="#news">News</A> <A HREF="#mirrors">Mirrors</A>
<A HREF="#preface">Preface</A> <A HREF="#background">Background</A> <A HREF="#vga">VGA</A>
<A HREF="#svga">SVGA</A> <A HREF="#tricks">Tricks</A> <A HREF="#references">Links</A>
<A HREF="#warn">Disclaimer</A> <A HREF="#product">Products</A> <A HREF="#feedback">Feedback</A>
<A HREF="home.htm">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>Home&nbsp;
<HR WIDTH="100%"></CENTER>
<CENTER>&nbsp;</CENTER>
<CENTER><TABLE BORDER WIDTH="600" CELLPADING="2" >
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"><FONT SIZE=+4>F</FONT></TD>
<TD WIDTH="75"><FONT SIZE=+4>R</FONT></TD>
<TD WIDTH="75"><FONT SIZE=+4>E</FONT></TD>
<TD WIDTH="75"><FONT SIZE=+4>E</FONT></TD>
<TD WIDTH="75"><FONT SIZE=+4>&nbsp;</FONT></TD>
<TD WIDTH="75"><FONT SIZE=+4>V</FONT></TD>
<TD WIDTH="75"><FONT SIZE=+4>G</FONT></TD>
<TD WIDTH="75"><FONT SIZE=+4>A</FONT></TD>
</TR>
</TABLE></CENTER>
<CENTER>This page is home to the <A HREF="freevga.htm">FreeVGA Project</A>
-- dedicated to providing a totally FREE source of information about video
hardware.&nbsp; <A HREF="freevga.htm">Additional goals/information are
located here.</A></CENTER>
<CENTER>"Keep on rocking in the free world." - Neil Young</CENTER>
<P><A NAME="news"></A><B>Latest News</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 08/01/1998</B> -- More
information is now up, including a large portion of the "standard" VGA
reference.&nbsp; Some other minor changes have been made to other information.&nbsp;
Expect more updates in the not too far future.
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <B>06/20/1998</B> -- The
work contiues.&nbsp; Added three new mirrors.&nbsp; Some of the information
that was located in the VGA reference, but really applies to video programming
in general has been moved to the new Background Information (formerly Introduction)
section of this page, and has been released.&nbsp; Also, a glossary has
been added defining terms related to video programming, but is not very
comprehensive at the moment, although this should improve over time. Many
minor corrections have been made to the released material after being pointed
out by the insightful people reading the information.&nbsp; Thank you!
<P><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 06/08/1998</B> -- The
mirror list has been updated with the new entries. Special thanks goes
out to all those who have donated their personal resources to advance the
project's goals.&nbsp; Also, the first section of *real* information is
online, the low-level programming introduction.&nbsp; This section has
been relatively stable for quite some time, and seems to be releasable.&nbsp;
It is my goal to release the information after it stabilizes, and has been
verified for accuracy.
<P><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 06/04/1998</B> --<B> </B>If
you are looking for the current work-in-progress, and have been given the
passwords for the archive for review purposes, it can be downloaded <A HREF="http://www.goodnet.com/~tinara/wip.zip">here</A>.&nbsp;
For those with current problems/questions that this page addresses, please
feel free to use the <A HREF="#feedback">Feedback Form</A> to contact the
author.&nbsp; If a link is marked with <B>(WIP)</B>, it is not posted online
and at this time is available only for review, upon request, and under
specific limitations.
<P><A NAME="mirrors"></A><B>Mirror Sites</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; At this time, the project
is experimenting with the feasibility of maintaining mirror sites to make
this information more widely available.&nbsp; The following mirror sites
are provided for your convenience.&nbsp; If you are interested in hosting
a mirror site of this information, please contact the author for more information.
If you are experiencing problems with any of these mirrors please use the
<A HREF="#feedback">Feedback Form</A> to contact the author, as it is likely
my fault that the problem has arisen.
<UL>
<LI>
<A HREF="http://www.goodnet.com/~tinara/FreeVGA/home.htm">USA, Arizona,
Phoenix</A> -- hosted by <A HREF="feedback.htm">Joshua Neal</A></LI>
<LI>
<A HREF="http://sf.znet.com/~vhold/FreeVGA/home.htm">USA, California, San
Francisco</A> -- hosted by <A HREF="http://sf.znet.com/~vhold/">Marty Price</A></LI>
<LI>
<A HREF="http://hardware.doa.org/FreeVGA/home.htm">USA, Massachusetts,
Boston</A> -- hosted by <A HREF="http://hardware.doa.org/">Leif Hardison</A></LI>
<LI>
<A HREF="http://www.pacwest.net/byron13/FreeVGA/home.htm">USA, Oregon,
Eugene</A> -- hosted by <A HREF="http://www.pacwest.net/byron13/">Byron
Miller</A></LI>
<LI>
<A HREF="http://hups.apana.org.au/~scuffer/FreeVGA/home.htm">Australia,
Canberra</A> -- hosted by <A HREF="http://hups.apana.org.au/~scuffer/">David
Murn</A></LI>
<LI>
<A HREF="http://nightmare.euroweb.hu/~ytiddo/FreeVGA/home.htm">Hungary</A>
-- hosted by <A HREF="http://nightmare.euroweb.hu/~ytiddo/">Justin Doiel</A></LI>
<LI>
<A HREF="http://www.inter.uunet.nl/hcc/S.Weijgers/FreeVGA/home.htm">The
Netherlands, Apeldoorn</A> -- hosted by <A HREF="http://web.inter.nl.net/hcc/S.Weijgers/">Simon
Weijgers</A></LI>
<LI>
<A HREF="http://n152.apeldoorn.telekabel.euronet.nl/FreeVGA/home.htm">The
Netherlands, Nijmegen</A> -- hosted by <A HREF="http://web.inter.nl.net/hcc/S.Weijgers/">Simon
Weijgers</A></LI>
</UL>
<A NAME="preface"></A><B>Preface</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This page's purpose is to
provide free low-level programming information to programmers interested
in the low-level details of programming the VGA and Super VGA adapters,
in a format independent of operating environment or programming language.
This page is not intended to be a reference to graphics or game programming
algorithms but rather a reference for those people attempting to implement
such algorithms in whatever environment they are using. This page is not
intended to be a showcase of web technology and thus will use HTML features
and graphics only when it is necessary to convey information. For example,
I have left the colors and fonts set to the default, so you can actually
use the default preferences in your browser. I am continuously adding material
to this page and have tried to incorporate links to other sites with valuable
information.
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- An introduction to low-level programming</LI>
<LI>
<A HREF="#vga">Standard VGA Chipset Reference</A> -- Documents the common
functionality of all VGA and SVGA adapters.</LI>
<LI>
<A HREF="#svga">Super VGA Hardware Chipset Reference</A> -- Documents the
specifics of VGA and SVGA adapters.</LI>
<LI>
<A HREF="#other">Other Video Hardware Reference</A> -- Documents video
related hardware other than VGA and SVGA adapters.</LI>
<LI>
<A HREF="#tricks">Tricks and Techniques</A> -- Articles detailing the use
of low-level programming for optimization or special effects.</LI>
<LI>
<A HREF="#references">Other References</A> -- Gives pointers to other related
material.</LI>
<LI>
<A HREF="#warn">Warnings and Disclaimer</A> -- Reading this section before
utilizing any information contained within is both recommended and required.</LI>
</UL>
<A NAME="background"></A><B>Background Information</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Foremost, this page is meant
to be a place online where one can learn about low-level programming (If
everyone knew all of this information then this page would be redundant!)
This section contains general information that can be very helpful when
attempting to use the programming information located on this site.
<UL>
<LI>
<A HREF="llintro.htm">Introduction to Low-level Programming</A> -- Answers
general questions about the topic. <B>(Released 6/08/1998)</B></LI>
<LI>
<A HREF="hardovr.htm">Overview of Video Hardware Functionality</A> -- Describes
the job of the video hardware and what components it uses to perform that
task. <B>(Released 6/15/1998)</B></LI>
<LI>
<A HREF="vtiming.htm">Video Timing Information</A> -- Gives information
about video timing that is useful for video programmers.<B> (Released 6/15/98)</B></LI>
<LI>
<A HREF="glossary.htm">Video Programming Glossary</A> -- Defines terms
that are related to video programming. <B>(Added 6/15/1998)</B></LI>
</UL>
<A NAME="vga"></A><B>Standard VGA Chipset Reference</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>This section documents
the subset of functionality present on nearly all computers today. The
VGA BIOS utilizes only a fraction of the capability of the VGA hardware.
By programming the hardware at the lowest level, one gains the flexibility
to unleash the hardware's full potential.
<UL>
<LI>
<A HREF="vga/vga.htm">VGA Chipset Reference</A> -- Documentation of the
"Standard" VGA implementation. <B>(Released 8/01/1998)</B></LI>
</UL>
<A NAME="svga"></A><B>Super VGA Hardware Chipset Reference</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section documents the
known functionality of specific VGA/SVGA chipsets. Because developers of
chipsets and video cards face incredible competition, they have added features
and functionality far beyond the standard VGA hardware. Unfortunately to
programmers, these features have been implemented differently in each particular
chipset, and even differently between products by the same manufacturer.
It is difficult to obtaining information on these chipsets and their implementations,
particularly so if the chipset is considered "obsolete" by the manufacturer.
Because of the open-ended nature of this topic (chipsets are under constant
development) this page will be updated constantly as new information becomes
available.
<UL>
<LI>
<A HREF="svga/svga.htm">SVGA Chipset Reference</A> -- Documentation of
specific VGA/SVGA hardware implementations. <B>(WIP)</B></LI>
</UL>
<A NAME="other"></A><B>Other Video Hardware Reference</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</B> This section is for
video hardware that does not specifically fit into the category of VGA
or SVGA, such as MPEG hardware, video capture hardware, non-integrated
3D accelerators, virtual reality gear, digital video cameras, stereoscopic
3D goggles, TV tuner cards, non-VGA compatible video adapters and the like.
This is another open-ended topic but is not the primary focus of this page.
<P><A NAME="tricks"></A><B>Tricks and Techniques</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section contains useful
information on how to utilize the VGA/SVGA hardware to optimize specific
tasks or implement visual effects. Many of these techniques have been utilized
by game and demo programmers alike to push the envelope of the hardware's
capacity.
<UL>
<LI>
<A HREF="tricks/tricks.htm">Tricks and Techniques</A> -- Details on using
the hardware to your advantage. <B>(WIP)</B></LI>
</UL>
<A NAME="references"></A><B>Other References:</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>This section gives
some pointers to other available VGA hardware information available. Note
that they are listed here because
<UL>
<LI>
<B>Online Information</B></LI>
<UL>
<LI>
The <A HREF="http://www.heartlab.rri.uwo.ca/vidfaq/">COMP.SYS.IBM.PC.HARDWARE.VIDEO
Frequently Asked Questions (FAQ)</A> document, although not programming
oriented does contain much useful information about video hardware. The
site also includes links to nearly every vendor of video cards and monitors,
as well as links to pages covering monitor specifications. If you are looking
for video hardware related information not covered by the FreeVGA Project's
goals, you will likely find it or a link to it here.</LI>
<LI>
Finn Th&oslash;gersen's <A HREF="http://www.datashopper.dk/~finth/">VGADOC
&amp; WHATVGA Homepage</A> -- An excellent collection of information for
programming VGA and SVGA.</LI>
<LI>
Boone's <A HREF="http://www.strangecreations.com/library/hardware/vgaregs.txt">Programming
the VGA Registers</A> -- Contains a very sketchy "Documentation Over the
I/O Registers for Standard VGA Cards" by "Shaggy of The Yellow One." It
is free and distributable over the "Feel free to spread this to whoever
wants it....." licensing agreement.</LI>
<LI>
Andrew Scott's <I>VGA Programmers Master Reference Manual</I> (<A HREF="ftp://ftp.cdrom.com/pub/demos/code/hardware/video/vga-info.zip">click
here to download from ftp.cdrom.com</A>) -- A dated ('91) document that
is interesting if only because it attempts to document the VGA hardware
(actually the Trident TVGA8900 hardware) in a form useful for "writing
an applications specific BIOS." Begins with a very general description
the topic (a wordy definition of computation in general) and ends with
detailed register descriptions. Unfortunately, it lacks much material between
these areas. Worse, far from being a free resource, it requires shareware
registration fees that must be sent to the U.K. by means of a check drawn
from a U.K. bank only!</LI>
<LI>
Richard Wilton's <I>Programmer's Guide to PC and PS/2 Video Systems</I>
(<A HREF="http://www.dc.ee/Files/Programm.Docs/videoprg.arj">click here
to download from www.dc.ee</A>) An older reference, covers MDA, Hercules,
CGA, MCGA, and VGA. Not much VGA material but does have some register documentation.</LI>
<LI>
IBM's RS/6000 <I>CHRP I/O Device Reference</I> <A HREF="http://www.rs6000.ibm.com/resource/technology/chrpio/vga_app.mak.html">Appendix
A: VGA Programming Model</A> -- A good VGA reference from the makers of
the IBM VGA. Better than most on-line references as it contains programming
information in addition to a register description of the hardware; however
it is still vague in many areas. Especially interesting as it begins with
an acknowledgment of the many "clones" of the VGA hardware.</LI>
<LI>
Some brief VGA register info is available from the <A HREF="http://www.hitex.com/chipdir/reg/vga.txt">Chip
Directory</A>, also mirrored at other sites (see <A HREF="http://www.hitex.com/chipdir/">Chip
Directory home page</A>).</LI>
<LI>
Eric S. Raymond's <A HREF="http://sunsite.unc.edu/LDP/HOWTO/XFree86-Video-Timings-HOWTO.html">The
XFree86 Video Timings HOWTO</A> -- explains video mode and timing information
used in configuring XFree86 to support a given monitor, intended to be
used by the end user.&nbsp; Much of the information is not sepcific to
XFree86, and can be used by a programmer as an example of how a low-level
video routine can allow the end-users to setup video modes that pertain
to their monitors, as well as being useful to an end-user of such a program
attempting to configure such a routine to work with their monitors.</LI>
<LI>
Tomi Engdahl's <A HREF="http://www.hut.fi/Misc/Electronics/docs/">electronics
info page</A> has some information about video and vga timings, as well
as a section on VGA to TV converters and homemade circuitry.&nbsp; The
<A HREF="http://www.hut.fi/Misc/Electronics/circuits/vga2tv/cindex.html">VGA
to TV converter page</A> contans much information that pertains to driving
custom TV and monitors with a VGA or SVGA card that doesn't have the capability
built-in.</LI>
</UL>
<LI>
<B>Offline Information</B></LI>
<UL>
<LI>
Richard F. Ferraro's<B> </B><I>Programmer's Guide to the EGA, VGA, and
Super VGA Cards, Third Edition</I> -- A good text, one of the few good
books on a subject as broad and as complicated as low-level I/O.</LI>
<LI>
Frank van Gilluwe's <I>The Undocumented PC, Second Edition -- A Programmer's
Guide to I/O, CPUs and Fixed Memory Areas</I> -- An excellent book, which
is the likely the most complete PC technical reference ever written, and
includes 100+ pages of video programming information, although very little
VGA register information.</LI>
<LI>
Bertelsons, Rasch &amp; Hoffman's PC Underground: Unconventional Programming
Topics -- I bought this book on markdown, due to it having some VGA information
in it.&nbsp; I was surprised to find that not only did it have a register
description, but it also described some possible effects that can be done
with that register.</LI>
</UL>
<LI>
<B>Miscellaneous Information (Information not specific to video hardware,
but useful to video programmers.)</B></LI>
<UL>
<LI>
Norman Walsh's <A HREF="http://nwalsh.com/comp.fonts/FAQ/index.html">The
comp.fonts FAQ</A> -- An excellent resource on fonts, typefaces, and such.&nbsp;
Particularly helpful is the section on intellectual property protection
for fonts, as the copyright legality of fonts and typefaces is somewhat
confusing.&nbsp; Note -- Norman Walsh has ceased maintaining the FAQ, however,
this link will remain until a new version of the FAQ is produced.</LI>
</UL>
</UL>
<A NAME="product"></A><B>Product Recommendations</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The FreeVGA Project does
not make hardware recommendations as pertains to hardware covered by the
documentation, in an attempt to prevent any conflicts of interest.&nbsp;
However, there are other products that can be extremely helpful when implementing
the information found here, such as monitors, test equipment, and software.&nbsp;
I will not refuse any request to list a product on this page, however I
will categorize it depending upon its importance and suitability for video
related software development using opinions of myself and others.&nbsp;
If you disagree with the opinion here, please use the Feedback Form to
voice that opinion, such that it can be taken into account.
<UL>
<LI>
<A HREF="hardrec.htm">Product Recommendations</A> -- Listing of products
that can be beneficial to the target audience of this site.</LI>
</UL>
<A NAME="warn"></A><B>Warnings and Disclaimer</B>
<UL>
<LI>
<B><U>Danger</U>: </B>Monitors are designed to operate within certain frequency
ranges, or for fixed frequency monitors at certain frequencies.<B> <U>Driving
a monitor at a frequency that it is not designed for is not recommended
and may cause damage to the monitor's circuitry which can result in a fire
and safety risk</U>. </B>It is wise to know and understand the specifications
of the monitor(s) that you will be driving in order to prevent damage.
Consult the manufacturers documentation for the monitor for the information,
or if not available, contact the manufacturer directly.&nbsp; If the monitor
makes unusual noises, or the internal temperature exceeds the rated temperature
of its components, the monitor is likely to experience failure.&nbsp; This
failure may not be immediate, but is under most circumstances inevitable.&nbsp;<B>
<U>Monitor failures can be violent in nature, and can explode and produce
shrapnel, as well as overheat and catch fire</U>.&nbsp; </B>In no circumstance
should one leave a monitor unattended in an uncertain state.&nbsp; Furthermore,
exceeding the rated maximum frequencies of a monitor may cause the phosphors
to age prematurely, as well as<B> <U>increase the amount of harmful radiation
projected towards the viewer beyond the specified maximums</U>.</B></LI>
<LI>
<B><U>Warning</U>: </B>Clock chips and RAMDACs as well as other components
of the video card are designed with a maximum frequency.<B> <U>Programming
these chips to operate at a frequency greater than they were designed for
causes the chips to run hotter than they were designed to operate, and
may cause the component to fail</U>. </B>It is wise to know and understand
the maximum operating frequency of the components of any video subsystem
you will be programming. Do not assume that the component is safe to operate
at a particular frequency because it can be programmed to operate at that
frequency.&nbsp; The rated frequencies are rated and verified according
to batch yield.&nbsp; As clock frequencies increase, the failure rate of
the chips during manufacturing testing increases.&nbsp; It is impossible
to predict the actual point at which a given semiconductor will fail, thus
manufacturers monitor the failure rate statistically to determine the frequency
that gives an acceptable batch yield.&nbsp; <B><U>These failures are typically
unobservable and require a method of testing every gate on the chip, as
many failures may only be observable under very specific circumstances,
typically resulting in intermittent failures, although complete "meltdown"
due to a newly formed short is also possible.</U></B>&nbsp;&nbsp; If they
occur, the entire semiconductor must be rejected due to these failures
being irrepairable.&nbsp; As you exceed the rated frequency you are taking
a semiconductor that has passed a thourough test at its rated frequency
and entering the realm of statistical probability.&nbsp; Attempting to
find the maximum frequency is impossible, as by the time a failure is noticable
the semiconductor has already been permanently damaged.&nbsp; Cooling the
external package by using a heat sink and/or fan may increase the frequency
at which a semiconductor can operate; however, there is still no way to
determine the frequency at which a specific semiconductor will fail as
it can only be done statistically and practically undetectable without
being able to determine the proper operation of every gate on the semiconductor.&nbsp;
Semiconductors such as fast CPU's are rated with the required heat sink
and/or cooling fan in place.&nbsp; Aftermarket cooling devices are sold
as "performance coolers" due to the inability to determine the statistical
likelyhood of failure and the inability of the end user to simply reject
failed semiconductors.&nbsp; <B><U>Under no circumstances should a programmer
develop software that overclocks an end-user's hardware without the end
user being warned of the statistical likelyhood of failure.</U></B>&nbsp;
Making any claims about the safety of the software's operation can leave
the programmer with legal liability that cannot be excluded by disclaimer.</LI>
<LI>
<B><U>Disclaimer</U>: The author presents this information as-is without
any warranty, including suitability for intended purpose. The author is
not responsible for damages resulting by the use of the information, incidental
or otherwise. By utilizing this information, you as the programmer take
full liability for any damages caused by your use of this information.
If you are not satisfied with these terms, then your only recourse is to
not use this information. While every reasonable effort is made to ensure
that this information is correct, the possibility exists for error and
is not guaranteed for accuracy, and disclaims liability for any changes,
errors or omissions and is not responsible for any damages that may arise
from the use or misuse of this information.&nbsp; License to use this information
is only granted where this disclaimer applies in whole.</B></LI>
</UL>
<A NAME="feedback"></A><B>Feedback</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I can be reached online
via the <A HREF="feedback.htm">Feedback Form</A>.&nbsp; Consider it your
moral obligation to send feedback about the page, including inaccuracies,
confusing parts, missing info, questions/answers and other feedback type
thingies.
<BR>&nbsp;
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.&nbsp;<IMG SRC="http://www.goodnet.com/~tinara/cgi-bin/imgserv.cgi?logo.gif" >
</BODY>
</HTML>

124
specs/freevga/license.htm Normal file
View File

@@ -0,0 +1,124 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA Copyright License</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="home.htm#vga">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>FreeVGA Project Copyright License&nbsp;
<HR></CENTER>
<B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This document contains the
FreeVGA Copyright License which states the conditions under which the FreeVGA
Project's Copyrighted information may be used and distributed.&nbsp; The
conditions of this license ensure that all parties with a need for this
information have the same availability, to the maximum extent possible
as well as ensure the integrity of the documentation.
<P><B>Disclaimer</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The author presents this
information as-is without any warranty, including suitability for intended
purpose. The author is not responsible for damages resulting by the use
of the information, incidental or otherwise. By utilizing this information,
you as the programmer take full liability for any damages caused by your
use of this information. If you are not satisfied with these terms, then
your only recourse is to not use this information. While every reasonable
effort is made to ensure that this information is correct, the possibility
exists for error and is not guaranteed for accuracy, and disclaims liability
for any changes, errors or omissions and is not responsible for any damages
that may arise from the use or misuse of this information.&nbsp; License
to use this information is only granted where this disclaimer applies in
whole.
<P><B>License</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The following copyright
license applies to all works by the FreeVGA Project. All of the FreeVGA
Project's documentation is copyrighted by its author, Joshua Neal.
<P>License to utilize the FreeVGA Project documentation is subject to the
following conditions:
<UL>
<LI>
The copyright notice and this permission notice must be preserved complete
on all copies, complete or partial.</LI>
<LI>
Duplication is permitted only for personal purposes.&nbsp; Reduplication
is permitted only under the FreeVGA Project documentation's redistribution
license.</LI>
<LI>
The use of the FreeVGA Project documentation to produce translations or
derivative works must be approved specifically by the author.</LI>
<LI>
All warnings and disclaimers present in the complete documentation must
apply to the licensee and may not be restricted by locality.&nbsp; These
must be read before use, and determined to be applicable to the licensee
before the material may be utilized.</LI>
<LI>
It is forbidden to represent the FreeVGA Project or to use the FreeVGA
Project's name to solicit or obtain information, services, product, or
endorsements from another party, commercial or otherwise.</LI>
</UL>
If all of the previous conditions are not met, then permission to utilize
the FreeVGA Project's documentation is not granted, and all rights are
reserved.
<P>License to distribute the FreeVGA Project documentation is subject to
the following conditions:
<UL>
<LI>
The copyright notice and this permission notice must be preserved complete
on all copies, complete or partial.</LI>
<LI>
An archive of the FreeVGA Project documentation may be distributed in electronic
form only in its entirety, without adding or removing any material, notices,
advertisement, or other information.&nbsp; Only exact copies of archives
produced or specifically approved by the author may be distributed, and
at the time of distribution, the most recent archive must be distributed.&nbsp;
The FreeVGA Project documentation must be excluded from any compilation
copyright or other restrictions.&nbsp; No fee other than the cost of transmission
or the physical media containing the archive may be charged without prior
approval by the author.&nbsp; The documentation may not be distributed
electronically in part, which includes mirroring in html format on the
internet, unless specific permission is granted by the author.</LI>
<LI>
The FreeVGA Project documentation may be distributed in non-electronic
form to students or members of a programming team subject to the condition
that it be provided free of charge.&nbsp; The documentation may not be
included with or within other copyrighted works unless the other copyrighted
works are also provided free of charge.</LI>
<LI>
Small portions may be reproduced as illustrations for reviews or quotes
in other works without this permission notice if proper citation is given
(including URL if the work is online.)</LI>
<LI>
Only the current documentation may be distributed.&nbsp; The URL of the
FreeVGA project online documentation must be provided.&nbsp; The author
reserves the right to limit distribution by any parties at any time.</LI>
</UL>
If all of the previous conditions are not met, then permission to redistribute
the FreeVGA Project's documentation is not granted, and all distribution
rights are reserved.
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

246
specs/freevga/llintro.htm Normal file
View File

@@ -0,0 +1,246 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA -- Introduction to Low-level Programming</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#know">Know</A>
<A HREF="#why">Why</A> <A HREF="#assembly">Assembly</A> <A HREF="#hex">Hex</A>
<A HREF="#conventions">Conventions</A> <A HREF="#memory">Memory</A> <A HREF="#access">Accessing</A>
<A HREF="home.htm#intro">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Introduction to Low-level Programming&nbsp;
<HR WIDTH="100%"></CENTER>
<P><A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section is intended
to give one a general background in low-level programming, specifically
related to video programming. It assumes that you already know how to program
in your intended programming environment, and answers questions such as:
<UL>
<LI>
<A HREF="#know">What do I need to know?</A></LI>
<LI>
<A HREF="#why">Why write hardware-level code?</A></LI>
<LI>
<A HREF="#assembly">Do I need to know assembly language?</A></LI>
<LI>
<A HREF="#hex">What are hex and binary numbers?</A></LI>
<LI>
<A HREF="#conventions">What are the numerical conventions used in this
reference?</A></LI>
<LI>
<A HREF="#memory">How do memory and I/O ports work?</A></LI>
<LI>
<A HREF="#access">How do I access these from my programming environment?</A></LI>
</UL>
<A NAME="know"></A><B>What do I need to know?</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>To program video
hardware at the lowest level you should have an understanding of hexadecimal
and binary numbers, how the CPU accesses memory and I/O ports, and finally
how to perform these operations in your particular programming environment.
In addition you need detailed descriptions of the particular graphics chipset
you are programming.
<P><A NAME="why"></A><B>Why write hardware-level code?</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; One reason for writing hardware-level
code is to develop drivers for operating systems or applications. Another
reason is when existing drivers do not provide the required performance
or capabilities for your application, such as for programming games or
multimedia. Finally, the most important reason is enjoyment. There is a
whole programming scene dedicated to producing "demos" of what the VGA/SVGA
can do.
<P><A NAME="assembly"></A><B>Do I need to know assembly language?</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; No, but it helps. Assembly
language is the basis all CPU operations. All functions of the processor
and computer are potentially accessible from assembly. With crafty use
of assembly language, one can write software that exceeds greatly the potential
of higher level languages. However, any programming environment that provides
direct access to I/O and memory will work.
<P><A NAME="hex"></A><B>What are hex and binary numbers?</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Humans use a number system
using 10 different digits (0-9), probably because that is the number of
fingers we have. Each digit represents part of a number with the rightmost
digit being ones, the second to right being tens, then hundreds, thousands
and so on. These represent the powers of 10 and is called "base 10" or
"decimal."
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Computers are digital (and
don't usually have fingers) and use two states, either on or off to represent
numbers. The off state is represented by 0 and the on state is represented
by 1. Each digit (called a bit, short for Binary digIT) here represents
a power of 2, such as ones, twos, fours, and doubling each subsequent digit.
Thus this number system is called "base 2" or "binary."
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Computer researchers realized
that binary numbers are unwieldy for humans to deal with; for example,
a 32-bit number would be represented in binary as 11101101010110100100010010001101.
Converting decimal to binary or vice versa requires multiplication or division,
something early computers performed very slowly, and researchers instead
created a system where the numbers were broken into groups of 3 (such as
11 101 101 010 110 100 100 010 010 001 101) and assigned a number from
0-7 based on the triplet's decimal value. This number system is called
"base 8" or "octal."
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Computers deal with numbers
in groups of bits usually a length that is a power of 2, for example, four
bits is called a "nibble", eight bits is called a "byte", 16 bits is a
"word", and 32 bits is a "double word." These powers of two are not equally
divisible by 3, so as you see in the divided example a "double word" is
represented by 10 complete octal digits plus two-thirds of an octal digit.
It was then realized that by grouping bits into groups of four, a byte
could be accurately represented by two digits. Because a group of four
bits can represent 16 decimal numbers, they could not be represented by
simply using 0-9, so they simply created more digits, or rather re-used
the letters A-F (or a-f) to represent 10-15. So for example the rightmost
digits of our example binary number is 1101, which translates to 13 decimal
or D in this system, which is called "base 16" or "hexadecimal."
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Computers nowadays usually
speak decimal (multiplication and division is much faster now) but when
it comes to low-level and hardware stuff, hexadecimal or binary is usually
used instead. Programming environments require you to explicitly specify
the base a number is in when overriding the default decimal. In most assembler
packages this is accomplished by appending "h" for hex and "b" for binary
to end of the number, such as 2A1Eh or 011001b. In addition, if the hex
value starts with a letter, you have to add a "0" to the beginning of the
number to allow it to distinguish it from a label or identifier, such as
0BABEh. In C and many other languages the standard is to append "0x" to
the beginning of the hex number and to append "%" to the beginning of a
binary number. Consult your programming environment's documentation for
how specifically to do this.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Historical Note: Another
possible explanation for the popularity of the octal system is that early
computers used 12 bit addressing instead of the 16 or 32 bit addressing
currently used by modern processors. Four octal digits conveniently covers
this range exactly, thus the historical architecture of early computers
may have been the cause for octal's popularity.
<P><A NAME="conventions"></A><B>What are the numerical conventions used
in this reference?</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>Decimal is used often
in this reference, as it is conventional to specify certain details about
the VGA's operation in decimal. Decimal numbers have no letter after them.
An example you might see would be a video mode described as 640x480z256.
This means that the video mode has 640 pixels across by 480 pixels down
with 256 possible simultaneous colors. Similarly an 80x25 text mode means
that the text mode has 80 characters wide (columns) by 25 characters high
(rows.) Binary is frequently used to specify fields within a particular
register and also for bitmap patterns, and has a trailing letter b (such
as 10011100b) to distinguish it from a decimal number containing only 0's
and 1's. Octal you are not likely to encounter in this reference, but if
used has a trailing letter o (such as 145o) to distinguish it from a decimal.
Hexadecimal is always used for addressing, such as when describing I/O
ports, memory offsets, or indexes. It is also often used in fields longer
than 3 bits, although in some cases it is conventional to utilize decimal
instead (for example in a hypothetical screen-width field.)
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Note: Decimal numbers in
the range 0-1 are also binary digits, and if only a single digit is present,
the decimal and binary numbers are equivalent. Similarly, for octal the
a single digit between 0-7 is equivalent to the decimal numbers in the
same range. With hexadecimal, the single-digit numbers 0-9 are equivalent
to decimal numbers 0-9. Under these circumstances, the number is often
given as decimal where another format would be conventional, as the number
is equivalent to the decimal value.
<BR>&nbsp;
<P><A NAME="memory"></A><B>How do memory and I/O ports work?</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 80x86 machines have both
a memory address space and an input/output (I/O) address space. Most of
the memory is provided as system RAM on the motherboard and most of the
I/O devices are provided by cards (although the motherboard does provide
quite a bit of I/O capability, varying on the motherboard design.) Also
some cards also provide memory. The VGA and SVGA display adapters provide
memory in the form of video memory, and they also handle I/O addresses
for controlling the display, so you must learn to deal with both. An adapter
card could perform all of its functions using solely memory or I/O (and
some do), but I/O is usually used because the decoding circuitry is simpler
and memory is used when higher performance is required.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The original PC design was
based upon the capabilities of the 8086/8088, which allowed for only 1
MB of memory, of which a small range (64K) was allotted for graphics memory.
Designers of high-resolution video cards needed to put more than 64K of
memory on their video adapters to support higher resolution modes, and
used a concept called "banking" which made the 64K available to the processor
into a "window" which shows a 64K chunk of video memory at once. Later
designs used multiple banks and other techniques to simplify programming.
Since modern 32-bit processors have 4 gigabytes of address space, some
designers allow you to map all of the video memory into a "linear frame
buffer" allowing access to the entire video memory at once without having
to change the current window pointer (which can be time consuming.) while
still providing support for the windowed method.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Memory can be accessed most
flexibly as it can be the source and/or target of almost every machine
language instruction the CPU is capable of executing, as opposed to a very
limited set of I/O instructions. I/O space is divided into 65536 addresses
in the range 0-65535. Most I/O devices are configured to use a limited
set of addresses that cannot conflict with another device. The primary
instructions for accessing I/O are the assembly instructions "IN" and "OUT",
simply enough. Most programming environments provide similarly named instructions,
functions, or procedures for accessing these.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Memory can be a bit confusing
though, because the CPU has two memory addressing modes, Real mode and
Protected mode. Real mode was the only method available on the 8086 and
is still the primary addressing mode used in DOS. Unfortunately, real mode
only provides access to the first 1 MB of memory. Protected mode is used
on the 80286 and up to allow access to more memory. (There are also other
details such as protection, virtual memory, and other aspects not particularly
applicable to this discussion.) Memory is accessed by the 80x86 processors
using segments and offsets. Segments tell the memory management unit where
in memory is located, and the offset is the displacement from that address.
In real mode offsets are limited to 64K, because of the 16-bit nature of
the 8086. In protected mode, segments can be any size up to the full address
capability of the machine. Segments are accessed via special segment registers
in the processor. In real mode, the segment address is shifted left four
bits and added to the offset, allowing for a 20 bit address (20 bits =
1 MB); in protected mode segments are offsets into a table in memory which
tells where the segment is located. Your particular programming environment
may create code for real and/or protected mode, and it is important to
know which mode is being used. An added difficulty is the fact that protected
mode provides for I/O and memory protection (hence protected mode), in
order to allow multiple programs to share one processor and prevent them
from corrupting other processes. This means that you may need to interact
with the operating system to gain rights to access the hardware directly.
If you write your own protected mode handler for DOS or are using a DOS
extender, then this should be simple, but it is much more complicated under
multi-tasking operating systems such as Windows or Linux.
<P><A NAME="access"></A><B>How do I access these from my programming environment?</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; That is a very important
question, one that is very difficult to answer without knowing all of the
details of your programming environment. The documentation that accompanies
your particular development environment is best place to look for this
information, in particular the compiler, operating system, and/or the chip
specifications for the platform.
<P>Details for some common programming environments are given in:
<UL>
<LI>
Eli Zaretskii's <A HREF="http://www.delorie.com/djgpp/v2faq/faq133.html#Low-level">DJGPP
Frequently-Asked Questions List: Low-level DOS/BIOS and Hardware-oriented
Programming</A> -- details on accessing hardware in DJGPP, a free 32-bit
compiler and programming environment for MS-DOS.</LI>
<LI>
There were more links here, but they expired. If anyone wants to write
an article or has a link on this topic for their favorite environment,
I will gladly and thankfully put it on this site.</LI>
</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,20 @@
256-Color Shift Mode Diagram (Left)
-----------------------------------
Plane 0 Plane 1 Plane 2 Plane 3
Carried 7654 3210 7654 3210 7654 3210 7654 3210
From Prev 0000 1111 0000 1111 0000 1111 0000 1111
| | | | | | | | |
| | | | | | | | |
XXXX 0000 | | | | | | |
0 0000 1111 | | | | | |
1 1111 0000 | | | | |
2 0000 1111 | | | |
3 1111 0000 | | |
4 0000 1111 | |
5 1111 0000 |
<----- Direction of Shift 6 0000 1111
7 |
v
Carried
To Next

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,18 @@
256-Color Shift Mode Diagram (Right)
-----------------------------------
Plane 3 Plane 2 Plane 1 Plane 0
7654 3210 7654 3210 7654 3210 7654 3210 Carried
0000 1111 0000 1111 0000 1111 0000 1111 From Prev
| | | | | | | | |
| | | | | | | 1111 XXXX
| | | | | | 0000 1111 0
| | | | | 1111 0000 1
| | | | 0000 1111 2
| | | 1111 0000 3
| | 0000 1111 4
| 1111 0000 5
0000 1111 6
| 7
Carried
To Next

View File

@@ -0,0 +1,360 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Attribute Controller Registers</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm#register">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Attribute Controller Registers&nbsp;
<HR WIDTH="100%"></CENTER>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The Attribute Controller
Registers are accessed via a pair of registers, the Attribute Address/Data
Register and the Attribute Data Read Register. See the <A HREF="vgareg.htm">Accessing
the VGA Registers</A> section for more detals. The Address/Data Register
is located at port 3C0h and the Data Read Register is located at port 3C1h.
<BR>&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION><A NAME="3C0"></A><B>Attribute Address Register(3C0h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">PAS</TD>
<TD COLSPAN="5" WIDTH="375">Attribute Address</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>PAS -- Palette Address Source<BR>
</B>"<I>This bit is set to 0 to load color values to the registers in the
internal palette. It is set to 1 for normal operation of the attribute
controller. Note: Do not access the internal palette while this bit is
set to 1. While this bit is 1, the Type 1 video subsystem disables accesses
to the palette; however, the Type 2 does not, and the actual color value
addressed cannot be ensured.</I>"
<LI>
<B>Attribute Address<BR>
</B>This field specifies the index value of the attribute register to be
read or written.</LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="000F"></A><B>Palette Registers (Index 00-0Fh)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="6" WIDTH="450">Internal Palette Index</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>Internal Palette Index<BR>
</B>"<I>These 6-bit registers allow a dynamic mapping between the text
attribute or graphic color input value and the display color on the CRT
screen. When set to 1, this bit selects the appropriate color. The Internal
Palette registers should be modified only during the vertical retrace interval
to avoid problems with the displayed image. These internal palette values
are sent off-chip to the video DAC, where they serve as addresses into
the DAC registers.</I>"</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="10"></A><B>Attribute Mode Control Register
(Index 10h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">P54S</TD>
<TD WIDTH="75">8BIT</TD>
<TD WIDTH="75">PPM</TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">BLINK</TD>
<TD WIDTH="75">LGE</TD>
<TD WIDTH="75">MONO</TD>
<TD WIDTH="75">ATGE</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>P54S -- Palette Bits 5-4 Select<BR>
</B>"<I>This bit selects the source for the P5 and P4 video bits that act
as inputs to the video DAC. When this bit is set to 0, P5 and P4 are the
outputs of the Internal Palette registers. When this bit is set to 1, P5
and P4 are bits 1 and 0 of the Color Select register.</I>"
<BR><B>8BIT -- 8-bit Color Enable<BR>
</B>"<I>When this bit is set to 1, the video data is sampled so that eight
bits are available to select a color in the 256-color mode (0x13). This
bit is set to 0 in all other modes.</I>"
<LI>
<B>PPM -- Pixel Panning Mode</B></LI>
<BR>This field allows the upper half of the screen to pan independently
of the lower screen. If this field is set to 0 then nothing special occurs
during a successful line compare (see the <A HREF="crtcreg.htm#18">Line
Compare</A> field.) If this field is set to 1, then upon a successful line
compare, the bottom portion of the screen is displayed as if the <A HREF="attrreg.htm#13">Pixel
Shift Count</A> and <A HREF="crtcreg.htm#08">Byte Panning</A> fields are
set to 0.
<BR><B>BLINK - Blink Enable<BR>
</B>"<I>When this bit is set to 0, the most-significant bit of the attribute
selects the background intensity (allows 16 colors for background). When
set to 1, this bit enables blinking.</I>"
<LI>
<B>LGA - Line Graphics Enable</B></LI>
<BR>This field is used in 9 bit wide character modes to provide continuity
for the horizontal line characters in the range C0h-DFh. If this field
is set to 0, then the 9th column of these characters is replicated from
the 8th column of the character. Otherwise, if it is set to 1 then the
9th column is set to the background like the rest of the characters.
<LI>
<B>MONO - Monochrome Emulation</B></LI>
<BR>This field is used to store your favorite bit. According to IBM, "When
this bit is set to 1, monochrome emulation mode is selected. When this
bit is set to 0, color |emulation mode is selected." It is present and
programmable in all of the hardware but it apparently does nothing. The
internal palette is used to provide monochrome emulation instead.
<LI>
<B>ATGE - Attribute Controller Graphics Enable<BR>
</B>"<I>When set to 1, this bit selects the graphics mode of operation.</I>"</LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION><A NAME="11"></A><B>Overscan Color Register (Index 11h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD COLSPAN="8" WIDTH="600">Overscan Palette Index</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>Overscan Palette Index<BR>
</B>"<I>These bits select the border color used in the 80-column alphanumeric
modes and in the graphics modes other than modes 4, 5, and D. (Selects
a color from one of the DAC registers.)</I>"</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="12"></A><B>Color Plane Enable Register (Index
12h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="4" WIDTH="300">Color Plane Enable</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Color Plane Enable<BR>
</B>"<I>Setting a bit to 1, enables the corresponding display-memory color
plane.</I>"</LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="13"></A><B>Horizontal Pixel Panning Register
(Index 13h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="4" WIDTH="300">Pixel Shift Count</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>Pixel Shift Count<BR>
</B>"<I>These bits select the number of pels that the video data is shifted
to the left. PEL panning is available in both alphanumeric and graphics
modes.</I>"</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="14"></A><B>Color Select Register (Index 14h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Color Select 7-6</TD>
<TD COLSPAN="2" WIDTH="150">Color Select 5-4</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>Color Select 7-6<BR>
</B>"<I>In modes other than mode 13 hex, these are the two most-significant
bits of the 8-bit digital color value to the video DAC. In mode 13 hex,
the 8-bit attribute is the digital color value to the video DAC. These
bits are used to rapidly switch between sets of colors in the video DAC.</I>"
<BR><B>Color Select 5-4<BR>
</B>"<I>These bits can be used in place of the P4 and P5 bits from the
Internal Palette registers to form the&nbsp; 8-bit digital color value
to the video DAC. Selecting these bits is done in the Attribute Mode Control&nbsp;
register (index 0x10). These bits are used to rapidly switch between colors
sets within the video DAC.</I>"</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

View File

@@ -0,0 +1,22 @@
_____Examples_of_Text_Mode_Bitmap_Characters_____
7 8x8 0 ___Legend___ 7 8x16 0 7 9x16 0
0--XX---- - Background 0-------- 0--------
-XXXX--- X Foreground -------- --------
XX--XX-- ? Undisplayed ---X---- XX----XX
XX--XX-- --XXX--- XXX--XXX
XXXXXX-- -XX-XX-- XXXXXXXX
XX--XX-- XX---XX- XXXXXXXX
XX--XX-- XX---XX- XX-XX-XX
7-------- <------+ XXXXXXX- XX----XX
8???????? | XX---XX- XX----XX
???????? XX---XX- XX----XX
???????? Maximum Scan XX---XX- XX----XX
???????? Line XX---XX- XX----XX
???????? -------- --------
???????? | -------- --------
???????? | -------- --------
???????? +------> 15-------- 15--------
???????? 16???????? 16????????
... ... ...
31???????? 31???????? 31????????

View File

@@ -0,0 +1,253 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Color Regsters</TITLE>
</HEAD>
<BODY>
<UL>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm#register">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Color Registers</CENTER>
<CENTER>
<HR WIDTH="100%"></CENTER>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The Color Registers in the standard
VGA provide a mapping between the palette of between 2 and 256 colors to
a larger 18-bit color space. This capability allows for efficient use of
video memory while providing greater flexibility in color choice. The standard
VGA has 256 palette entries containing six bits each of red, green, and
blue values. The palette RAM is accessed via a pair of address registers
and a data register. To write a palette entry, output the palette entry's
index value to the <A HREF="#3C8">DAC Address Write Mode Register</A> then
perform 3 writes to the <A HREF="#3C9">DAC Data Register</A>, loading the
red, green, then blue values into the palette RAM. The internal write address
automatically advances allowing the next value's RGB values to be loaded
without having to reprogram the <A HREF="#3C8">DAC Address Write Mode Register.&nbsp;
This</A> allows the entire palette to be loaded in one write operation.
To read a palette entry, output the palette entry's index to the <A HREF="#3C7W">DAC
Address Read Mode Register</A>. Then perform 3 reads from the <A HREF="#3C9">DAC
Data Register</A>, loading the red, green, then blue values from palette
RAM. The internal write address automatically advances allowing the next
RGB values to be written without having to reprogram the <A HREF="#3C7W">DAC
Address Read Mode Register</A>.
<P><A NAME="note"></A>Note: I have noticed some great variance in the actual
behavior of these registers on VGA chipsets. The best way to ensure compatibility
with the widest range of cards is to start an operation by writing to the
appropriate address register and performing reads and writes in groups
of 3 color values. While the automatic increment works fine on all cards
tested, reading back the value from the <A HREF="#3C8">DAC Address Write
Mode Register</A> may not always produce the expected result. Also interleaving
reads and writes to the <A HREF="#3C9">DAC Data Register</A> without first
writing to the respected address register may produce unexpected results.
In addition, writing values in anything other than groups of 3 to the <A HREF="#3C9">DAC
Data Register</A> and then performing reads may produce unexpected results.
I have found that some cards fail to perform the desired update until the
third value is written.
<UL>
<LI>
Port 3C8h -- <A HREF="#3C8">DAC Address Write Mode Register</A></LI>
<LI>
Port 3C7h -- <A HREF="#3C7W">DAC Address Read Mode Register</A></LI>
<LI>
Port 3C9h -- <A HREF="#3C9">DAC Data Register</A></LI>
<LI>
Port 3C7h -- <A HREF="#3C7R">DAC State Register</A></LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C8"></A><B>DAC Address Write Mode Register
(Read/Write at 3C8h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD COLSPAN="8" WIDTH="600">DAC Write Address</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC Write Address</B></LI>
<BR>Writing to this register prepares the DAC hardware to accept writes
of data to the <A HREF="#3C9">DAC Data Register</A>. The value written
is the index of the first DAC entry to be written (multiple DAC entries
may be written without having to reset the write address due to the auto-increment.)
Reading this register returns the current index, or at least theoretically
it should. However it is likely the value returned is not the one expected,
and is dependent on the particular DAC implementation. (See <A HREF="#note">note</A>
above)</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C7W"></A><B>DAC Address Read Mode Register
(Write at 3C7h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD COLSPAN="8" WIDTH="600">DAC Read Address</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC Read Address</B></LI>
<BR>Writing to this register prepares the DAC hardware to accept reads
of data to the <A HREF="#3C9">DAC Data Register</A>. The value written
is the index of the first DAC entry to be read (multiple DAC entries may
be read without having to reset the write address due to the auto-increment.)</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C9"></A><B>DAC Data Register (Read/Write at
3C9h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="6" WIDTH="450">DAC Data</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC Data</B></LI>
<BR>Reading or writing to this register returns a value from the DAC memory.
Three successive I/O operations accesses three intensity values, first
the red, then green, then blue intensity values. The index of the DAC entry
accessed is initially specified by the <A HREF="#3C7W">DAC Address Read
Mode Register</A> or the <A HREF="#3C8">DAC Address Write Mode Register</A>,
depending on the I/O operation performed. After three I/O operations the
index automatically increments to allow the next DAC entry to be read without
having to reload the index. I/O operations to this port should always be
performed in sets of three, otherwise the results are dependent on the
DAC implementation. (See <A HREF="#note">note</A> above)</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C7R"></A><B>DAC State Register (Read at 3C7h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">DAC State</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>DAC State</B></LI>
<BR>This field returns whether the DAC is prepared to accept reads or writes
to the <A HREF="#3C9">DAC Data Register</A>. In practice, this field is
seldom used due to the DAC state being known after the index has been written.
This field can have the following values:
<UL>
<LI>
00 -- DAC is prepared to accept reads from the <A HREF="#3C9">DAC Data
Register</A>.</LI>
<LI>
11 -- DAC is prepared to accept writes to the <A HREF="#3C9">DAC Data Register</A>.</LI>
</UL>
</UL>
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,282 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--External Regsters</TITLE>
</HEAD>
<BODY>
<UL>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm#register">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>External Regsters</CENTER>
<CENTER>
<HR WIDTH="100%"></CENTER>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The External Registers (sometimes
called the General Registers) each have their own unique I/O location in
the VGA, although sometimes the Read Port differs from the Write port,
and some are Read-only.. See the <A HREF="vgareg.htm">Accessing the VGA
Registers</A> section for more detals.
<UL>
<LI>
Port 3CCh/3C2h -- <I>Miscellaneous Output Register</I></LI>
<LI>
Port 3CAh/3xAh -- <I>Feature Control Register</I></LI>
<LI>
Port 3C2h -- <I>Input Status #0 Register</I></LI>
<LI>
Port 3xAh -- <I>Input Status #1 Register</I></LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3CCR3C2W"></A><B>Miscellaneous Output Register
(Read at 3CCh, Write at 3C2h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">VSYNCP</TD>
<TD WIDTH="75">HSYNCP</TD>
<TD WIDTH="75">O/E Page</TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Clock Select</TD>
<TD WIDTH="75">RAM En.</TD>
<TD WIDTH="75">I/OAS</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>VSYNCP -- Vertical Sync Polarity<BR>
</B>"<I>Determines the polarity of the vertical sync pulse and can be used
(with HSP) to control the vertical size of the display by utilizing the
autosynchronization feature of VGA displays.</I>
<BR><I>&nbsp; = 0 selects a positive vertical retrace sync pulse.</I>"
<BR><B>HSYNCP -- Horizontal Sync Polarity<BR>
</B>"<I>Determines the polarity of the horizontal sync pulse.</I>
<BR><I>&nbsp; = 0 selects a positive horizontal retrace sync pulse.</I>"
<BR><B>O/E Page -- Odd/Even Page Select<BR>
</B>"<I>Selects the upper/lower 64K page of memory when the system is in
an eve/odd mode (modes 0,1,2,3,7).</I>
<BR><I>&nbsp; = 0 selects the low page</I>
<BR><I>&nbsp; = 1 selects the high page</I>"
<LI>
<B>Clock Select</B></LI>
<BR>This field controls the selection of the dot clocks used in driving
the display timing.&nbsp; The standard hardware has 2 clocks available
to it, nominally 25 Mhz and 28 Mhz.&nbsp; It is possible that there may
be other "external" clocks that can be selected by programming this register
with the undefined values.&nbsp; The possible valuse of this register are:
<UL>
<LI>
00 -- select 25 Mhz clock (used for 320/640 pixel wide modes)</LI>
<LI>
01 -- select 28 Mhz clock (used for 360/720 pixel wide modes)</LI>
<LI>
10 -- undefined (possible external clock)</LI>
<LI>
11 -- undefined (possible external clock)</LI>
</UL>
<B>RAM En. -- RAM Enable<BR>
</B>"<I>Controls system access to the display buffer.</I>
<BR><I>&nbsp; = 0 disables address decode for the display buffer from the
system</I>
<BR><I>&nbsp; = 1 enables address decode for the display buffer from the
system</I>"
<BR><B>I/OAS -- Input/Output Address Select<BR>
</B>"<I>This bit selects the CRT controller addresses. When set to 0, this
bit sets the CRT controller addresses to 0x03Bx and the address for the
Input Status Register 1 to 0x03BA for compatibility withthe monochrome
adapter.&nbsp; When set to 1, this bit sets CRT controller addresses to
0x03Dx and the Input Status Register 1 address to 0x03DA for compatibility
with the color/graphics adapter. The Write addresses to the Feature Control
register are affected in the same manner.</I>"</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3CAR3xAW"></A><B>Feature Control Register (Read
at 3CAh, Write at 3BAh (mono) or 3DAh (color))</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">FC1</TD>
<TD WIDTH="75">FC0</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>FC1 -- Feature Control bit 1<BR>
</B>"<I>All bits are reserved.</I>"</LI>
<LI>
<B>FC2 -- Feature Control bit 0<BR>
</B>"<I>All bits are reserved.</I>"</LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3C2R"></A><B>Input Status #0 Register (Read-only
at 3C2h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">SS</TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
</TR>
</TABLE>
&nbsp;
<UL><B>SS - Switch Sense<BR>
</B>"<I>Returns the status of the four sense switches as selected by the
CS field of the Miscellaneous Output Register.</I>"</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="3xAR"></A><B>Input Status #1 Register (Read
at 3BAh (mono) or 3DAh (color))</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">VRetrace</TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">DD</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>VRetrace -- Vertical Retrace<BR>
</B>"<I>When set to 1, this bit indicates that the display is in a vertical
retrace interval.This bit can be programmed, through the Vertical Retrace
End register, to generate an interrupt at the start of the vertical retrace.</I>"
<BR><B>DD -- Display Disabled<BR>
</B>"<I>When set to 1, this bit indicates a horizontal or vertical retrace
interval. This bit is the real-time status of the inverted 'display enable'
signal. Programs have used this status bit to restrict screen updates to
the inactive display intervals in order to reduce screen flicker. The video
subsystem is designed to eliminate this software requirement; screen updates
may be made at any time without screen degradation.</I>"</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

View File

@@ -0,0 +1,585 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Graphics Registers</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm#register">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Graphics Registers&nbsp;
<HR WIDTH="100%"></CENTER>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The Graphics Registers are
accessed via a pair of registers, the Graphics Address Register and the
Graphics Data Register. See the <A HREF="vgareg.htm">Accessing the VGA
Registers</A> section for more details. The Address Register is located
at port 3CEh and the Data Register is located at port 3CFh.
<UL>
<LI>
Index 00h -- Set/Reset Register</LI>
<LI>
Index 01h -- Enable Set/Reset Register</LI>
<LI>
Index 02h -- Color Compare Register</LI>
<LI>
Index 03h -- Data Rotate Register</LI>
<LI>
Index 04h -- Read Map Select Register</LI>
<LI>
Index 05h -- <I>Graphics Mode Register</I></LI>
<LI>
Index 06h -- <I>Miscellaneous Graphics Register</I></LI>
<LI>
Index 07h -- Color Don't Care Register</LI>
<LI>
Index 08h -- Bit Mask Register</LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="00"></A><B>Set/Reset Register (Index 00h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="4" WIDTH="300">Set/Reset</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Set/Reset</B></LI>
<BR>Bits 3-0 of this field represent planes 3-0 of the VGA display memory.
This field is used by Write Mode 0 and Write Mode 3 (See the <A HREF="#05">Write
Mode</A> field.) In Write Mode 0, if the corresponding bit in the <A HREF="#01">Enable
Set/Reset</A> field is set, and in Write Mode 3 regardless of the <A HREF="#01">Enable
Set/Reset</A> field, the value of the bit in this field is expanded to
8 bits and substituted for the data of the respective plane and passed
to the next stage in the graphics pipeline, which for Write Mode 0 is the
<A HREF="#03">Logical Operation</A> unit and for Write Mode 3 is the <A HREF="#08">Bit
Mask</A> unit.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="01"></A><B>Enable Set/Reset Register (Index
01h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="4" WIDTH="300">Enable Set/Reset</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Enable Set/Reset</B></LI>
<BR>Bits 3-0 of this field represent planes 3-0 of the VGA display memory.
This field is used in Write Mode 0 (See the <A HREF="#05">Write Mode</A>
field) to select whether data for each plane is derived from host data
or from expansion of the respective bit in the <A HREF="#00">Set/Reset</A>
field.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="02"></A><B>Color Compare Register (Index 02h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="4" WIDTH="300">Color Compare</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Color Compare</B></LI>
<BR>Bits 3-0 of this field represent planes 3-0 of the VGA display memory.
This field holds a reference color that is used by Read Mode 1 (See the
<A HREF="#05">Read Mode</A> field.) Read Mode 1 returns the result of the
comparison between this value and a location of display memory, modified
by the <A HREF="#07">Color Don't Care</A> field.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="03"></A><B>Data Rotate Register (Index 03h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Logical Operation</TD>
<TD COLSPAN="3" WIDTH="225">Rotate Count</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Logical Operation</B></LI>
<BR>This field is used in Write Mode 0 and Write Mode 2 (See the <A HREF="#05">Write
Mode</A> field.) The logical operation stage of the graphics pipeline is
32 bits wide (1 byte * 4 planes) and performs the operations on its inputs
from the previous stage in the graphics pipeline and the latch register.
The latch register remains unchanged and the result is passed on to the
next stage in the pipeline. The results based on the value of this field
are:
<UL>
<LI>
00b - Result is input from previous stage unmodified.</LI>
<LI>
01b - Result is input from previous stage logical ANDed with latch register.</LI>
<LI>
10b - Result is input from previous stage logical ORed with latch register.</LI>
<LI>
11b - Result is input from previous stage logical XORed with latch register.</LI>
</UL>
<LI>
<B>Rotate Count</B></LI>
<BR>This field is used in Write Mode 0 and Write Mode 3 (See the <A HREF="#05">Write
Mode</A> field.) In these modes, the host data is rotated to the right
by the value specified by the value of this field. A rotation operation
consists of moving bits 7-1 right one position to bits 6-0, simultaneously
wrapping bit 0 around to bit 7, and is repeated the number of times specified
by this field.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="04"></A><B>Read Map Select Register (Index
04h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Read Map Select</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Read Map Select</B></LI>
<BR>This value of this field is used in Read Mode 0 (see the <A HREF="#05">Read
Mode</A> field) to specify the display memory plane to transfer data from.
Due to the arrangement of video memory, this field must be modified four
times to read one or more pixels values in the planar video modes.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION><A NAME="05"></A><B>Graphics Mode Register (Index 05h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75">Shift256</TD>
<TD>Shift Reg.</TD>
<TD WIDTH="75">Host O/E</TD>
<TD WIDTH="75">Read Mode</TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Write Mode</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Shift256 -- 256-Color Shift Mode<BR>
</B>"<I>When set to 0, this bit allows bit 5 to control the loading of
the shift registers. When set to 1, this bit causes the shift registers
to be loaded in a manner that supports the 256-color mode.</I>"</LI>
<BR><B>Shift Reg. -- Shift Register Interleave Mode<BR>
</B>"<I>When set to 1, this bit directs the shift registers in the graphics
controller to format the serial data stream with even-numbered bits from
both maps on even-numbered maps, and odd-numbered bits from both maps on
the odd-numbered maps. This bit is used for modes 4 and 5.</I>"
<BR><B>Host O/E -- Host Odd/Even Memory Read Addressing Enable<BR>
</B>"<I>When set to 1, this bit selects the odd/even addressing mode used
by the IBM Color/Graphics Monitor Adapter. Normally, the value here follows
the value of Memory Mode register bit 2 in the sequencer.</I>"
<LI>
<B>Read Mode</B></LI>
<BR>This field selects between two read modes, simply known as Read Mode
0, and Read Mode 1, based upon the value of this field:
<UL>
<LI>
0b -- Read Mode 0: In this mode, a byte from one of the four planes is
returned on read operations. The plane from which the data is returned
is determined by the value of the <A HREF="#04">Read Map Select</A> field.</LI>
</UL>
<LI>
1b -- Read Mode 1: In this mode, a comparison is made between display memory
and a reference color defined by the <A HREF="#02">Color Compare</A> field.
Bit planes not set in the <A HREF="#07">Color Don't Care</A> field then
the corresponding color plane is not considered in the comparison. Each
bit in the returned result represents one comparison between the reference
color, with the bit being set if the comparison is true.</LI>
<LI>
<B>Write Mode</B></LI>
<BR>This field selects between four write modes, simply known as Write
Modes 0-3, based upon the value of this field:
<UL>
<LI>
00b -- Write Mode 0: In this mode, the host data is first rotated as per
the <A HREF="#03">Rotate Count</A> field, then the <A HREF="#01">Enable
Set/Reset</A> mechanism selects data from this or the <A HREF="#00">Set/Reset</A>
field. Then the selected <A HREF="#03">Logical Operation</A> is performed
on the resulting data and the data in the latch register. Then the <A HREF="#08">Bit
Mask</A> field is used to select which bits come from the resulting data
and which come from the latch register. Finally, only the bit planes enabled
by the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field are
written to memory.</LI>
<LI>
01b -- Write Mode 1: In this mode, data is transferred directly from the
32 bit latch register to display memory, affected only by the <A HREF="seqreg.htm#02">Memory
Plane Write Enable</A> field. The host data is not used in this mode.</LI>
<LI>
10b -- Write Mode 2: In this mode, the bits 3-0 of the host data are replicated
across all 8 bits of their respective planes. Then the selected <A HREF="#03">Logical
Operation</A> is performed on the resulting data and the data in the latch
register. Then the <A HREF="#08">Bit Mask</A> field is used to select which
bits come from the resulting data and which come from the latch register.
Finally, only the bit planes enabled by the <A HREF="seqreg.htm#02">Memory
Plane Write Enable</A> field are written to memory.</LI>
<LI>
11b -- Write Mode 3: In this mode, the data in the <A HREF="#00">Set/Reset</A>
field is used as if the <A HREF="#01">Enable Set/Reset</A> field were set
to 1111b. Then the host data is first rotated as per the <A HREF="#03">Rotate
Count</A> field, then logical ANDed with the value of the <A HREF="#08">Bit
Mask</A> field. The resulting value is used on the data obtained from the
Set/Reset field in the same way that the <A HREF="#08">Bit Mask</A> field
would ordinarily be used. to select which bits come from the expansion
of the <A HREF="#00">Set/Reset</A> field and which come from the latch
register. Finally, only the bit planes enabled by the <A HREF="seqreg.htm#02">Memory
Plane Write Enable</A> field are written to memory.</LI>
</UL>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="06"></A><B>Miscellaneous Graphics Register
(Index 06h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Memory Map Select</TD>
<TD WIDTH="75">Chain O/E</TD>
<TD WIDTH="75">Alpha Dis.</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Memory Map Select<BR>
</B>This field specifies the range of host memory addresses that is decoded
by the VGA hardware and mapped into display memory accesses.&nbsp; The
values of this field and their corresponding host memory ranges are:</LI>
<UL>
<LI>
00b -- A0000h-BFFFFh (128K region)</LI>
<LI>
01b -- A0000h-AFFFFh (64K region)</LI>
<LI>
10b -- B0000h-B7FFFh (32K region)</LI>
<LI>
11b -- B8000h-BFFFFh (32K region)</LI>
</UL>
<B>Chain O/E -- Chain Odd/Even Enable<BR>
</B>"<I>When set to 1, this bit directs the system address bit, A0, to
be replaced by a higher-order bit. The odd map is then selected when A0
is 1, and the even map when A0 is 0.</I>"
<BR><B>Alpha Dis. -- Alphanumeric Mode Disable<BR>
</B>"<I>This bit controls alphanumeric mode addressing. When set to 1,
this bit selects graphics modes, which also disables the character generator
latches."</I></UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="07"></A><B>Color Don't Care Register (Index
07h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="4" WIDTH="300">Color Don't Care</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Color Don't Care</B></LI>
<BR>Bits 3-0 of this field represent planes 3-0 of the VGA display memory.
This field selects the planes that are used in the comparisons made by
Read Mode 1 (See the <A HREF="#05">Read Mode</A> field.) Read Mode 1 returns
the result of the comparison between the value of the <A HREF="#02">Color
Compare</A> field and a location of display memory. If a bit in this field
is set, then the corresponding display plane is considered in the comparison.
If it is not set, then that plane is ignored for the results of the comparison.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="08"></A><B>Bit Mask Register (Index 08h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD COLSPAN="8" WIDTH="600">Bit Mask</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Bit Mask</B></LI>
<BR>This field is used in Write Modes 0, 2, and 3 (See the <A HREF="#05">Write
Mode</A> field.) It it is applied to one byte of data in all four display
planes. If a bit is set, then the value of corresponding bit from the previous
stage in the graphics pipeline is selected; otherwise the value of the
corresponding bit in the latch register is used instead. In Write Mode
3, the incoming data byte, after being rotated is logical ANDed with this
byte and the resulting value is used in the same way this field would normally
be used by itself.</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

View File

@@ -0,0 +1,124 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA Copyright License</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>FreeVGA Project Copyright License&nbsp;
<HR></CENTER>
<B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This document contains the
FreeVGA Copyright License which states the conditions under which the FreeVGA
Project's Copyrighted information may be used and distributed.&nbsp; The
conditions of this license ensure that all parties with a need for this
information have the same availability, to the maximum extent possible
as well as ensure the integrity of the documentation.
<P><B>Disclaimer</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The author presents this
information as-is without any warranty, including suitability for intended
purpose. The author is not responsible for damages resulting by the use
of the information, incidental or otherwise. By utilizing this information,
you as the programmer take full liability for any damages caused by your
use of this information. If you are not satisfied with these terms, then
your only recourse is to not use this information. While every reasonable
effort is made to ensure that this information is correct, the possibility
exists for error and is not guaranteed for accuracy, and disclaims liability
for any changes, errors or omissions and is not responsible for any damages
that may arise from the use or misuse of this information.&nbsp; License
to use this information is only granted where this disclaimer applies in
whole.
<P><B>License</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The following copyright
license applies to all works by the FreeVGA Project. All of the FreeVGA
Project's documentation is copyrighted by its author, Joshua Neal.
<P>License to utilize the FreeVGA Project documentation is subject to the
following conditions:
<UL>
<LI>
The copyright notice and this permission notice must be preserved complete
on all copies, complete or partial.</LI>
<LI>
Duplication is permitted only for personal purposes.&nbsp; Reduplication
is permitted only under the FreeVGA Project documentation's redistribution
license.</LI>
<LI>
The use of the FreeVGA Project documentation to produce translations or
derivative works must be approved specifically by the author.</LI>
<LI>
All warnings and disclaimers present in the complete documentation must
apply to the licensee and may not be restricted by locality.&nbsp; These
must be read before use, and determined to be applicable to the licensee
before the material may be utilized.</LI>
<LI>
It is forbidden to represent the FreeVGA Project or to use the FreeVGA
Project's name to solicit or obtain information, services, product, or
endorsements from another party, commercial or otherwise.</LI>
</UL>
If all of the previous conditions are not met, then permission to utilize
the FreeVGA Project's documentation is not granted, and all rights are
reserved.
<P>License to distribute the FreeVGA Project documentation is subject to
the following conditions:
<UL>
<LI>
The copyright notice and this permission notice must be preserved complete
on all copies, complete or partial.</LI>
<LI>
An archive of the FreeVGA Project documentation may be distributed in electronic
form only in its entirety, without adding or removing any material, notices,
advertisement, or other information.&nbsp; Only exact copies of archives
produced or specifically approved by the author may be distributed, and
at the time of distribution, the most recent archive must be distributed.&nbsp;
The FreeVGA Project documentation must be excluded from any compilation
copyright or other restrictions.&nbsp; No fee other than the cost of transmission
or the physical media containing the archive may be charged without prior
approval by the author.&nbsp; The documentation may not be distributed
electronically in part, which includes mirroring in html format on the
internet, unless specific permission is granted by the author.</LI>
<LI>
The FreeVGA Project documentation may be distributed in non-electronic
form to students or members of a programming team subject to the condition
that it be provided free of charge.&nbsp; The documentation may not be
included with or within other copyrighted works unless the other copyrighted
works are also provided free of charge.</LI>
<LI>
Small portions may be reproduced as illustrations for reviews or quotes
in other works without this permission notice if proper citation is given
(including URL if the work is online.)</LI>
<LI>
Only the current documentation may be distributed.&nbsp; The URL of the
FreeVGA project online documentation must be provided.&nbsp; The author
reserves the right to limit distribution by any parties at any time.</LI>
</UL>
If all of the previous conditions are not met, then permission to redistribute
the FreeVGA Project's documentation is not granted, and all distribution
rights are reserved.
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,29 @@
Paging Memory Utilization Example
---------------------------------
0 +-------------------------+ 79
| |
| |
| |
| PAGE 0 |
| |
| |
| |
1920 | | 1999
+-------------------------+
| 48 bytes unused |
+-------------------------+
2048 | | 2127
| |
| |
| PAGE 1 |
| |
| |
| |
3968 | | 4047
+-------------------------+
| |
+-------------------------+
| |
|_ __ __ __ _ _|
-- --_- - --___-- --

View File

@@ -0,0 +1,99 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA - VGA I/O Port Index</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="../home.htm">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>VGA I/O Port Index&nbsp;
<HR></CENTER>
Introduction
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This index lists the VGA's
I/O ports in numerical order, making looking up a specific I/O port access
simpler.
<BR>&nbsp;
<UL>
<LI>
3B4h -- <A HREF="crtcreg.htm">CRTC Controller Address Register</A></LI>
<LI>
3B5h -- <A HREF="crtcreg.htm">CRTC Controller Data Register</A></LI>
<LI>
3BAh Read -- <A HREF="extreg.htm#3xAR">Input Status #1 Register</A></LI>
<LI>
3BAh Write -- <A HREF="extreg.htm#3CAR3xAW">Feature Control Register</A></LI>
<LI>
3C0h -- <A HREF="attrreg.htm">Attribute Address/Data Register</A></LI>
<LI>
3C1h -- <A HREF="attrreg.htm">Attribute Data Read Register</A></LI>
<LI>
3C2h Read -- <A HREF="extreg.htm#3C2R">Input Status #0 Register</A></LI>
<LI>
3C2h Write -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output Register</A></LI>
<LI>
3C4h -- <A HREF="seqreg.htm">Sequencer Address Register</A></LI>
<LI>
3C5h -- <A HREF="seqreg.htm">Sequencer Data Register</A></LI>
<LI>
3C7h Read -- <A HREF="colorreg.htm#3C7R">DAC State Register</A></LI>
<LI>
3C7h Write -- <A HREF="colorreg.htm#3C7W">DAC Address Read Mode Register</A></LI>
<LI>
3C8h -- <A HREF="colorreg.htm#3C8">DAC Address Write Mode Register</A></LI>
<LI>
3C9h -- <A HREF="colorreg.htm#3C9">DAC Data Register</A></LI>
<LI>
3CAh Read -- <A HREF="extreg.htm#3CAR3xAW">Feature Control Register</A></LI>
<LI>
3CCh Read -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output Register</A></LI>
<LI>
3CEh -- <A HREF="graphreg.htm">Graphics Controller Address Register</A></LI>
<LI>
3CFh -- <A HREF="graphreg.htm">Graphics Controller Data Register</A></LI>
<LI>
3D4h -- <A HREF="crtcreg.htm">CRTC Controller Address Register</A></LI>
<LI>
3D5h -- <A HREF="crtcreg.htm">CRTC Controller Data Register</A></LI>
<LI>
3DAh Read -- <A HREF="extreg.htm#3xAR">Input Status #1 Register</A></LI>
<LI>
3DAh Write -- <A HREF="extreg.htm#3CAR3xAW">Feature Control Register</A></LI>
</UL>
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="../license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1,25 @@
Packed Shift Mode Diagram
-------------------------
Plane 0 Plane 1
/-----------------^-----------------\ /-----------------^-----------------\
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+
| | | | | | | | | | | | | | | | | | | | | | | |
+---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+
| | | | | | | | | | | | | | | |
\ | \ | \ | \ | \ | \ | \ | \ |
3 2 | | 3 2 | | 3 2 | | 3 2 | | 3 2 | | 3 2 | | 3 2 | | 3 2 | |
[][][][] [][][][] [][][][] [][][][] [][][][] [][][][] [][][][] [][][][]
| | 1 0 | | 1 0 | | 1 0 | | 1 0 | | 1 0 | | 1 0 | | 1 0 | | 1 0
| \ | \ | \ | \ | \ | \ | \ | \
| | | | | | | | | | | | | | | |
+---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+
| | | | | | | | | | | | | | | | | | | | | | | |
+---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
\-----------------v-----------------/ \-----------------v-----------------/
Plane 2 Plane 3
<------- Direction of Shift

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,31 @@
Planar Shift Mode Diagram
-------------------------
Pixel Value Display Memory
3 2 1 0 7 6 5 4 3 2 1 0
+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+-----+-----+-----+
|.....|.....|.....|.....|___|.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
|.....|.....|.....|.....| |.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
+-----+-----+-----+-----+ +-----+-----+-----+-----+-----+-----+-----+-----+
| | | Plane 0 | | | | | | | |
| | | +-----+-----+-----+-----+-----+-----+-----+-----+
| | |____________|.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
| | Plane 1|.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
| | +-----+-----+-----+-----+-----+-----+-----+-----+
| | | | | | | | | |
| | +-----+-----+-----+-----+-----+-----+-----+-----+
| |__________________|.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
| Plane 2|.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
| +-----+-----+-----+-----+-----+-----+-----+-----+
| | | | | | | | |
| +-----+-----+-----+-----+-----+-----+-----+-----+
|________________________|.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
Plane 3|.....|%%%%%|:::::|%%%%%|:::::|%%%%%|:::::|%%%%%|
+-----+-----+-----+-----+-----+-----+-----+-----+
| | | | | | | |
Pixel: 0 1 2 3 4 5 6 7
<-------- Direction of Shift

View File

@@ -0,0 +1,381 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Sequencer Registers</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm#register">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Sequencer Registers&nbsp;
<HR WIDTH="100%"></CENTER>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The Sequencer Registers are
accessed via a pair of registers, the Sequencer Address Register and the
Sequencer Data Register. See the <A HREF="vgareg.htm">Accessing the VGA
Registers</A> section for more detals. The Address Register is located
at port 3C4h and the Data Register is located at port 3C5h.
<UL>
<LI>
Index 00h -- <I>Reset Register</I></LI>
<LI>
Index 01h -- <I>Clocking Mode Register</I></LI>
<LI>
Index 02h -- <I>Map Mask Register</I></LI>
<LI>
Index 03h -- Character Map Select Register</LI>
<LI>
Index 04h -- <I>Sequencer Memory Mode Register</I></LI>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="00"></A><B>Reset Register (Index 00h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">SR</TD>
<TD WIDTH="75">AR</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>SR -- Sychnronous Reset</B>
<BR>"<I>When set to 0, this bit commands the sequencer to synchronously
clear and halt. Bits 1 and 0 must be 1 to allow the sequencer to operate.
To prevent the loss of data, bit 1 must be set to 0 during the active display
interval before changing the clock selection. The clock is changed through
the Clocking Mode register or the Miscellaneous Output register.</I>"
<BR><B>AR -- Asynchronous Reset</B>
<BR>"<I>When set to 0, this bit commands the sequencer to asynchronously
clear and halt. Resetting the sequencer with this bit can cause loss of
video data</I>"</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="01"></A><B>Clocking Mode Register (Index 01h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">SD</TD>
<TD WIDTH="75">S4</TD>
<TD WIDTH="75">DCR</TD>
<TD WIDTH="75">SLR</TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">9/8DM</TD>
</TR>
</TABLE>
&nbsp;
<UL><B>SD -- Screen Disable</B>
<BR>"<I>When set to 1, this bit turns off the display and assigns maximum
memory bandwidth to the system. Although the display is blanked, the synchronization
pulses are maintained. This bit can be used for rapid full-screen updates.</I>"
<BR><B>S4 -- Shift Four Enable</B>
<BR>"<I>When the Shift 4 field and the Shift Load Field are set to 0, the
video serializers are loaded every character clock. When the Shift 4 field
is set to 1, the video serializers are loaded every forth character clock,
which is useful when 32 bits are fetched per cycle and chained together
in the shift registers.</I>"
<BR><B>DCR -- Dot Clock Rate</B>
<BR>"<I>When set to 0, this bit selects the normal dot clocks derived from
the sequencer master clock input. When this bit is set to 1, the master
clock will be divided by 2 to generate the dot clock. All other timings
are affected because they are derived from the dot clock. The dot clock
divided by 2 is used for 320 and 360 horizontal PEL modes.</I>"
<BR><B>SLR -- Shift/Load Rate</B>
<BR>"<I>When this bit and bit 4 are set to 0, the video serializers are
loaded every character clock. When this bit is set to 1, the video serializers
are loaded every other character clock, which is useful when 16 bits are
fetched per cycle and chained together in the shift registers. The Type
2 video behaves as if this bit is set to 0; therefore, programs should
set it to 0.</I>"
<LI>
<B>9/8DM -- 9/8 Dot Mode</B></LI>
<BR>This field is used to select whether a character is 8 or 9 dots wide.
This can be used to select between 720 and 640 pixel modes (or 360 and
320) and also is used to provide 9 bit wide character fonts in text mode.
The possible values for this field are:
<UL>
<LI>
0 - Selects 9 dots per character.</LI>
<LI>
1 - Selects 8 dots per character.</LI>
</UL>
</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="02"></A><B>Map Mask Register (Index 02h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="4" WIDTH="300">Memory Plane Write Enable</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>Memory Plane Write Enable</B></LI>
<BR>Bits 3-0 of this field correspond to planes 3-0 of the VGA display
memory. If a bit is set, then write operations will modify the respective
plane of display memory. If a bit is not set then write operations will
not affect the respective plane of display memory.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="03"></A><B>Character Map Select Register (Index
03h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">CSAS2</TD>
<TD WIDTH="75">CSBS2</TD>
<TD COLSPAN="2" WIDTH="150">Character Set A Select</TD>
<TD COLSPAN="2" WIDTH="150">Character Set B Select</TD>
</TR>
</TABLE>
&nbsp;
<UL>
<LI>
<B>CSAS2 -- Bit 2 of Character Set A Select</B></LI>
<BR>This is bit 2 of the Character Set A Select field. See <A HREF="#03">Character
Set A Select</A> below.
<LI>
<B>CSBS2 -- Bit 2 of Character Set B Select</B></LI>
<BR>This is bit 2 of the Character Set B field. See <A HREF="#03">Character
Set B Select</A> below.
<LI>
<B>Character Set A Select</B></LI>
<BR>This field is used to select the font that is used in text mode when
bit 3 of the attribute byte for a character is set to 1. Note that this
field is not contiguous in order to provide EGA compatibility. The font
selected resides in plane 2 of display memory at the address specified
by this field, as follows:
<UL>
<LI>
000b -- Select font residing at 0000h - 1FFFh</LI>
</UL>
<UL>
<LI>
001b -- Select font residing at 4000h - 5FFFh</LI>
<LI>
010b -- Select font residing at 8000h - 9FFFh</LI>
<LI>
011b -- Select font residing at C000h - DFFFh</LI>
<LI>
100b -- Select font residing at 2000h - 3FFFh</LI>
<LI>
101b -- Select font residing at 6000h - 7FFFh</LI>
<LI>
110b -- Select font residing at A000h - BFFFh</LI>
<LI>
111b -- Select font residing at E000h - FFFFh</LI>
</UL>
<LI>
<B>Character Set B Select</B></LI>
<BR>This field is used to select the font that is used in text mode when
bit 3 of the attribute byte for a character is set to 0. Note that this
field is not contiguous in order to provide EGA compatibility. The font
selected resides in plane 2 of display memory at the address specified
by this field, identical to the mapping used by <A HREF="#03">Character
Set A Select</A> above.</UL>
&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><A NAME="04"></A><B>Sequencer Memory Mode Register (Index
04h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75"></TD>
<TD WIDTH="75">Chain 4</TD>
<TD WIDTH="75">O/E Dis.</TD>
<TD WIDTH="75">Ext. Mem</TD>
<TD WIDTH="75"></TD>
</TR>
</TABLE>
&nbsp;
<UL><B>Chain 4 -- Chain 4 Enable</B>
<BR>"<I>This bit controls the map selected during system read operations.
When set to 0, this bit enables system addresses to sequentially access
data within a bit map by using the Map Mask register. When setto 1, this
bit causes the two low-order bits to select the map accessed as shown below.</I>
<BR><I>Address Bits</I>
<BR><I>&nbsp; A0 A1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Map Selected</I>
<BR><I>&nbsp;&nbsp; 0&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0</I>
<BR><I>&nbsp;&nbsp; 0&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
1</I>
<BR><I>&nbsp;&nbsp; 1&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
2</I>
<BR><I>&nbsp;&nbsp; 1&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
3</I>"
<BR><B>O/E Dis. -- Odd/Even Host Memory Write Adressing Disable<BR>
</B>"<I>When this bit is set to 0, even system addresses access maps 0
and 2, while odd system addresses access maps 1 and 3. When this bit is
set to 1, system addresses sequentially access data within a bit map, and
the maps are accessed according to the value in the Map Mask register (index
0x02).</I>"
<BR><B>Ext. Mem -- Extended Memory<BR>
</B>"<I>When set to 1, this bit enables the video memory from 64KB to 256KB.
This bit must be set to 1 to enable the character map selection described
for the previous register.</I>"</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

View File

@@ -0,0 +1,137 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Manipulating the Text-mode Cursor</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#enable">Visibility</A>
<A HREF="#position">Position</A> <A HREF="#shape">Shape</A> <A HREF="#blink">Blink
Rate</A> <A HREF="#color">Color</A> <A HREF="vga.htm#general">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Manipulating the Text-mode Cursor&nbsp;
<HR WIDTH="100%"></CENTER>
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- gives overview of text-mode cursor
capabilities</LI>
<LI>
<A HREF="#enable">Enabling/Disabling the Cursor</A> -- details on making
the cursor visible or not visible</LI>
<LI>
<A HREF="#position">Manipulating the Cursor Position</A> -- details on
controlling the cursor's placement</LI>
<LI>
<A HREF="#shape">Manipulating the Cursor Shape</A> -- details on controlling
the cursor's appearance</LI>
<LI>
<A HREF="#blink">Cursor Blink Rate</A> -- provides information about the
cursor's blink rate</LI>
<LI>
<A HREF="#color">Cursor Color</A> -- provides information regarding the
cursor's color</LI>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>When dealing with
the cursor in most high-level languages, the cursor is defined as the place
where the next text output will appear on the display. When dealing directly
with the display, the cursor is simply a blinking area of a particular
character cell. A program may write text directly to the display independent
of the current location of the cursor. The VGA provides facilities for
specifying whether a cursor is to be displayed, where the cursor is to
appear, and the shape of the cursor itself. Note that this cursor is only
used in the text modes of the standard VGA and is not to be confused with
the graphics cursor capabilities of particular SVGA chipsets.
<P><A NAME="enable"></A><B>Enabling/Disabling the Cursor</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; On the VGA there are three
main ways of disabling the cursor. The most straightforward is to set the
<A HREF="crtcreg.htm#0A">Cursor Disable</A> field to 1. Another way is
to set the <A HREF="crtcreg.htm#0B">Cursor Scan Line End</A> field to a
value less than that of the <A HREF="crtcreg.htm#0A">Cursor Scan Line Start</A>
field. On some adapters such as the IBM EGA, this will result instead in
a split block cursor. The third way is to set the cursor location to a
location off-screen. The first two methods are specific to VGA and compatible
adapters and are not guaranteed to work on non-VGA adapters, while the
third method should.
<P><A NAME="position"></A><B>Manipulating the Cursor Position</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>When dealing with
the cursor in standard BIOS text modes, the cursor position is specified
by row and column. The VGA hardware, due to its flexibility to display
any different text modes, specifies cursor position as a 16-bit address.
The upper byte of this address is specified by the <A HREF="crtcreg.htm#0E">Cursor
Location High Register</A>, and the lower by the <A HREF="crtcreg.htm#0F">Cursor
Location Low Register</A>. In addition this value is affected by the <A HREF="crtcreg.htm#0B">Cursor
Skew</A> field. When the hardware fetches a character from display memory
it compares the address of the character fetched to that of the cursor
location added to the <A HREF="crtcreg.htm#0B">Cursor Skew</A> field. If
they are equal and the cursor is enabled, then the character is written
with the current cursor pattern superimposed. Note that the address compared
to the cursor location is the address in display memory, not the address
in host memory. Characters and their attributes are stored at the same
address in display memory in different planes, and it is the odd/even addressing
mode usually used in text modes that makes the interleaved character/attribute
pairs in host memory possible. Note that it is possible to set the cursor
location to an address not displayed, effectively disabling the cursor.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The <A HREF="crtcreg.htm#0B">Cursor
Skew</A> field was used on the EGA to synchronize the cursor with internal
timing. On the VGA this is not necessary, and setting this field to any
value other than 0 may result in undesired results. For example, on one
particular card, setting the cursor position to the rightmost column and
setting the skew to 1 made the cursor disappear entirely. On the same card,
setting the cursor position to the leftmost column and setting the skew
to 1 made an additional cursor appear above and to the left of the correct
cursor. At any other position, setting the skew to 1 simply moved the cursor
right one position. Other than these undesired effects, there is no function
that this register can provide that could not be obtained by simply increasing
the cursor location.
<P><A NAME="shape"></A><B>Manipulating the Cursor Shape</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</B> On the VGA, the text-mode
cursor consists of a line or block of lines that extend horizontally across
the entire scan line of a character cell. The first, topmost line is specified
by the <A HREF="crtcreg.htm#0A">Cursor Scan Line Start</A> field. The last,
bottom most line is specified by the <A HREF="crtcreg.htm#0B">Cursor Scan
Line End</A> field. The scan lines in a character cell are numbered from
0 up to the value of the <A HREF="crtcreg.htm#09">Maximum Scan Line</A>
field. On the VGA if the <A HREF="crtcreg.htm#0B">Cursor Scan Line End</A>
field is less than the <A HREF="crtcreg.htm#0A">Cursor Scan Line Start</A>
field, no cursor will be displayed. Some adapters, such as the IBM EGA
may display a split-block cursor instead.
<P><A NAME="blink"></A><B>Cursor Blink Rate</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; On the standard VGA, the
blink rate is dependent on the vertical frame rate. The on/off state of
the cursor changes every 16 vertical frames, which amounts to 1.875 blinks
per second at 60 vertical frames per second. The cursor blink rate is thus
fixed and cannot be software controlled on the standard VGA. Some SVGA
chipsets provide non-standard means for changing the blink rate of the
text-mode cursor.
<P><A NAME="color"></A><B>Cursor Color</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; On the standard VGA, the
cursor color is obtained from the foreground color of the character that
the cursor is superimposing. On the standard VGA there is no way to modify
this behavior.
<BR>&nbsp;
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
</BODY>
</HTML>

226
specs/freevga/vga/vga.htm Normal file
View File

@@ -0,0 +1,226 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Standard VGA Chipset Reference</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#general">General</A>
<A HREF="#register">Registers</A> <A HREF="#index">Index</A> <A HREF="../home.htm#vga">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>VGA Chipset Reference&nbsp;
<HR WIDTH="100%"></CENTER>
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- introduction to the VGA reference</LI>
<LI>
<A HREF="#general">General Programming Information</A> -- details of the
functional operation of the VGA hardware.</LI>
<LI>
<A HREF="#register">Input/Output Register Information</A> -- details on
the VGA registers themselves</LI>
<LI>
<A HREF="#index">Indices</A> -- convenient listings of fields and their
locations alphabetically and by function</LI>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section is intended
to be a reference to the common functionality of the original IBM VGA and
compatible adapters. If you are writing directly to hardware then this
is the lowest common denominator of nearly all video cards in use today.
Nearly all programs requiring the performance of low-level hardware access
resort to this baseline capacity, so this information is still valuable
to programmers. In addition most of the VGA functions apply to SVGA cards
when operating in SVGA modes, so it is best to know how to use them even
when programming more advanced hardware.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Most VGA references I have
seen document the VGA by describing its operation in the various BIOS modes.
However, because BIOS was designed for use in MS-DOS real mode applications,
its functionality is limited in other environments. This document is structured
in a way that explains the VGA hardware and its operation independent of
the VGA BIOS modes, which will allow for better understanding of the capabilities
of the VGA hardware.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This reference has grown
out of my own notes and experimentation while learning to program the VGA
hardware. During this process I have identified errors in various references
that I have used and have attempted to document the VGA hardware's actual
behavior as best as possible. If in your experience you find any of this
information to be inaccurate, or even if you find this information to be
misleading or inaccurate, please let me know!
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; One of the reasons I started
this reference was that I was using existing references and found myself
wishing for a hypertext reference as almost every register is affected
by the operation of another, and was constantly flipping pages. Here I
simply use links for the register references, such as <A HREF="crtcreg.htm#13">Offset
Register</A>, rather than stating something like: Offset Register (CRTC:
Offset = 13h, bits 7-0). While the second method is more informative, using
them for every reference to the register makes the text somewhat bogged
down. HTML allows simply clicking on the register name and all of the details
are provided. Another is that no single reference had all of the information
I was looking for, and that I had penciled many corrections and clarifications
into the references themselves. This makes it difficult to switch to a
newer version of a book when another edition comes out -- I still use my
heavily annotated second edition of Ferarro's book, rather than the more
up-to-date third edition.
<P><A NAME="general"></A><B>General Programming Information</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>This section is intended
to provide functional information on various aspects of the VGA. If you
are looking simply for VGA register descriptions look in the next section.
The VGA hardware is complex and can be confusing to program. Rather than
attempt to document the VGA better than existing references by using more
words to describe the registers, this section breaks down the functionality
of the VGA into specific categories of similar functions or by detailing
procedures for performing certain operations.
<UL>
<LI>
<A HREF="vgamem.htm">Accessing the VGA Display Memory</A> -- details on
the memory interface between the CPU and VGA frame buffer.</LI>
<LI>
<A HREF="vgaseq.htm">Sequencer Operation</A> -- details on how the VGA
hardware rasterizes the display buffer</LI>
<UL>
<LI>
Text-mode</LI>
<UL>
<LI>
<A HREF="vgatext.htm">VGA Text Mode Operation</A> -- details concerning
text mode operation, including attributes and fonts.</LI>
<LI>
<A HREF="textcur.htm">Manipulating the Text-mode Cursor</A> -- details
controlling the appearance and location of the cursor.</LI>
</UL>
</UL>
<UL>
<LI>
<A HREF="vgafx.htm">Special Effects Hardware</A> -- details on hardware
support for windowing, paging, smooth scrolling and panning, and split-screen
operation.</LI>
</UL>
<LI>
<A HREF="vgaattr.htm">Attribute Controller Operation</A> -- details on
the conversion of sequenced display data into DAC input. <B>(WIP)</B></LI>
<LI>
<A HREF="vgadac.htm">DAC Operation</A> -- details controlling the conversion
of palette data into analog signals.</LI>
<LI>
<A HREF="vgacrtc.htm">Display Generation</A> -- details on formatting of
the produced video signal for output to the display.</LI>
</UL>
<A NAME="register"></A><B>Input/Output Register Information</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section is intended
to provide a detailed reference of the VGA's internal registers. It attempts
to combine information from a variety of sources, including the references
listed in the reference section of the home page; however, rather than
attempting to condense this information into one reference, leaving out
significant detail, I have attempted to expand upon the information available
and provide an accurate, detailed reference that should be useful to any
programmer of the VGA and SVGA. Only those registers that are present and
functional on the VGA are given, so if you are seeking information specific
to the CGA, EGA, MCGA, or MGA adapters try the Other References section
on the home page.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In some cases I have changed
the name of the register, not to protect the innocent but simply to make
it clearer to understand. One clarification is the use of "Enable" and
"Disable". A the function of a field with the name ending with "Enable"
is enabled when it is 1, and likewise a field with a name ending in Disable
is disabled when it is 1. Another case is when two fields have similar
or identical names, I have added more description to the name to differentiate
them.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; It can be difficult to understand
how to manipulate the VGA registers as many registers have been packed
into a small number of I/O ports and accessing them can be non-intuituve,
especially the Attribute Controller Registers, so I have provided a tutorial
for doing this.
<UL>
<LI>
&nbsp;<A HREF="vgareg.htm">Accessing the VGA Registers</A> -- methods of
manipulating the VGA registers</LI>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In order to facilitate understanding
of the registers, one should view them as groups of similar registers,
based upon how they are accessed, as the VGA uses indexed registers to
access most parameters. This also roughly places them in groups of similar
functionality; however, in many cases the fields do not fit neatly into
their category. In certain cases I have utilized quotes from the IBM VGA
Programmer's Reference, this information is given in "<I>italic.</I>"&nbsp;
This is meant to be a temporary placeholder until a better description
can be written, it may not be applicable to a standard VGA implementation.&nbsp;
Presented to roughly based upon their place in the graphics pipeline between
the CPU and the video outputs are the:
<UL>
<LI>
<A HREF="graphreg.htm">Graphics Registers</A> -- control the way the CPU
accesses video RAM.</LI>
<LI>
<A HREF="seqreg.htm">Sequencer Registers</A> -- control how video data
is sent to the DAC.</LI>
<LI>
<A HREF="attrreg.htm">Attribute Controller Registers</A> -- selects the
16 color and 64 color palettes used for EGA/CGA compatibility.</LI>
<LI>
<A HREF="crtcreg.htm">CRT Controller Registers</A> -- control how the video
is output to the display.</LI>
<LI>
<A HREF="colorreg.htm">Color Registers</A> -- selects the 256 color palette
from the maximum possible colors.</LI>
<LI>
<A HREF="extreg.htm">External Registers</A> -- miscellaneous registers
used to control video operation.</LI>
</UL>
<A NAME="index"></A><B>Indices</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In order to locate a particular
register quickly, the following indexes are provided. The first is a listing
of all of the register fields of the VGA hardware. This is especially useful
for fields that are split among multiple registers, or for finding the
location of a field that are packed in with other fields in one register.
The second is indexed by function groups each pertaining to a particular
part of the VGA hardware. This makes understanding and programming the
VGA hardware easier by listing the fields by subsystem, as the VGA's fields
are grouped in a somewhat haphazard fashion. The third is intended for
matching a read or write to a particular I/O port address to the section
where it is described.
<UL>
<LI>
<A HREF="vgargidx.htm">VGA Field Index</A> -- An alphabetical listing of
all fields and links to their location.</LI>
<LI>
<A HREF="vgafunc.htm">VGA Functional Index</A> -- A listing of all fields
and links to their location grouped by function.</LI>
<LI>
<A HREF="portidx.htm">VGA I/O Port Index</A> -- A listing of VGA I/O ports
in numerical order.</LI>
</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<P>&nbsp;
</BODY>
</HTML>

View File

@@ -0,0 +1,210 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA - VGA Display Generation</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#clocks">Clocks</A>
<A HREF="#horiz">Horizontal</A> <A HREF="#vert">Vertical</A> <A HREF="#monitor">Monitoring</A>
<A HREF="#misc">Misc</A> <A HREF="vga.htm#general">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>VGA Display Generation&nbsp;
<HR></CENTER>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This page documents the
configuration of the VGA's CRTC registers which control the framing and
timing of video signals sent to the display device, usually a monitor.
<P><A NAME="clocks"></A><B>Dot Clocks</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The standard VGA has two
"standard" dot clock frequencies available to it, as well as a possible
"external" clock source, which is implementation dependent.&nbsp; The two
standard clock frequencies are nominally 25 Mhz and 28 MHz.&nbsp; Some
chipsets use 25.000 MHz and 28.000 MHz, while others use slightly greater
clock frequencies.&nbsp; The IBM VGA chipset I have uses 25.1750 MHz&nbsp;
Mhz and 28.3220 crystals.&nbsp; Some newer cards use the closest generated
frequency produced by their clock chip.&nbsp; In most circumstances the
IBM VGA timings can be assumed as the monitor should allow an amount of
variance; however, if you know the actual frequencies used you should use
them in your timing calculations.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The dot clock source in
the VGA hardware is selected using the <A HREF="extreg.htm#3CCR3C2W">Clock
Select</A> field.&nbsp; For the VGA, two of the values are undefined; some
SVGA chipsets use the undefined values for clock frequencies used for 132
column mode and such.&nbsp; The 25 MHz clock is designed for 320 and 640
pixel modes and the 28 MHz is designed for 360 and 720 pixel modes. The
<A HREF="seqreg.htm#01">Dot Clock Rate</A> field specifies whether to use
the dot clock source directly or to divide it in half before using it as
the actual dot clock rate.
<P><A NAME="horiz"></A><B>Horizontal Timing</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA measures horizontal
timing periods in terms of character clocks, which can either be 8 or 9
dot clocks, as specified by the <A HREF="seqreg.htm#01">9/8 Dot Mode</A>
field.&nbsp; The 9 dot clock mode was included for monochrome emulation
and 9-dot wide character modes, and can be used to provide 360 and 720
pixel wide modes that work on all standard VGA monitors, when combined
with a 28 Mhz dot clock. The VGA uses a horizontal character counter which
is incremented at each character, which the horizontal timing circuitry
compares against the values of the horizontal timing fields to control
the horizontal state. The horizontal periods that are controlled are the
active display, overscan, blanking, and refresh periods.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The start of the active
display period coincides with the resetting of the horizontal character
counter, thus is fixed at zero.&nbsp; The value at which the horizontal
character is reset is controlled by the <A HREF="crtcreg.htm#00">Horizontal
Total</A> field. Note, however, that the value programmed into the <A HREF="crtcreg.htm#00">Horizontal
Total</A> field is actually 5 less than the actual value due to timing
concerns.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The end of the active display
period is controlled by the <A HREF="crtcreg.htm#01">End Horizontal Display</A>
field.&nbsp; When the horizontal character counter is equal to the value
of this field, the sequencer begins outputting the color specified by the
<A HREF="attrreg.htm#11">Overscan Palette Index</A> field.&nbsp; This continues
until the active display begins at the beginning of the next scan line
when the active display begins again.&nbsp; Note that the horizontal blanking
takes precedence over the sequencer and attribute controller.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The horizontal blanking
period begins when the character clock equals the value of the <A HREF="crtcreg.htm#02">Start
Horizontal Blanking</A> field.&nbsp; During the horizontal blanking period,
the output voltages of the DAC signal the monitor to turn off the guns.&nbsp;&nbsp;
Under normal conditions, this prevents the overscan color from being displayed
during the horizontal retrace period.&nbsp; This period extends until the
lower 6 bits of the <A HREF="crtcreg.htm#03">End Horizontal Blanking</A>
field match the lower 6 bits of the horizontal character counter.&nbsp;
This allows for a blanking period from 1 to 64 character clocks, although
some implementations may treat 64 as 0 character clocks in length.&nbsp;
The blanking period may occur anywhere in the scan line, active display
or otherwise even though its meant to appear outside the active display
period.&nbsp; It takes precedence over all other VGA output.&nbsp; There
is also no requirement that blanking occur at all.&nbsp; If the <A HREF="crtcreg.htm#02">Start
Horizontal Blanking</A> field falls outside the maximum value of the character
clock determined by the <A HREF="crtcreg.htm#00">Horizontal Total</A> field,
then no blanking will occur at all.&nbsp; Note that due to the setting
of the <A HREF="crtcreg.htm#00">Horizontal Total</A> field, the first match
for the <A HREF="crtcreg.htm#03">End Horizontal Blanking</A> field may
be on the following scan line.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Similar to the horizontal
blanking period, the horizontal retrace period is specified by the <A HREF="crtcreg.htm#04">Start
Horizontal Retrace</A> and <A HREF="crtcreg.htm#05">End Horizontal Retrace</A>
fields. The horizontal retrace period begins when the character clock equals
the value stored in the <A HREF="crtcreg.htm#04">Start Horizontal Retrace</A>
field.&nbsp; The horizontal retrace ends when the lower 5 bits of the character
clock match the bit pattern stored in the <A HREF="crtcreg.htm#05">End
Horizontal Retrace</A> field, allowing a retrace period from 1 to 32 clocks;
however, a particular implementation may treat 32 clocks as zero clocks
in length.&nbsp; The operation of this is identical to that of the horizontal
blanking mechanism with the exception of being a 5 bit comparison instead
of 6, and affecting the horizontal retrace signal instead of the horizontal
blanking.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; There are two horizontal
timing fields that are described as being related to internal timings of
the VGA, the <A HREF="crtcreg.htm#03">Display Enable Skew</A> and <A HREF="crtcreg.htm#05">Horizontal
Retrace Skew</A> fields.&nbsp; In the VGA they do seem to affect the timing,
but also do not seem to be necessary for the operation of the VGA and are
pretty much unused.&nbsp; These registers were required by the IBM VGA
implementations, so I'm assuming this was added in the early stages of
the VGA design for EGA compatibility, but the internal timings were changed
to more friendly ones making the use of these fields unnecessary.&nbsp;
It seems to be totally safe to set these fields to 0 and ignore them.&nbsp;
See the register descriptions for more details, if you have to deal with
software that programs them.
<P><A NAME="vert"></A><B>Vertical Timing</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA maintains a scanline
counter which is used to measure vertical timing periods.&nbsp; This counter
begins at zero which coincides with the first scan line of the active display.&nbsp;
This counter is set to zero before the beginning of the first scanline
of the active display.&nbsp; Depending on the setting of the <A HREF="crtcreg.htm#17">Divide
Scan Line Clock by 2</A> field, this counter is incremented either every
scanline, or every second scanline.&nbsp; The vertical scanline counter
is incremented before the beginning of each horizontal scan line, as all
of the VGA's vertical timing values are measured at the beginning of the
scan line, after the counter has ben set/incremented.&nbsp; The maximum
value of the scanline counter is specified by the <A HREF="crtcreg.htm#06">Vertical
Total</A> field.&nbsp; Note that, like the rest of the vertical timing
values that "overflow" an 8-bit register, the most significant bits are
located in the <A HREF="crtcreg.htm#07">Overflow Register</A>.&nbsp; The
<A HREF="crtcreg.htm#06">Vertical Total</A> field is programmed with the
value of the scanline counter at the beginning of the last scanline.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The vertical active display
period begins when the scanline counter is at zero, and extends up to the
value specified by the <A HREF="crtcreg.htm#12">Vertical Display End</A>
field.&nbsp; This field is set with the value of the scanline counter at
the beginning of the first inactive scanline, telling the video hardware
when to stop outputting scanlines of sequenced pixel data and outputs the
attribute specified by the <A HREF="attrreg.htm#11">Overscan Palette Index</A>
field in the horizontal active display period of those scanlines.&nbsp;
This continues until the start of the next frame when the active display
begins again.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The <A HREF="crtcreg.htm#15">Start
Vertical Blanking</A> and <A HREF="crtcreg.htm#16">End Vertical Blanking</A>
fields control the vertical blanking interval.&nbsp; The <A HREF="crtcreg.htm#15">Start
Vertical Blanking</A> field is programmed with the value of the scanline
counter at the beginning of the scanline to begin blanking at.&nbsp; The
value of the <A HREF="crtcreg.htm#16">End Vertical Blanking</A> field is
set to the lower eight bits of the scanline counter at the beginning of
the scanline after the last scanline of vertical blanking.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The <A HREF="crtcreg.htm#10">Vertical
Retrace Start</A> and <A HREF="crtcreg.htm#11">Vertical Retrace End</A>
fields determine the length of the vertical retrace interval.&nbsp; The
<A HREF="crtcreg.htm#10">Vertical Retrace Start</A> field contains the
value of the scanline counter at the beginning of the first scanline where
the vertical retrace signal is asserted.&nbsp; The <A HREF="crtcreg.htm#11">Vertical
Retrace End</A> field is programmed with the value of the lower four bits
of the scanline counter at the beginning of the scanline after the last
scanline where the vertical retrace signal is asserted.
<P><A NAME="monitor"></A><B>Monitoring Timing</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; There are certain operations
that should be performed during certain periods of the display cycle to
minimize visual artifacts, such as attribute and DAC writes.&nbsp; There
are two bit fields that return the current state of the VGA, the <A HREF="extreg.htm#3xAR">Display
Disabled</A> and <A HREF="extreg.htm#3xAR">Vertical Retrace</A> fields.
The <A HREF="extreg.htm#3xAR">Display Disabled</A> field is set to 1 when
the display enable signal is not asserted, providing the programmer with
a means to determine if the video hardware is currently refreshing the
active display or it is currently outputting blanking.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The <A HREF="extreg.htm#3xAR">Vertical
Retrace</A> field signals whether or not the VGA is in a vertical retrace
period.&nbsp; This is useful for determining the end of a display period,
which can be used by applications that need to update the display every
period such as when doing animation.&nbsp; Under normal conditions, when
the blanking signal is asserted during the entire vertical retrace, this
can also be used to detect this period of blanking, such that a large amount
of register accesses can be performed, such as reloading the complete set
of DAC entries.
<P><A NAME="misc"></A><B>Miscellaneous</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; There are a few registers
that affect display generation, but don't fit neatly into the horizontal
or vertical timing categories.&nbsp; The first is the <A HREF="crtcreg.htm#17">Sync
Enable</A> field which controls whether the horizontal and vertical sync
signals are sent to the display or masked off.&nbsp; The sync signals should
be disabled while setting up a new mode to ensure that an improper signal
that could damage the display is not being output.&nbsp; Keeping the sync
disabled for a period of one or more frames helps the display determine
that a mode change has occurred as well.
<BR>&nbsp;&nbsp;&nbsp; The <A HREF="crtcreg.htm#11">Memory Refresh Bandwidth</A>
field is used by the original IBM VGA hardware and some compatible VGA/SVGA
chipsets to control how often the display memory is refreshed.&nbsp; This
field controls whether the VGA hardware provides 3 or 5 memory refresh
cycles per scanline.&nbsp; At or above VGA horizontal refresh rates, this
field should be programmed for 3 memory refresh cycles per scanline.&nbsp;
Below this rate, for compatibility's sake the 5 memory refresh cycles per
scanline setting might be safer, see the <A HREF="crtcreg.htm#11">Memory
Refresh Bandwidth</A> field for (slightly) more information.
<P>&nbsp;
<BR>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

View File

@@ -0,0 +1,190 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--DAC Operation</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#DAC">DAC</A>
<A HREF="#programming">Programming</A> <A HREF="#precautions">Precautions</A>
<A HREF="#flicker">Flicker</A> <A HREF="#state">State</A> <A HREF="vga.htm#general">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>DAC Operation&nbsp;
<HR WIDTH="100%"></CENTER>
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- details the standard VGA DAC capabilities.</LI>
<LI>
<A HREF="#DAC">DAC Subsystem</A> -- gives a description of the DAC hardware.</LI>
<LI>
<A HREF="#programming">Programming the DAC</A> -- details reading and writing
to DAC memory.</LI>
<LI>
<A HREF="#precautions">Programming Precautions</A> -- details potential
problems that can be encountered with DAC hardware.</LI>
<LI>
<A HREF="#flicker">Eliminating Flicker</A> -- details on how to manipulate
DAC memory without causing visible side-effects.</LI>
<LI>
<A HREF="#state">The DAC State</A> -- details one possible use for an otherwise
useless field</LI>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; One of the improvements
the VGA has over the EGA hardware is in the amount of possible colors that
can be generated, in addition to an increase in the amount of colors that
can be displayed at once. The VGA hardware has provisions for up to 256
colors to be displayed at once, selected from a range of 262,144 (256K)
possible colors. This capability is provided by the DAC subsystem, which
accepts attribute information for each pixel and converts it into an analog
signal usable by VGA displays.
<P><A NAME="DAC"></A><B>DAC Subsystem</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA's DAC subsystem
accepts an 8 bit input from the attribute subsystem and outputs an analog
signal that is presented to the display circuitry. Internally it contains
256 18-bit memory locations that store 6 bits each of red, blue, and green
signal levels which have values ranging from 0 (minimum intensity) to 63
(maximum intensity.) The DAC hardware takes the 8-bit value from the attribute
subsystem and uses it as an index into the 256 memory locations and obtains
a red, green, and blue triad and produces the necessary output.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Note -- the DAC subsystem
can be implemented in a number of ways, including discrete components,
in a DAC chip which may or may not contain internal ram, or even integrated
into the main chipset ASIC itself. Many modern DAC chipsets include additional
functionality such as hardware cursor support, extended color mapping,
video overlay, gamma correction, and other functions. Partly because of
this it is difficult to generalize the DAC subsystem's exact behavior.
This document focuses on the common functionality of all VGA DACs; functionality
specific to a particular chipset are described elsewhere.
<P><A NAME="programming"></A><B>Programming the DAC</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The DAC's primary host interface
(there may be a secondary non-VGA compatible access method) is through
a set of four external registers containing the <A HREF="colorreg.htm#3C8">DAC
Write Address</A>, the <A HREF="colorreg.htm#3C7W">DAC Read Address</A>,
the <A HREF="colorreg.htm#3C9">DAC Data</A>, and the <A HREF="colorreg.htm#3C7R">DAC
State</A> fields. The DAC memory is accessed by writing an index value
to the <A HREF="colorreg.htm#3C8">DAC Write Address</A> field for write
operations, and to the <A HREF="colorreg.htm#3C7W">DAC Read Address</A>
field for read operations. Then reading or writing the <A HREF="colorreg.htm#3C9">DAC
Data</A> field, depending on the selected operation, three times in succession
returns 3 bytes, each containing 6 bits of red, green, and blue intensity
values, with red being the first value and blue being the last value read/written.
The read or write index then automatically increments such that the next
entry can be read without having to reprogramming the address. In this
way, the entire DAC memory can be read or written in 768 consecutive I/O
cycles to/from the <A HREF="colorreg.htm#3C9">DAC Data</A> field. The <A HREF="colorreg.htm#3C7R">DAC
State</A> field reports whether the DAC is setup to accept reads or writes
next.
<P><A NAME="precautions"></A><B>Programming Precautions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Due to the variances in
the different implementations, programming the DAC takes extra care to
ensure proper operation across the range of possible implementations. There
are a number of things can cause undesired effects, but the simplest way
to avoid problems is to ensure that you program the <A HREF="colorreg.htm#3C7W">DAC
Read Address</A> field or the <A HREF="colorreg.htm#3C8">DAC Write Address</A>
field before each read operation (note that a read operation may include
reads/writes to multiple DAC memory entries.) And always perform writes
and reads in groups of 3 color values. The DAC memory may not be updated
properly otherwise. Reading the value of the <A HREF="colorreg.htm#3C8">DAC
Write Address</A> field may not produce the expected result, as some implementations
may return the current index and some may return the next index. This operation
may even be dependent on whether a read or write operation is being performed.
While it may seem that the DAC implements 2 separate indexes for read and
write, this is often not the case, and interleaving read and write operations
may not work properly without reprogramming the appropriate index.
<UL>
<LI>
<B>Read Operation</B></LI>
<UL>
<LI>
Disable interrupts (this will ensure that a interrupt service routine will
not change the DAC's state)</LI>
<LI>
Output beginning DAC memory index to the <A HREF="colorreg.htm#3C7W">DAC
Read Address</A> register.</LI>
<LI>
Input red, blue, and green values from the <A HREF="colorreg.htm#3C9">DAC
Data</A> register, repeating for the desired number of entries to be read.</LI>
<LI>
Enable interrupts</LI>
</UL>
<LI>
<B>Write Operation</B></LI>
<UL>
<LI>
Disable interrupts (this will ensure that a interrupt service routine will
not change the DAC's state)</LI>
<LI>
Output beginning DAC memory index to the <A HREF="colorreg.htm#3C8">DAC
Write Address</A> register.</LI>
<LI>
Output red, blue, and green values to the <A HREF="colorreg.htm#3C9">DAC
Data</A> register, repeating for the desired number of entries to be read.</LI>
<LI>
Enable interrupts</LI>
</UL>
</UL>
<A NAME="flicker"></A><B>Eliminating Flicker</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; An important consideration
when programming the DAC memory is the possible effects on the display
generation. If the DAC memory is accessed by the host CPU at the same time
the DAC memory is being used by the DAC hardware, the resulting display
output may experience side effects such as flicker or "snow". Note that
both reading and writing to the DAC memory has the possibility of causing
these effects. The exact effects, if any, are dependent on the specific
DAC implementation. Unfortunately, it is not possible to detect when side-effects
will occur in all circumstances. The best measure is to only access the
DAC memory during periods of horizontal or vertical blanking. However,
this puts a needless burden on programs run on chipsets that are not affected.
If performance is an issue, then allowing the user to select between flicker-prone
and flicker-free access methods could possibly improve performance.
<P><A NAME="state"></A><B>The DAC State</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The <A HREF="colorreg.htm#3C7R">DAC
State</A> field seems to be totally useless, as the DAC state is usually
known by the programmer and it does not give enough information (about
whether a red, green, or blue value is expected next) for a interrupt routine
or such to determine the DAC state. However, I can think of one possible
use for it. You can use the DAC state to allow an interrupt driven routine
to access the palette (like for palette rotation effects or such) while
still allowing the main thread to write to the DAC memory. When the interrupt
routine executes it should check the DAC state. If the DAC state is in
a write state, it should not access the DAC memory. If it is in a read
state, the routine should perform the necessary DAC accesses then return
the DAC to a read state. This means that the main thread use the DAC state
to control the execution of the ISR. Also it means that it can perform
writes to the DAC without having to disable interrupts or otherwise inhibit
the ISR.
<BR>&nbsp;
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
</BODY>
</HTML>

View File

@@ -0,0 +1,402 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--VGA Functional Index</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#register">Register</A>
<A HREF="#memory">Memory</A> <A HREF="#sequencer">Sequencing</A> <A HREF="#cursor">Cursor</A>
<A HREF="#attribute">Attribute</A> <A HREF="#DAC">DAC</A> <A HREF="#display">Display</A>
<A HREF="#misc">Misc</A> <A HREF="vga.htm#index">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>VGA Functional Index&nbsp;
<HR WIDTH="100%"></CENTER>
<P><A NAME="register"></A><B>Register Access Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields control the
acessability/inaccessability of the VGA registers. These registers are
used for compatibiltiy with older programs that may attempt to program
the VGA in a fashion suited only to an EGA, CGA, or monochrome card.
<UL>
<LI>
CRTC Registers Protect Enable -- <A HREF="crtcreg.htm#11">Vertical Retrace
End Register</A></LI>
<LI>
Enable Vertical Retrace Access -- <A HREF="crtcreg.htm#03">End Horizontal
Blanking Register</A></LI>
<LI>
Input/Output Address Select -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous
Output Register</A></LI>
</UL>
<A NAME="memory"></A><B>Display Memory Access Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields control the
way the video RAM is mapped into the host CPU's address space and how memory
reads/writes affect the display memory.
<UL>
<LI>
Bit Mask -- <A HREF="graphreg.htm#08">Bit Mask Register</A></LI>
<LI>
Chain 4 Enable -- <A HREF="seqreg.htm#04">Sequencer Memory Mode Register</A></LI>
<LI>
Chain Odd/Even Enable -- <A HREF="graphreg.htm#06">Miscellaneous Graphics
Register</A></LI>
<LI>
Color Compare -- <A HREF="graphreg.htm#02">Color Compare Register</A></LI>
<LI>
Color Don't Care -- <A HREF="graphreg.htm#07">Color Don't Care Register</A></LI>
<LI>
Enable Set/Reset -- <A HREF="graphreg.htm#01">Enable Set/Reset Register</A></LI>
<LI>
Extended Memory -- <A HREF="seqreg.htm#04">Sequencer Memory Mode Register</A></LI>
<LI>
Host Odd/Even Memory Read Addressing Enable -- <A HREF="graphreg.htm#05">Graphics
Mode Register</A></LI>
<LI>
Host Odd/Even Memory Write Addressing Enable -- <A HREF="seqreg.htm#04">Sequencer
Memory Mode Register</A></LI>
<LI>
Logical Operation -- <A HREF="graphreg.htm#03">Data Rotate Register</A></LI>
<LI>
Memory Map Select -- <A HREF="graphreg.htm#06">Miscellaneous Graphics Register</A></LI>
<LI>
Memory Plane Write Enable -- <A HREF="seqreg.htm#02">Map Mask Register</A></LI>
<LI>
Odd/Even Page Select -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output
Register</A></LI>
<LI>
RAM Enable -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output Register</A></LI>
<LI>
Read Map Select -- <A HREF="graphreg.htm#04">Read Map Select Register</A></LI>
<LI>
Read Mode - <A HREF="graphreg.htm#05">Graphics Mode Register</A></LI>
<LI>
Rotate Count -- <A HREF="graphreg.htm#03">Data Rotate Register</A></LI>
<LI>
Set/Reset -- <A HREF="graphreg.htm#00">Set/Reset Register</A></LI>
<LI>
Write Mode -- <A HREF="graphreg.htm#05">Graphics Mode Register</A></LI>
</UL>
<A NAME="sequencer"></A><B>Display Sequencing Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields affect the
way the video memory is serialized for display.
<UL>
<LI>
256-Color Shift Mode -- <A HREF="graphreg.htm#05">Graphics Mode Register</A></LI>
<LI>
9/8 Dot Mode -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Address Wrap Select -- <A HREF="crtcreg.htm#17">CRTC Mode Control Register</A></LI>
<LI>
Alphanumeric Mode Disable -- <A HREF="graphreg.htm#06">Miscellaneous Graphics
Register</A></LI>
<LI>
Asynchronous Reset -- <A HREF="seqreg.htm#00">Reset Register</A></LI>
<LI>
Byte Panning -- <A HREF="crtcreg.htm#08">Preset Row Scan Register</A></LI>
<LI>
Character Set A Select -- <A HREF="seqreg.htm#03">Character Map Select
Register</A></LI>
<LI>
Character Set B Select -- <A HREF="seqreg.htm#03">Character Map Select
Register</A></LI>
<LI>
Divide Memory Address Clock by 4 -- <A HREF="crtcreg.htm#14">Underline
Location Register</A></LI>
<LI>
Double-Word Addressing -- <A HREF="crtcreg.htm#14">Underline Location Register</A></LI>
<LI>
Pixel Shift Count -- <A HREF="attrreg.htm#13">Horizontal Pixel Panning
Register</A></LI>
<LI>
Line Compare -- bit 9: <A HREF="crtcreg.htm#09">Maximum Scan Line Register</A>,
bit 8: <A HREF="crtcreg.htm#07">Overflow Register</A>, bits 7-0: <A HREF="crtcreg.htm#18">Line
Compare Register</A></LI>
<LI>
Line Graphics Enable -- <A HREF="attrreg.htm#10">Attribute Mode Control
Register</A></LI>
<LI>
Map Display Address 13 -- <A HREF="crtcreg.htm#17">CRTC Mode Control Register</A></LI>
<LI>
Map Display Address 14 -- <A HREF="crtcreg.htm#17">CRTC Mode Control Register</A></LI>
<LI>
Maximum Scan Line -- <A HREF="crtcreg.htm#09">Maximum Scan Line Register</A></LI>
<LI>
Offset -- <A HREF="crtcreg.htm#13">Offset Register</A></LI>
<LI>
Pixel Panning Mode -- <A HREF="attrreg.htm#10">Attribute Mode Control Register</A></LI>
<LI>
Preset Row Scan -- <A HREF="crtcreg.htm#08">Preset Row Scan Register</A></LI>
<LI>
Scan Doubling -- <A HREF="crtcreg.htm#09">Maximum Scan Line Register</A></LI>
<LI>
Screen Disable -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Shift Four Enable -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Shift/Load Rate -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Shift Register Interleave Mode -- <A HREF="graphreg.htm#05">Graphics Mode
Register</A></LI>
<LI>
Start Address -- bits 15-8: <A HREF="crtcreg.htm#0C">Start Address High
Register</A>, bits 7-0: <A HREF="crtcreg.htm#0D">Start Address Low Register</A></LI>
<LI>
Sycnchronous Reset -- <A HREF="seqreg.htm#00">Reset Register</A></LI>
<LI>
Word/Byte Mode Select -- <A HREF="crtcreg.htm#17">CRTC Mode Control Register</A></LI>
</UL>
<A NAME="cursor"></A><B>Cursor Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields affect the
operation of the cursor displayed while the VGA hardware is in text mode.
<UL>
<LI>
Cursor Disable -- <A HREF="crtcreg.htm#0A">Cursor Start Reguster</A></LI>
<LI>
Cursor Location -- bits 15-8: <A HREF="crtcreg.htm#0E">Cursor Location
High Register</A>, bits 7-0: <A HREF="crtcreg.htm#0F">Cursor Location Low
Register</A></LI>
<LI>
Cursor Scan Line End -- <A HREF="crtcreg.htm#0B">Cursor End Register</A></LI>
<LI>
Cursor Scan Line Start -- <A HREF="crtcreg.htm#0A">Cursor Start Reguster</A></LI>
<LI>
Cursor Skew -- <A HREF="crtcreg.htm#0B">Cursor End Register</A></LI>
</UL>
<A NAME="attribute"></A><B>Attribute Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields control the
way the video data is submitted to the RAMDAC, providing color/blinking
capability in text mode and facilitating the mapping of colors in graphics
mode.
<UL>
<LI>
8-bit Color Enable -- <A HREF="attrreg.htm#10">Attribute Mode Control Register</A></LI>
<LI>
Attribute Address -- <A HREF="attrreg.htm#3C0">Attribute Address Register</A></LI>
<LI>
Attribute Controller Graphics Enable -- <A HREF="attrreg.htm#10">Attribute
Mode Control Register</A></LI>
<LI>
Blink Enable -- <A HREF="attrreg.htm#10">Attribute Mode Control Register</A></LI>
<LI>
Color Plane Enable -- <A HREF="attrreg.htm#12">Color Plane Enable Register</A></LI>
<LI>
Color Select 5-4 -- <A HREF="attrreg.htm#14">Color Select Register</A></LI>
<LI>
Color Select 7-6 -- <A HREF="attrreg.htm#14">Color Select Register</A></LI>
<LI>
Internal Palette Index -- <A HREF="attrreg.htm#000F">Palette Registers</A></LI>
<LI>
Monochrome Emulation -- <A HREF="attrreg.htm#10">Attribute Mode Control
Register</A></LI>
<LI>
Overscan Palette Index -- <A HREF="attrreg.htm#11">Overscan Color Register</A></LI>
<LI>
Underline Location -- <A HREF="crtcreg.htm#14">Underline Location Register</A></LI>
<LI>
Palette Address Source -- <A HREF="attrreg.htm#3C0">Attribute Address Register</A></LI>
<LI>
Palette Bits 5-4 Select -- <A HREF="attrreg.htm#10">Attribute Mode Control
Register</A></LI>
</UL>
<A NAME="DAC"></A><B>DAC Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields allow control
of the VGA's 256-color palette that is part of the RAMDAC.
<UL>
<LI>
DAC Write Address -- <A HREF="colorreg.htm#3C8">DAC Address Write Mode
Register</A></LI>
<LI>
DAC Read Address -- <A HREF="colorreg.htm#3C7W">DAC Address Read Mode Register</A></LI>
<LI>
DAC Data -- <A HREF="colorreg.htm#3C9">DAC Data Register</A></LI>
<LI>
DAC State -- <A HREF="colorreg.htm#3C7R">DAC State Register</A></LI>
</UL>
<A NAME="display"></A><B>Display Generation Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields control the
formatting and timing of the VGA's video signal output.
<UL>
<LI>
Clock Select -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output Register</A></LI>
<LI>
Display Disabled -- <A HREF="extreg.htm#3xAR">Input Status #1 Register</A></LI>
<LI>
Display Enable Skew -- <A HREF="crtcreg.htm#03">End Horizontal Blanking
Register</A></LI>
<LI>
Divide Scan Line Clock by 2 -- <A HREF="crtcreg.htm#17">CRTC Mode Control
Register</A></LI>
<LI>
Dot Clock Rate -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
End Horizontal Display -- <A HREF="crtcreg.htm#01">End Horizontal Display
Register</A></LI>
<LI>
End Horizontal Blanking -- bit 5: <A HREF="crtcreg.htm#05">End Horizontal
Retrace Register</A>, bits 4-0: <A HREF="crtcreg.htm#03">End Horizontal
Blanking Register</A>,</LI>
<LI>
End Horizontal Retrace -- <A HREF="crtcreg.htm#05">End Horizontal Retrace
Register</A></LI>
<LI>
End Vertical Blanking -- <A HREF="crtcreg.htm#16">End Vertical Blanking
Register</A></LI>
<LI>
Horizontal Retrace Skew -- <A HREF="crtcreg.htm#05">End Horizontal Retrace
Register</A></LI>
<LI>
Horizontal Sync Polarity -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous
Output Register</A></LI>
<LI>
Horizontal Total -- <A HREF="crtcreg.htm#00">Horizontal Total Register</A></LI>
<LI>
Memory Refresh Bandwidth -- <A HREF="crtcreg.htm#11">Vertical Retrace End
Register</A></LI>
<LI>
Start Horizontal Blanking -- <A HREF="crtcreg.htm#02">Start Horizontal
Blanking Register</A></LI>
<LI>
Start Horizontal Retrace -- <A HREF="crtcreg.htm#04">Start Horizontal Retrace
Register</A></LI>
<LI>
Start Vertical Blanking -- bit 9: <A HREF="crtcreg.htm#09">Maximum Scan
Line Register</A>, bit 8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#15">Start Vertical Blanking Register</A></LI>
<LI>
Sync Enable -- <A HREF="crtcreg.htm#17">CRTC Mode Control Register</A></LI>
<LI>
Vertical Display End -- bits 9-8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#12">Vertical Display End Register</A></LI>
<LI>
Vertical Retrace End -- <A HREF="crtcreg.htm#11">Vertical Retrace End Register</A></LI>
<LI>
Vertical Retrace -- <A HREF="extreg.htm#3xAR">Input Status #1 Register</A></LI>
<LI>
Vertical Retrace Start -- bits 9-8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#10">Vertical Retrace Start Register</A></LI>
<LI>
Vertical Sync Polarity -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output
Register</A></LI>
<LI>
Vertical Total -- bits 9-8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#06">Vertical Total Register</A></LI>
</UL>
<A NAME="misc"></A><B>Miscellaneous Functions</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These fields are used to
detect the state of possible VGA hardware such as configuration switches/jumpers
and feature connector inputs.
<UL>
<LI>
Feature Control Bit 0 -- <A HREF="extreg.htm#3CAR3xAW">Feature Control
Register</A></LI>
<LI>
Feature Control Bit 1 -- <A HREF="extreg.htm#3CAR3xAW">Feature Control
Register</A></LI>
<LI>
Switch Sense -- <A HREF="extreg.htm#3C2R">Input Status #0 Register</A></LI>
</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

295
specs/freevga/vga/vgafx.htm Normal file
View File

@@ -0,0 +1,295 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA--Special Effects Hardware</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#window">Windowing</A>
<A HREF="#paging">Paging</A> <A HREF="#smooth">Smooth Scrolling</A> <A HREF="#split">Split-Screen</A>
<A HREF="vga.htm#general">Back
<HR WIDTH="100%"></A><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Special Effects Hardware&nbsp;
<HR WIDTH="100%"></CENTER>
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- describes the capabilities of the
VGA special effects hardware.</LI>
<LI>
<A HREF="#window">Windowing</A> -- provides rough panning and scrolling
of a larger virtual image.</LI>
<LI>
<A HREF="#paging">Paging</A> -- provides the ability to switch between
multiple screens rapidly.</LI>
<LI>
<A HREF="#smooth">Smooth Panning and Scrolling</A> -- provides more precise
control when panning and scrolling.</LI>
<LI>
<A HREF="#split">Split-Screen Operation</A> -- provides a horizontal division
which allows independent scrolling and panning of the top window.</LI>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section describes the
capabilities of the VGA hardware that can be used to implement special
effects such as windowing, paging, smooth panning and scrolling, and split
screen operation.. These functions are probably the least utilized of all
of the VGA's capabilities, possibly because most texts devoted to video
hardware provide only brief documentation. Also, the video BIOS provides
no support for these capabilities so the VGA card must be programmed at
the hardware level in order to utilize these capabilities. Windowing allows
a program to view a portion of an image in display memory larger than the
current display resolution, providing rough panning and scrolling. Paging
allows multiple display screens to be stored in the display memory allowing
rapid switching between them. Smooth panning and scrolling works in conjunction
with windowing to provide more precise control of window position. Split-screen
operation allows the creation of a horizontal division on the screen that
creates a window below that remains fixed in place independent of the panning
and scrolling of the window above. These features can be combined to provide
powerful control of the display with minimal demand on the host CPU.
<P><A NAME="window"></A><B>Windowing</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA hardware has the
ability treat the display as a window which can pan and/or scroll across
an image larger than the screen, which is used by some windowing systems
to provide a virtual scrolling desktop, and by some games and assembly
demos to provide scrolling. Some image viewers use this to allow viewing
of images larger than the screen. This capability is not limited to graphics
mode; some terminal programs use this capability to provide a scroll-back
buffer, and some editors use this to provide an editing screen wider than
80 columns.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This feature can be implemented
by brute force by simply copying the portion of the image to be displayed
to the screen. Doing this, however takes significant processor horsepower.
For example, scrolling a 256 color 320x200 display at 30 frames per second
by brute force requires a data transfer rate of 1.92 megabytes/second.
However, using the hardware capability of the VGA the same operation would
require a data transfer rate of only 120 bytes/second. Obviously there
is an advantage to using the VGA hardware. However, there are some limitations--one
being that the entire screen must scroll (or the top portion of the screen
if split-screen mode is used.) and the other being that the maximum size
of the virtual image is limited to the amount of video memory accessible,
although it is possible to redraw portions of the display memory to display
larger virtual images.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In text mode, windowing
allows panning at the character resolution. In graphics mode, windowing
allows panning at 8-bit resolution and scrolling at scan-line resolution.
For more precise control, see <A HREF="#smooth">Smooth Panning and Scrolling</A>
below. Because the VGA BIOS and most programming environment's graphics
libraries do not support windowing, you must modify or write your own routines
to write to the display for functions such as writing text or graphics.
This section assumes that you have the ability to work with the custom
resolutions possible when windowing is used.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In order to understand virtual
resolutions it is necessary to understand how the VGA's <A HREF="crtcreg.htm#0C">Start
Address High Register</A>, <A HREF="crtcreg.htm#0D">Start Address Low Register</A>,
and <A HREF="crtcreg.htm#13">Offset</A> field work. Because display memory
in the VGA is accessed by a 32-bit bus, a 16-bit address is sufficient
to uniquely identify any location in the VGA's 256K address space. The
<A HREF="crtcreg.htm#0C">Start Address High Register</A> and <A HREF="crtcreg.htm#0D">Start
Address Low Register</A> provide such an address. This address is used
to specify either the location of the first character in text mode or the
position of the first byte of pixels in graphics mode. At the end of the
vertical retrace, the current line start address is loaded with this value.
This causes one scan line of pixels or characters to be output starting
at this address. At the beginning of the next scan-line (or character row
in text mode) the value of the <A HREF="crtcreg.htm#13">Offset Register</A>
multiplied by the current memory address size * 2 is added to the current
line start address. The <A HREF="crtcreg.htm#14">Double-Word Addressing</A>
field and the <A HREF="crtcreg.htm#17">Word/Byte</A> field specify the
current memory address size. If the value of the <A HREF="crtcreg.htm#14">Double-Word
Addressing</A> field is 1, then the current memory address size is four
(double-word). Otherwise, the <A HREF="crtcreg.htm#17">Word/Byte</A> field
specifies the current memory address size. If the value of the <A HREF="crtcreg.htm#17">Word/Byte</A>
field is 0 then the current memory address size is 2 (word) otherwise,
the current memory address size is 1 (byte).
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Normally in graphics modes,
the offset register is programmed to represent (after multiplication) the
number of bytes in a scan line. This means that (unless a CGA/MDA emulation
mode is in effect) scan lines will be arranged sequentially in memory with
no space in between, allowing for the most compact representation in display
memory. However, this does not have to be the case--in fact, by increasing
the value of the offset register we can leave "extra space" between lines.
This is what provides for virtual widths. By programming the offset register
to the value of the equation:
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <B>Offset = VirtualWidth
/ ( PixelsPerAddress * MemoryAddressSize * 2 )</B>
<P>VirtualWidth is the width of the virtual resolution in pixels, and PixelsPerAddress
is the number of pixels per display memory address (1, 2, 4 or 8) depending
on the current video mode. For virtual text modes, the offset register
is programmed with the value of the equation:
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <B>Offset = VirtualWidth
/ ( MemoryAddressSize * 2 )</B>
<P>In text mode, there is always one character per display memory address.
In standard CGA compatible text modes, MemoryAddressSize is 2 (word).
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; After you have programmed
the new offset, the screen will now display only a portion of a virtual
display. The screen will display the number of scan-lines as specified
by the current mode. If the screen reaches the last byte of memory, the
next byte of memory will wrap around to the first byte of memory. Remember
that the Start Address specifies the display memory address of the upper-left
hand character or pixel. Thus the maximum height of a virtual screen depends
on the width of the virtual screen. By increasing this by the number of
bytes in a scan-line (or character row), the display will scroll one scan-line
or character row vertically downwards. By increasing the Start Address
by less than the number of bytes in a scan line, you can move the virtual
window horizontally to the right. If the virtual width is the same as the
actual width, one can create a vertical scrolling mode. This is used sometimes
as an "elevator" mode or to provide rapid scrollback capability in text
mode. If the virtual height is the same as the actual height, then only
horizontal panning is possible, sometimes called "panoramic" mode. In any
case, the equation for calculating the Start Address is:
<P><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Start Address = StartingOffset
+ Y * BytesPerVirtualRow + X</B>
<P>Y is the vertical position, from 0 to the value of the VitrualHeight
- ActualHeight. X is the horizontal position, from 0 to the value of BytesPerVirtualRow
- BytesPerActualRow . These ranges prevent wrapping around to the left
side of the screen, although you may find it useful to use the wrap-around
for whatever your purpose. Note that the wrap-around simply starts displaying
the next row/scan-line rather than the current one, so is not that useful
(except when using programming techniques that take this factor into account.)
Normally StartingOffset is 0, but if paging or split-screen mode is being
used, or even if you simply want to relocate the screen, you must change
the starting offset to the address of the upper-left hand pixel of the
virtual screen.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For example, a 512x300 virtual
screen in a 320x200 16-color 1 bit/pixel planar display would require 512
pixels / 8 pixels/byte = 64 bytes per row and 64 bytes/row * 300 lines
= 19200 bytes per screen. Assuming the VGA is in byte addressing mode,
this means that we need to program the offset register <A HREF="crtcreg.htm#13">Offset</A>
field with 512 pixels / (8 pixels/byte * 1 * 2) = 32 (20h). Adding one
to the start address will move the display screen to the right eight pixels.
More precise control is provided by the smooth scrolling mechanism. Adding
64 to the start address will move the virtual screen down one scan line.
See the following chart which shows the virtual screen when the start address
is calculated with an X and Y of 0:
<CENTER><A HREF="virtual.txt"><IMG SRC="virtual.gif" ALT="Click for Textified Virtual Screen Mode Example" HEIGHT=256 WIDTH=376></A></CENTER>
<P><A NAME="paging"></A><B>Paging</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The video display memory
may be able to hold more than one screen of data (or virtual screen if
virtual resolutions are used.) These multiple screens, called pages, allows
rapid switching between them. As long as they both have the same actual
(and virtual if applicable) resolution, simply changing the Start Address
as given by the <A HREF="crtcreg.htm#0C">Start Address High Register</A>
and <A HREF="crtcreg.htm#0D">Start Address Low Register</A> pair to point
to the memory address of the first byte of the page (or set the StartingOffset
term in the equation for virtual resolutions to the first memory address
of the page.) If they have different virtual widths, then the <A HREF="crtcreg.htm#13">Offset</A>
field must be reprogrammed. It is possible to store both graphics and text
pages simultaneously in memory, in addition to different graphics mode
pages. In this case, the video mode must be changed when changing pages.
In addition, in text mode the Cursor Location must be reprogrammed for
each page if it is to be displayed. Also paging allows for double buffering
of the display -- the CPU can write to one page while the VGA hardware
is displaying another. By switching between pages during the vertical retrace
period, flicker free screen updates can be implemented.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; An example of paging is
that used by the VGA BIOS in the 80x25 text mode. Each page of text takes
up 2000 memory address locations, and the VGA uses a 32K memory aperture,
with the Odd/Even addressing enabled. Because Odd/Even addressing is enabled,
each page of text takes up 4000 bytes in host memory, thus 32768 / 4000
= 8 (rounded down) pages can be provided and can be accessed at one time
by the CPU. Each page starts at a multiple of 4096 (1000h). Because the
display controller circuitry works independent of the host memory access
mode, this means that each page starts at a display address that is a multiple
of 2048 (800h), thus the Starting Address is programmed to the value obtained
by multiplying the page to be displayed by 2048 (800h). See the following
chart which shows the arrangement of these pages in display memory:
<BR>&nbsp;
<CENTER><A HREF="paging.txt"><IMG SRC="paging.gif" ALT="Click here to display a textified Paging Memory Utilization Example" HEIGHT=256 WIDTH=376></A></CENTER>
<P><A NAME="smooth"></A><B>Smooth Panning and Scrolling</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Because the Start Address
field only provides for scrolling and panning at the memory address level,
more precise panning and scrolling capability is needed to scroll at the
pixel level as multiple pixels may reside at the same memory address especially
in text mode where the Start Address field only allows panning and scrolling
at the character level.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pixel level panning is controlled
by the <A HREF="attrreg.htm#13">Pixel Shift Count</A> and <A HREF="crtcreg.htm#08">Byte
Panning</A> fields. The <A HREF="attrreg.htm#13">Pixel Shift Count</A>
field specifies the number of pixels to shift left. In all graphics modes
and text modes except 9 dot text modes and 256 color graphics modes, the
<A HREF="attrreg.htm#13">Pixel Shift Count</A> is defined for values 0-7.
This provides the pixel level control not provided by the <A HREF="crtcreg.htm#0D">Start
Address Register</A> or the <A HREF="crtcreg.htm#08">Byte Panning</A> fields.
In 9 dot text modes the <A HREF="attrreg.htm#13">Pixel Shift Count</A>
is field defined for values 8, and 0-7, with 8 being the minimum shift
amount and 7 being the maximum. In 256 color graphics modes, due to the
way the hardware makes a 256 color value by combining 2 16-bit values,
the <A HREF="attrreg.htm#13">Pixel Shift Count</A> field is only defined
for values 0, 2, 4, and 6. Values 1, 3, 5, and 7 cause the screen to be
distorted due to the hardware combining 4 bits from each of 2 adjacent
pixels. The <A HREF="crtcreg.htm#08">Byte Panning</A> field is added to
the <A HREF="crtcreg.htm#0D">Start Address Register</A> when determining
the address of the top-left hand corner of the screen, and has the value
from 0-3. Combined, both panning fields allow a shift of 15, 31, or 35
pixels, dependent upon the video mode. Note that programming the <A HREF="attrreg.htm#13">Pixel
Shift Count</A> field to an undefined value may cause undesired effects
and these effects are not guaranteed to be identical on all chipsets, so
it is best to be avoided.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Pixel level scrolling is
controlled by the <A HREF="crtcreg.htm#08">Preset Row Scan</A> field. This
field may take any value from 0 up to the value of the <A HREF="crtcreg.htm#09">Maximum
Scan Line</A> field; anything greater causes interesting artifacts (there
is no guarantee that the result will be the same for all VGA chipsets.)
Incrementing this value will shift the screen upwards by one scan line,
allowing for smooth scrolling in modes where the Offset field does not
provide precise control.
<P><A NAME="split"></A><B>Split-screen Operation</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA hardware provides
the ability to specify a horizontal division which divides the screen into
two windows which can start at separate display memory addresses. In addition,
it provides the facility for panning the top window independent of the
bottom window. The hardware does not provide for split-screen modes where
multiple video modes are possible in one display screen as provided by
some non-VGA graphics controllers. In addition, there are some limitations,
the first being that the bottom window's starting display memory address
is fixed at 0. This means that (unless you are using split screen mode
to duplicate memory on purpose) the bottom screen must be located first
in memory and followed by the top. The second limitation is that either
both windows are panned by the same amount, or only the top window pans,
in which case, the bottom window's panning values are fixed at 0. Another
limitation is that the <A HREF="crtcreg.htm#08">Preset Row Scan</A> field
only applies to the top window -- the bottom window has an effective Preset
Row Scan value of 0.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The Line Compare field in
the VGA, of which bit 9 is in the <A HREF="crtcreg.htm#09">Maximum Scan
Line Register</A>, bit 8 is in the <A HREF="crtcreg.htm#07">Overflow Register</A>,
and bits 7-0 are in the <A HREF="crtcreg.htm#18">Line Compare Register</A>,
specifies the scan line address of the horizontal division. When the line
counter reaches the value in the Line Compare Register, the current scan
line start address is reset to 0. If the <A HREF="attrreg.htm#10">Pixel
Panning Mode</A> field is set to 1 then the <A HREF="attrreg.htm#13">Pixel
Shift Count</A> and <A HREF="crtcreg.htm#08">Byte Panning</A> fields are
reset to 0 for the remainder of the display cycle allowing the top window
to pan while the bottom window remains fixed. Otherwise, both windows pan
by the same amount.
<BR>&nbsp;
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
</BODY>
</HTML>

View File

@@ -0,0 +1,334 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Accessing the VGA Display Memory</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#detect">Detecting</A>
<A HREF="#mapping">Mapping</A> <A HREF="#address">Addressing</A> <A HREF="#manip">Manipulating</A>
<A HREF="#read">Reading</A> <A HREF="#write">Writing</A> <A HREF="vga.htm#general">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Accessing the VGA Display Memory&nbsp;
<HR WIDTH="100%"></CENTER>
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- gives an overview of the VGA display
memory.</LI>
<LI>
<A HREF="#detect">Detecting the Amount of Display Memory on the Adapter</A>
-- details how to determine the amount of memory present on the VGA.</LI>
<LI>
<A HREF="#mapping">Mapping of Display Memory into CPU Address Space</A>
-- details how to control the location and size of the memory aperture.</LI>
<LI>
<A HREF="#address">Host Address to Display Address Translation</A> -- detail
how the VGA hardware maps a host access to a display memory access</LI>
<LI>
<A HREF="#manip">Manipulating Display Memory</A> -- Details on reading
and writing to VGA memory</LI>
<UL>
<LI>
<A HREF="#read">Reading from Display Memory</A> -- Details the hardware
mechanisms used when reading display memory.</LI>
<LI>
<A HREF="#write">Writing to Display Memory</A> -- Details the hardware
mechanisms used when writing display memory.</LI>
</UL>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The standard VGA hardware
contains up to 256K of onboard display memory. While it would seem logical
that this memory would be directly available to the processor, this is
not the case. The host CPU accesses the display memory through a window
of up to 128K located in the high memory area. (Note that many SVGA chipsets
provide an alternate method of accessing video memory directly, called
a Linear Frame Buffer.) Thus in order to be able to access display memory
you must deal with registers that control the mapping into host address
space. To further complicate things, the VGA hardware provides support
for memory models similar to that used by the monochrome, CGA, EGA, and
MCGA adapters. In addition, due to the way the VGA handles 16 color modes,
additional hardware is included that can speed access immensely. Also,
hardware is present that allows the programer to rapidly copy data from
one area of display memory to another. While it is quite complicated to
understand, learning to utilize the VGA's hardware at a low level can vastly
improve performance. Many game programmers utilize the BIOS mode 13h, simply
because it offers the simplest memory model and doesn't require having
to deal with the VGA's registers to draw pixels. However, this same decision
limits them from being able to use the infamous X modes, or higher resolution
modes.
<P><A NAME="detect"></A><B>Detecting the Amount of Display Memory on the
Adapter</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>Most VGA cards in
existence have 256K on board; however there is the possibility that some
VGA boards have less. To actually determine further if the card has 256K
one must actually write to display memory and read back values. If RAM
is not present in a location, then the value read back will not equal the
value written. It is wise to utilize multiple values when doing this, as
the undefined result may equal the value written. Also, the card may alias
addresses, causing say the same 64K of RAM to appear 4 times in the 256K
address space, thus it is wise to change an address and see if the change
is reflected anywhere else in display memory. In addition, the card may
buffer one location of video memory in the chipset, making it appear that
there is RAM at an address where there is none present, so you may have
to read or write to a second location to clear the buffer. Not that if
the <A HREF="seqreg.htm#04">Extended Memory</A> field is not set to 1,
the adapter appears to only have 64K onboard, thus this bit should be set
to 1 before attempting to determine the memory size.
<P><A NAME="mapping"></A><B>Mapping of Display Memory into CPU Address
Space</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The first element that defines
this mapping is whether or not the VGA decodes accesses from the CPU. This
is controlled by the <A HREF="extreg.htm#3CCR3C2W">RAM Enable</A> field.
If display memory decoding is disabled, then the VGA hardware ignores writes
to its address space. The address range that the VGA hardware decodes is
based upon the <A HREF="graphreg.htm#06">Memory Map Select</A> field. The
following table shows the address ranges in absolute 32-bit form decoded
for each value of this field:
<UL>
<LI>
00 -- A0000h-BFFFFh -- 128K</LI>
<LI>
01 -- A0000h-AFFFFh -- 64K</LI>
<LI>
10 -- B0000h-B7FFFh -- 32K</LI>
<LI>
11 -- B8000h-BFFFFh -- 32K</LI>
</UL>
Note -- It would seem that by setting the <A HREF="graphreg.htm#06">Memory
Map Select</A> field to 00 and then using planar memory access that you
could gain access to more than 256K of memory on an SVGA card. However,
I have found that some cards simply mirror the first 64K twice within the
128K address space. This memory map is intended for use in the Chain Odd/Even
modes, eliminating the need to use the Odd/Even Page Select field. Also
I have found that MS-DOS memory managers don't like this very much and
are likely to lock up the system if configured to use the area from B0000h-B7FFFh
for loading device drivers high.
<P><A NAME="address"></A><B>Host Address to Display Address Translation</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The most complicated part
of accessing display memory involves the translation between a host address
and a display memory address. Internally, the VGA has a 64K 32-bit memory
locations. These are divided into four 64K bit planes. Because the VGA
was designed for 8 and 16 bit bus systems, and due to the way the Intel
chips handle memory accesses, it is impossible for the host CPU to access
the bit planes directly, instead relying on I/O registers to make part
of the memory accessible. The most straightforward display translation
is where a host access translates directly to a display memory address.
What part of the particular 32-bit memory location is dependent on certain
registers and is discussed in more detail in Manipulating Display Memory
below. The VGA has three modes for addressing, Chain 4, Odd/Even mode,
and normal mode:
<UL>
<LI>
Chain 4: This mode is used for MCGA emulation in the 320x200 256-color
mode. The address is mapped to memory MOD 4 (shifted right 2 places.)</LI>
</UL>
<B>&lt;More to be added here.></B>
<P><A NAME="manip"></A><B>Manipulating Display Memory</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA hardware contains
hardware that can perform bit manipulation on data and allow the host to
operate on all four display planes in a single operation. These features
are fairly straightforward, yet complicated enough that most VGA programmers
choose to ignore them. This is unfortunate, as properly utilization of
these registers is crucial to programming the VGA's 16 color modes. Also,
knowledge of this functionality can in many cases enhance performance in
other modes including text and 256 color modes. In addition to normal read
and write operations the VGA hardware provides enhanced operations such
as the ability to perform rapid comparisons, to write to multiple planes
simultaneously, and to rapidly move data from one area of display memory
to another, faster logical operations (AND/OR/XOR) as well as bit rotation
and masking.
<P><A NAME="read"></A><B>Reading from Display Memory</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA hardware has two
read modes, selected by the <A HREF="graphreg.htm#05">Read Mode</A> field.
The first is a straightforward read of one or more consecutive bytes (depending
on whether a byte, word or dword operation is used) from one bit plane.
The value of the <A HREF="graphreg.htm#04">Read Map Select</A> field is
the page that will be read from. The second read mode returns the result
of a comparison of the display memory and the <A HREF="graphreg.htm#02">Color
Compare</A> field and masked by the <A HREF="graphreg.htm#07">Color Don't
Care</A> field. This mode which can be used to rapidly perform up to 32
pixel comparisons in one operation in the planar video modes, helpful for
the implementation of fast flood-fill routines. A read from display memory
also loads a 32 bit latch register, one byte from each plane. This latch
register, is not directly accessible from the host CPU; rather it can be
used as data for the various write operations. The latch register retains
its value until the next read and thus may be used with more than one write
operation.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The two read modes, simply called
Read Mode 0-1 based on the value of the <A HREF="graphreg.htm#05">Read
Mode</A> field are:
<UL>
<LI>
<B>Read Mode 0:</B></LI>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Read Mode 0 is used to read one
byte from a single plane of display memory. The plane read is the value
of the <A HREF="graphreg.htm#04">Read Map Select</A> field. In order to
read a single pixel's value in planar modes, four read operations must
be performed, one for each plane. If more than one bytes worth of data
is being read from the screen it is recommended that you read it a plane
at a time instead of having to perform four I/O operations to the <A HREF="graphreg.htm#04">Read
Map Select</A> field for each byte, as this will allow the use of faster
string copy instructions and reduce the number I/O operations performed.
<LI>
<B>Read Mode 1:</B></LI>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Read Mode 1 is used to perform
comparisons against a reference color, specified by the <A HREF="graphreg.htm#02">Color
Compare</A> field. If a bit is set in the <A HREF="graphreg.htm#07">Color
Don't Care</A> field then the corresponding color plane is considered for
by the comparison, otherwise it is ignored. Each bit in the returned result
represents one comparison between the reference color from the <A HREF="graphreg.htm#02">Color
Compare</A> field, with the bit being set if the comparison is true. This
mode is mainly used by flood fill algorithms that fill an area of a specific
color, as it requires 1/4 the number of reads to determine the area that
needs to be filled in addition to the additional work done by the comparison.
Also an efficient "search and replace" operation that replaces one color
with another can be performed when this mode is combined with Write Mode
3.</UL>
<A NAME="write"></A><B>Writing to Display Memory</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA has four write modes,
selected by the <A HREF="graphreg.htm#05">Write Mode</A> field. This controls
how the write operation and host data affect the display memory. The VGA,
depending on the <A HREF="graphreg.htm#05">Write Mode</A> field performs
up to five distinct operations before the write affects display memory.
Note that not all write modes use all of pipelined stages in the write
hardware, and others use some of the pipelined stages in different ways.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The first of these allows
the VGA hardware to perform a bitwise rotation on the data written from
the host. This is accomplished via a barrel rotator that rotates the bits
to the right by the number of positions specified by the <A HREF="graphreg.htm#03">Rotate
Count</A> field. This performs the same operation as the 8086 ROR instruction,
shifting bits to the right (from bit 7 towards bit 0.) with the bit shifted
out of position 0 being "rolled" into position 7. Note that if the rotate
count field is zero then no rotation is performed.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The second uses the <A HREF="graphreg.htm#01">Enable
Set/Reset</A> and <A HREF="graphreg.htm#00">Set/Reset</A> fields. These
fields can provide an additional data source in addition to the data written
and the latched value from the last read operation performed. Normally,
data from the host is replicated four times, one for each plane. In this
stage, a 1 bit in the <A HREF="graphreg.htm#01">Enable Set/Reset</A> field
will cause the corresponding bit plane to be replaced by the bit value
in the corresponding <A HREF="graphreg.htm#00">Set/Reset</A> field location,
replicated 8 times to fill the byte, giving it either the value 00000000b
or 11111111b. If the <A HREF="graphreg.htm#01">Enable Set/Reset</A> field
for a given plane is 0 then the host data byte is used instead. Note that
in some write modes, the host data byte is used for other purposes, and
the set/reset register is always used as data, and in other modes the set/reset
mechanism is not used at all.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The third stage performs logical operations
between the host data, which has been split into four planes and is now
32-bits wide, and the latch register, which provides a second 32-bit operand.
The <A HREF="graphreg.htm#03">Logical Operation</A> field selects the operation
that this stage performs. The four possibilities are: NOP (the host data
is passed directly through, performing no operation), AND (the data is
logically ANDed with the latched data.), OR (the data is logically ORed
with the latched data), and XOR (the data is logically XORed with the latched
data.) The result of this operation is then passed on. whilst the latched
data remains unchanged, available for use in successive operations.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In the fourth stage, individual
bits may be selected from the result or copied from the latch register.
Each bit of the <A HREF="graphreg.htm#08">Bit Mask</A> field determines
whether the corresponding bits in each plane are the result of the previous
step or are copied directly from the latch register. This allows the host
CPU to modify only a single bit, by first performing a dummy read to fill
the latch register
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The fifth stage allows specification
of what planes, if any a write operation affects, via the <A HREF="seqreg.htm#02">Memory
Plane Write Enable</A> field. The four bits in this field determine whether
or not the write affects the corresponding plane If the a planes bit is
1 then the data from the previous step will be written to display memory,
otherwise the display buffer location in that plane will remain unchanged.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The four write modes, of
which the current one is set by writing to the <A HREF="graphreg.htm#05">Write
Mode</A> field The four write modes, simply called write modes 0-3, based
on the value of the <A HREF="graphreg.htm#05">Write Mode</A> field are:
<UL>
<LI>
<B>Write Mode 0:</B></LI>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write Mode 0 is the standard
and most general write mode. While the other write modes are designed to
perform a specific task, this mode can be used to perform most tasks as
all five operations are performed on the data. The data byte from the host
is first rotated as specified by the <A HREF="graphreg.htm#03">Rotate Count</A>
field, then is replicated across all four planes. Then the <A HREF="graphreg.htm#01">Enable
Set/Reset</A> field selects which planes will receive their values from
the host data and which will receive their data from that plane's <A HREF="graphreg.htm#00">Set/Reset</A>
field location. Then the operation specified by the <A HREF="graphreg.htm#03">Logical
Operation</A> field is performed on the resulting data and the data in
the read latches. The <A HREF="graphreg.htm#08">Bit Mask</A> field is then
used to select between the resulting data and data from the latch register.
Finally, the resulting data is written to the display memory planes enabled
in the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.
<LI>
<B>Write Mode 1:</B></LI>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write Mode 1 is used to
transfer the data in the latches register directly to the screen, affected
only by the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.
This can facilitate rapid transfer of data on byte boundaries from one
area of video memory to another or filling areas of the display with a
pattern of 8 pixels. When Write Mode 0 is used with the <A HREF="graphreg.htm#08">Bit
Mask</A> field set to 00000000b the operation of the hardware is identical
to this mode, although it is entirely possible that this mode is faster
on some cards.
<LI>
<B>Write Mode 2:</B></LI>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write Mode 2 is used to
unpack a pixel value packed into the lower 4 bits of the host data byte
into the 4 display planes. In the byte from the host, the bit representing
each plane will be replicated across all 8 bits of the corresponding planes.
Then the operation specified by the <A HREF="graphreg.htm#03">Logical Operation</A>
field is performed on the resulting data and the data in the read latches.
The <A HREF="graphreg.htm#08">Bit Mask</A> field is then used to select
between the resulting data and data from the latch register. Finally, the
resulting data is written to the display memory planes enabled in the <A HREF="seqreg.htm#02">Memory
Plane Write Enable</A> field.
<LI>
<B>Write Mode 3:</B></LI>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>Write Mode 3 is used
when the color written is fairly constant but the <A HREF="graphreg.htm#08">Bit
Mask</A> field needs to be changed frequently, such as when drawing single
color lines or text. The value of the <A HREF="graphreg.htm#00">Set/Reset</A>
field is expanded as if the <A HREF="graphreg.htm#01">Enable Set/Reset</A>
field were set to 1111b, regardless of its actual value. The host data
is first rotated as specified by the <A HREF="graphreg.htm#03">Rotate Count</A>
field, then is ANDed with the <A HREF="graphreg.htm#08">Bit Mask</A> field.
The resulting value is used where the <A HREF="graphreg.htm#08">Bit Mask</A>
field normally would be used, selecting data from either the expansion
of the <A HREF="graphreg.htm#00">Set/Reset</A> field or the latch register.
Finally, the resulting data is written to the display memory planes enabled
in the <A HREF="seqreg.htm#02">Memory Plane Write Enable</A> field.</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

View File

@@ -0,0 +1,508 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--Accessing the VGA Registers</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#general">Intro</A> <A HREF="#general">Advice</A>
<A HREF="#fudge">Fudge</A> <A HREF="#paranoia">Paranoia</A> <A HREF="#external">External</A>
<A HREF="#indexed">Indexed</A> <A HREF="#attribute">Attribute</A> <A HREF="#color">Color</A>
<A HREF="#binary">Binary</A> <A HREF="#example">Example</A> <A HREF="#bitfields">Masking</A>
<A HREF="vga.htm#register">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>Accessing the VGA Registers&nbsp;
<HR WIDTH="100%"></CENTER>
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- provides a general overview of accessing
the VGA registers.</LI>
<LI>
<A HREF="#general">General Advice</A> -- basic guidelines for use when
accessing VGA registers.</LI>
<LI>
<A HREF="#fudge">I/O Fudge Factor</A> -- discusses delays between I/O accesses.</LI>
<LI>
<A HREF="#paranoia">Paranoia</A> -- discusses making code more robust.</LI>
<LI>
<A HREF="#external">Accessing the External Registers</A> -- details and
guidelines for accessing these registers.</LI>
<LI>
<A HREF="#indexed">Accessing the Sequencer, Graphics, and CRT Controller
Registers</A> -- details and guidelines for accessing these registers,
including step-by-step instructions.</LI>
<LI>
<A HREF="#attribute">Accessing the Attribute Registers</A> -- details and
guidelines for accessing this register, including step-by-step instructions.</LI>
<LI>
<A HREF="#color">Accessing the Color Registers</A> -- details and guidelines
for accessing this register, including step-by-step instructions.</LI>
<LI>
<A HREF="#binary">Binary Operations</A> -- details on the operation of
the logical operators OR, AND, and XOR.</LI>
<LI>
<A HREF="#example">Example Register</A> -- an example register selected
to demonstrate both the format they will be presented in and how fields
work.</LI>
<LI>
<A HREF="#bitfields">Masking Bit-Fields</A> -- details on changing specific
fields within registers using the logical operators.</LI>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section discusses methods
of manipulating the particular registers present in VGA hardware. Depending
upon which register one is accessing, the method of accessing them is different
and sometimes difficult to understand. The VGA has many more registers
than it has I/O ports, thus it must provide a way to re-use or multiplex
many registers onto a relatively small number of ports. All of the VGA
ports are accessed by inputting and outputting bytes to I/O ports; however,
in many cases it is necessary to perform additional steps to ready the
VGA adapter for reading and writing data. Port addresses are given at their
hexadecimal address, such as 3C2h.
<P><A NAME="general"></A><B>General Advice</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>If a program takes
control of the video card and changes its state, it is considered good
programming practice to keep track of the original values of any register
it changes such that upon termination (normal or abnormal) it can write
them back to the hardware to restore the state. Anyone who has seen a graphics
application abort in the middle of a graphics screen knows how annoying
this can be. Almost all of the VGA registers can be saved and restored
in this fashion. In addition when changing only a particular field of a
register, the value of the register should be read and the byte should
be masked so that only the field one is trying to change is actually changed.
<P><A NAME="fudge"></A><B>I/O Fudge Factor</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Often a hardware device
is not capable handling I/O accesses as fast as the processor can issue
them. In this case, a program must provide adequate delay between I/O accesses
to the same device. While many modern chipsets provide this delay in hardware,
there are still many implementations in existence that do not provide this
delay. If you are attempting to write programs for the largest possible
variety of hardware configurations, then it is necessary to know the amount
of delay necessary. Unfortunately, this delay is not often specified, and
varies from one VGA implementation to another. In the interest of performance
it is ideal to keep this delay to the minimum necessary. In the interest
of compatibility it is necessary to implement a delay independent of clock
speed. (Faster processors are continuously being developed, and also a
user may change clock speed dynamically via the Turbo button on their case.)
<P><A NAME="paranoia"></A><B>Paranoia</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If one wishes to be extra
cautious when writing to registers, after writing to a register one can
read the value back and compare it with the original value. If they differ
it may mean that the VGA hardware has a stuck bit in one its registers,
that you are attempting to modify a locked or unsupported register, or
that you are not providing enough delay between I/O accesses. As long as
reading the register twice doesn't have any unintended side effects, when
reading a registers value, one can read the register twice and compare
the values read, after masking out any fields that may change without CPU
intervention. If the values read back are different it may mean that you
are not providing enough delay between I/O accesses, that the hardware
is malfunctioning, or are reading the wrong register or field. Other problems
that these techniques can address are noise on the I/O bus due to faulty
hardware, dirty contacts, or even sunspots! When perform I/O operations
and these checks fail, try repeating the operation, possibly with increased
I/O delay time. By providing extra robustness, I have found that my own
programs will work properly on hardware that causes less robust programs
to fail.
<P><A NAME="external"></A><B>Accessing the External Registers</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The external registers are
the easiest to program, because they each have their own separate I/O address.
Reading and writing to them is as simple as inputting and outputting bytes
to their respective port address. Note, however some, such as the Miscellaneous
Output Register is written at port 3C2h, but is read at port 3CCh. The
reason for this is for backwards compatibility with the EGA and previous
adapters. Many registers in the EGA were write only, and thus the designers
placed read-only registers at the same location as write-only ones. However,
the biggest complaint programmers had with the EGA was the inability to
read the EGA's video state and thus in the design of the VGA most of these
write-only registers were changed to read/write registers. However, for
backwards compatibility, the read-only register had to remain at 3C2h,
so they used a different port.
<P><A NAME="indexed"></A><B>Accessing the Sequencer, Graphics, and CRT
Controller Registers</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; These registers are accessed
in an indexed fashion. Each of the three have two unique read/write ports
assigned to them. The first port is the Address Register for the group.
The other is the Data Register for the group. By writing a byte to the
Address Register equal to the index of the particular sub-register you
wish to access, one can address the data pointed to by that index by reading
and writing the Data Register. The current value of the index can be read
by reading the Address Register. It is best to save this value and restore
it after writing data, particularly so in an interrupt routine because
the interrupted process may be in the middle of writing to the same register
when the interrupt occurred. To read and write a data register in one of
these register groups perform the following procedure:
<OL>
<LI>
Input the value of the Address Register and save it for step 6</LI>
<LI>
Output the index of the desired Data Register to the Address Register.</LI>
<LI>
Read the value of the Data Register and save it for later restoration upon
termination, if needed.</LI>
<LI>
If writing, modify the value read in step 3, making sure to mask off bits
not being modified.</LI>
<LI>
If writing, write the new value from step 4 to the Data register.</LI>
<LI>
Write the value of Address register saved in step 1 to the Address Register.</LI>
</OL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If you are paranoid, then you
might want to read back and compare the bytes written in step 2, 5, and
6 as in the <A HREF="#paranoia">Paranoia</A> section above. Note that certain
CRTC registers can be protected from read or write access for compatibility
with programs written prior to the VGA's existence. This protection is
controlled via the <A HREF="crtcreg.htm#03">Enable Vertical Retrace Access</A>
and <A HREF="crtcreg.htm#11">CRTC Registers Protect Enable</A> fields.
Ensuring that access is not prevented even if your card does not normally
protect these registers makes your
<P><A NAME="attribute"></A><B>Accessing the Attribute Registers</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The attribute registers
are also accessed in an indexed fashion, albeit in a more confusing way.
The address register is read and written via port 3C0h. The data register
is written to port 3C0h and read from port 3C1h. The index and the data
are written to the same port, one after another. A flip-flop inside the
card keeps track of whether the next write will be handled is an index
or data. Because there is no standard method of determining the state of
this flip-flop, the ability to reset the flip-flop such that the next write
will be handled as an index is provided. This is accomplished by reading
the Input Status #1 Register (normally port 3DAh) (the data received is
not important.) This can cause problems with interrupts because there is
no standard way to find out what the state of the flip-flop is; therefore
interrupt routines require special card when reading this register. (Especially
since the Input Status #1 Register's purpose is to determine whether a
horizontal or vertical retrace is in progress, something likely to be read
by an interrupt routine that deals with the display.) If an interrupt were
to read 3DAh in the middle of writing to an address/data pair, then the
flip-flop would be reset and the data would be written to the address register
instead. Any further writes would also be handled incorrectly and thus
major corruption of the registers could occur. To read and write an data
register in the attribute register group, perform the following procedure:
<OL>
<LI>
Input a value from the Input Status #1 Register (normally port 3DAh) and
discard it.</LI>
<LI>
Read the value of the Address/Data Register and save it for step 7.</LI>
<LI>
Output the index of the desired Data Register to the Address/Data Register</LI>
<LI>
Read the value of the Data Register and save it for later restoration upon
termination, if needed.</LI>
<LI>
If writing, modify the value read in step 4, making sure to mask off bits
not being modified.</LI>
<LI>
If writing, write the new value from step 5 to the Address/Data register.</LI>
<LI>
Write the value of Address register saved in step 1 to the Address/Data
Register.</LI>
<LI>
If you wish to leave the register waiting for an index, input a value from
the Input Status #1 Register (normally port 3DAh) and discard it.</LI>
</OL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If you have control over interrupts,
then you can disable interrupts while in the middle of writing to the register.
If not, then you may be able to implement a critical section where you
use a byte in memory as a flag whether it is safe to modify the attribute
registers and have your interrupt routine honor this. And again, it pays
to be paranoid. Resetting the flip-flop even though it <B>should</B> be
in the reset state already helps prevent catastrophic problems. Also, you
might want to read back and compare the bytes written in step 3, 6, and
7 as in the <A HREF="#paranoia">Paranoia</A> section above.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; On the IBM VGA implementation,
an undocumented register (CRTC Index=24h, bit 7) can be read to determine
the status of the flip-flop (0=address,1=data) and many VGA compatible
chipsets duplicate this behavior, but it is not guaranteed. However, it
is a simple matter to determine if this is the case. Also, some SVGA chipsets
provide the ability to access the attribute registers in the same fashion
as the CRT, Sequencer, and Graphics controllers. Because this functionality
is vendor specific it is really only useful when programming for that particular
chipset. To determine if this undocumented bit is supported, perform the
following procedure:
<OL>
<LI>
Input a value from the Input Status #1 Register (normally port 3DAh) and
discard it.</LI>
<LI>
Verify that the flip-flop status bit (CRTC Index 24, bit 7) is 0. If bit=1
then feature is not supported, else continue to step 3.</LI>
<LI>
Output an address value to the Attribute Address/Data register.</LI>
<LI>
Verify that the flip-flop status bit (CRTC Index 24, bit 7) is 1. If bit=0
then feature is not supported, else continue to step 5.</LI>
<LI>
Input a value from the Input Status #1 Register (normally port 3DAh) and
discard it.</LI>
<LI>
Verify that the flip-flop status bit (CRTC Index 24, bit 7) is 0. If bit=1
then feature is not supported, else feature is supported.</LI>
</OL>
<A NAME="color"></A><B>Accessing the Color Registers</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp; The color registers require an altogether
different technique; this is because the 256-color palette requires 3 bytes
to store 18-bit color values. In addition the hardware supports the capability
to load all or portions of the palette rapidly. To write to the palette,
first you must output the value of the palette entry to the PEL Address
Write Mode Register (port 3C8h.) Then you should output the component values
to the PEL Data Register (port 3C9h), in the order red, green, then blue.
The PEL Address Write Mode Register will then automatically increment,
allowing the component values of the palette entry to be written to the
PEL Data Register. Reading is performed similarly, except that the PEL
Address Read Mode Register (port 3C7h) is used to specify the palette entry
to be read, and the values are read from the PEL Data Register. Again,
the PEL Address Read Mode Register auto-increments after each triplet is
written. The current index for the current operation can be read from the
PEL Address Write Mode Register. Reading port 3C7h gives the DAC State
Register, which specifies whether a read operation or a write operation
is in effect. As in the attribute registers, there is guaranteed way for
an interrupt routine to access the color registers and return the color
registers to the state they were in prior to access without some communication
between the ISR and the main program. For some workarounds see the <A HREF="#attribute">Accessing
the Attribute Registers</A> section above. To read the color registers:
<OL>
<LI>
Read the DAC State Register and save the value for use in step 8.</LI>
<LI>
Read the PEL Address Write Mode Register for use in step 8.</LI>
<LI>
Output the value of the first color entry to be read to the PEL Address
Read Mode Register.</LI>
<LI>
Read the PEL Data Register to obtain the red component value.</LI>
<LI>
Read the PEL Data Register to obtain the green component value.</LI>
<LI>
Read the PEL Data Register to obtain the blue component value.</LI>
<LI>
If more colors are to be read, repeat steps 4-6.</LI>
<LI>
Based upon the DAC State from step 1, write the value saved in step 2 to
either the PEL Address Write Mode Register or the PEL Address Read Mode
Register.</LI>
</OL>
Note: Steps 1, 2, and 8 are hopelessly optimistic. This in no way guarantees
that the state is preserved, and with some DAC implementations this may
actually guarantee that the state is never preserved. See the <A HREF="vgadac.htm">DAC
Operation</A> page for more details.
<P><A NAME="binary"></A><B>Binary Operations</B>
<BR><B>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </B>In order to better
understand dealing with bit fields it is necessary to know a little bit
about logical operations such as logical-and (AND), logical-or (OR), and
exclusive-or(XOR.) These operations are performed on a bit by bit basis
using the truth tables below. All of these operations are commutative,
i.e. A OR B = B OR A, so you look up one bit in the left column and the
other in the top row and consult the intersecting row and column for the
answer.
<BR>&nbsp;
<CENTER><TABLE BORDER WIDTH="500" >
<TR ALIGN=CENTER>
<TD COLSPAN="3"><B>AND</B></TD>
<TD></TD>
<TD COLSPAN="3"><B>OR</B></TD>
<TD></TD>
<TD COLSPAN="3"><B>XOR</B></TD>
</TR>
<TR ALIGN=CENTER>
<TD WIDTH="10%"></TD>
<TD WIDTH="10%"><B>0</B></TD>
<TD WIDTH="10%"><B>1</B></TD>
<TD></TD>
<TD WIDTH="10%"></TD>
<TD WIDTH="10%"><B>0</B></TD>
<TD WIDTH="10%"><B>1</B></TD>
<TD></TD>
<TD WIDTH="10%"></TD>
<TD WIDTH="10%"><B>0</B></TD>
<TD WIDTH="10%"><B>1</B></TD>
</TR>
<TR ALIGN=CENTER>
<TD><B>0</B></TD>
<TD>0</TD>
<TD>0</TD>
<TD></TD>
<TD><B>0</B></TD>
<TD>0</TD>
<TD>1</TD>
<TD></TD>
<TD><B>0</B></TD>
<TD>0</TD>
<TD>1</TD>
</TR>
<TR ALIGN=CENTER>
<TD><B>1</B></TD>
<TD>0</TD>
<TD>1</TD>
<TD></TD>
<TD><B>1</B></TD>
<TD>1</TD>
<TD>1</TD>
<TD></TD>
<TD><B>1</B></TD>
<TD>1</TD>
<TD>0</TD>
</TR>
</TABLE></CENTER>
<BR>
<A NAME="example"></A><B>Example Register</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The following table is an
example of one particular register, the Mode Register of the Graphics Register.
Each number from 7-0 represents the bit position in the byte. Many registers
contain more than one field, each of which performs a different function.
This particular chart contains four fields, two of which are two bits in
length. It also contains two bits which are not implemented (to the best
of my knowledge) by the standard VGA hardware.
<BR>&nbsp;
<TABLE BORDER WIDTH="600" CELLPADING="2" >
<CAPTION ALIGN=TOP><B>Mode Register (Index 05h)</B></CAPTION>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75">7</TD>
<TD WIDTH="75">6</TD>
<TD WIDTH="75">5</TD>
<TD WIDTH="75">4</TD>
<TD WIDTH="75">3</TD>
<TD WIDTH="75">2</TD>
<TD WIDTH="75">1</TD>
<TD WIDTH="75">0</TD>
</TR>
<TR ALIGN=CENTER VALIGN=CENTER>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Shift Register</TD>
<TD WIDTH="75">Odd/Even</TD>
<TD WIDTH="75">RM</TD>
<TD WIDTH="75"></TD>
<TD COLSPAN="2" WIDTH="150">Write Mode</TD>
</TR>
</TABLE>
<BR>
<A NAME="bitfields"></A><B>Masking Bit-Fields</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Your development environment
may provide some assistance in dealing with bit fields. Consult your documentation
for this. In addition it can be performed using the logical operators AND,
OR, and XOR (for details on these operators see the <A HREF="#binary">Binary
Operations</A> section above.) To change the value of the Shift Register
field of the example register above, we would first mask out the bits we
do not wish to change. This is accomplished by performing a logical AND
of the value read from the register and a binary value in which all of
the bits we wish to leave alone are set to 1, which would be 10011111b
for our example. This leaves all of the bits except the Shift Register
field alone and set the Shift Register field to zero. If this was our goal,
then we would stop here and write the value back to the register. We then
OR the value with a binary number in which the bits are shifted into position.
To set this field to 10b we would OR the result of the AND with 01000000b.
The resulting byte would then be written to the register. To set a bitfield
to all ones the AND step is not necessary, similar to setting the bitfield
to all zeros using AND. To toggle a bitfield you can XOR a value with a
byte with a ones in the positions to toggle. For example XORing the value
read with 01100000b would toggle the value of the Shift Register bitfield.
By using these techniques you can assure that you do not cause any unwanted
"side-effects" when modifying registers.
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

View File

@@ -0,0 +1,385 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--VGA Field Index</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#A">A</A> <A HREF="#B">B</A>
<A HREF="#C">C</A>&nbsp; <A HREF="#D">D</A>&nbsp; <A HREF="#E">E</A>&nbsp;
<A HREF="#F">F</A>&nbsp; G&nbsp; <A HREF="#H">H</A>&nbsp; <A HREF="#I">I</A>&nbsp;
J&nbsp; K&nbsp; <A HREF="#L">L</A>&nbsp; <A HREF="#M">M</A>&nbsp; N&nbsp;
<A HREF="#O">O</A>&nbsp; <A HREF="#P">P</A>&nbsp; Q&nbsp; <A HREF="#R">R</A>&nbsp;
<A HREF="#S">S</A>&nbsp; T&nbsp; <A HREF="#U">U</A>&nbsp; <A HREF="#V">V</A>&nbsp;
<A HREF="#W">W</A>&nbsp; X&nbsp; Y&nbsp; Z <A HREF="vga.htm#index">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>VGA Field Index&nbsp;
<HR WIDTH="100%"></CENTER>
<CENTER><A HREF="#A">A</A> | <A HREF="#B">B</A> | <A HREF="#C">C</A> |&nbsp;
<A HREF="#D">D</A> | <A HREF="#E">E</A> | <A HREF="#F">F</A> | G | <A HREF="#H">H</A>
| <A HREF="#I">I</A> | J | K | <A HREF="#L">L</A> | <A HREF="#M">M</A>
| N | <A HREF="#O">O</A> | <A HREF="#P">P</A> | Q | <A HREF="#R">R</A>
| <A HREF="#S">S</A> | T | <A HREF="#U">U</A> | <A HREF="#V">V</A> | <A HREF="#W">W</A>
| X | Y | Z</CENTER>
<UL>
<LI>
256-Color Shift Mode -- <A HREF="graphreg.htm#05">Graphics Mode Register</A></LI>
<LI>
8-bit Color Enable -- <A HREF="attrreg.htm#10">Attribute Mode Control Register</A></LI>
<LI>
9/8 Dot Mode -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
<A NAME="A"></A>Address Wrap Select -- <A HREF="crtcreg.htm#17">CRTC Mode
Control Register</A></LI>
<LI>
Alphanumeric Mode Disable -- <A HREF="graphreg.htm#06">Miscellaneous Graphics
Register</A></LI>
<LI>
Asynchronous Reset -- <A HREF="seqreg.htm#00">Reset Register</A></LI>
<LI>
Attribute Address -- <A HREF="attrreg.htm#3C0">Attribute Address Register</A></LI>
<LI>
Attribute Controller Graphics Enable -- <A HREF="attrreg.htm#10">Attribute
Mode Control Register</A></LI>
<LI>
<A NAME="B"></A>Bit Mask -- <A HREF="graphreg.htm#08">Bit Mask Register</A></LI>
<LI>
Blink Enable -- <A HREF="attrreg.htm#10">Attribute Mode Control Register</A></LI>
<LI>
Byte Panning -- <A HREF="crtcreg.htm#08">Preset Row Scan Register</A></LI>
<LI>
<A NAME="C"></A>Chain 4 Enable -- <A HREF="seqreg.htm#04">Sequencer Memory
Mode Register</A></LI>
<LI>
Clock Select -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output Register</A></LI>
<LI>
Chain Odd/Even Enable -- <A HREF="graphreg.htm#06">Miscellaneous Graphics
Register</A></LI>
<LI>
Character Set A Select -- <A HREF="seqreg.htm#03">Character Map Select
Register</A></LI>
<LI>
Character Set B Select -- <A HREF="seqreg.htm#03">Character Map Select
Register</A></LI>
<LI>
Color Compare -- <A HREF="graphreg.htm#02">Color Compare Register</A></LI>
<LI>
Color Don't Care -- <A HREF="graphreg.htm#07">Color Don't Care Register</A></LI>
<LI>
Color Plane Enable -- <A HREF="attrreg.htm#12">Color Plane Enable Register</A></LI>
<LI>
Color Select 5-4 -- <A HREF="attrreg.htm#14">Color Select Register</A></LI>
<LI>
Color Select 7-6 -- <A HREF="attrreg.htm#14">Color Select Register</A></LI>
<LI>
CRTC Registers Protect Enable -- <A HREF="crtcreg.htm#11">Vertical Retrace
End Register</A></LI>
<LI>
Cursor Disable -- <A HREF="crtcreg.htm#0A">Cursor Start Reguster</A></LI>
<LI>
Cursor Location -- bits 15-8: <A HREF="crtcreg.htm#0E">Cursor Location
High Register</A>, bits 7-0: <A HREF="crtcreg.htm#0F">Cursor Location Low
Register</A></LI>
<LI>
Cursor Scan Line End -- <A HREF="crtcreg.htm#0B">Cursor End Register</A></LI>
<LI>
Cursor Scan Line Start -- <A HREF="crtcreg.htm#0A">Cursor Start Reguster</A></LI>
<LI>
Cursor Skew -- <A HREF="crtcreg.htm#0B">Cursor End Register</A></LI>
<LI>
<A NAME="D"></A>DAC Data -- <A HREF="colorreg.htm#3C9">DAC Data Register</A></LI>
<LI>
DAC Read Address -- <A HREF="colorreg.htm#3C7W">DAC Address Read Mode Register</A></LI>
<LI>
DAC State -- <A HREF="colorreg.htm#3C7R">DAC State Register</A></LI>
<LI>
DAC Write Address -- <A HREF="colorreg.htm#3C8">DAC Address Write Mode
Register</A></LI>
<LI>
Display Disabled -- <A HREF="extreg.htm#3xAR">Input Status #1 Register</A></LI>
<LI>
Display Enable Skew -- <A HREF="crtcreg.htm#03">End Horizontal Blanking
Register</A></LI>
<LI>
Divide Memory Address Clock by 4 -- <A HREF="crtcreg.htm#14">Underline
Location Register</A></LI>
<LI>
Divide Scan Line Clock by 2 -- <A HREF="crtcreg.htm#17">CRTC Mode Control
Register</A></LI>
<LI>
Dot Clock Rate -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Double-Word Addressing -- <A HREF="crtcreg.htm#14">Underline Location Register</A></LI>
<LI>
<A NAME="E"></A>Enable Set/Reset -- <A HREF="graphreg.htm#01">Enable Set/Reset
Register</A></LI>
<LI>
Enable Vertical Retrace Access -- <A HREF="crtcreg.htm#03">End Horizontal
Blanking Register</A></LI>
<LI>
End Horizontal Display -- <A HREF="crtcreg.htm#01">End Horizontal Display
Register</A></LI>
<LI>
End Horizontal Blanking -- bit 5: <A HREF="crtcreg.htm#05">End Horizontal
Retrace Register</A>, bits 4-0: <A HREF="crtcreg.htm#03">End Horizontal
Blanking Register</A>,</LI>
<LI>
End Horizontal Retrace -- <A HREF="crtcreg.htm#05">End Horizontal Retrace
Register</A></LI>
<LI>
End Vertical Blanking -- <A HREF="crtcreg.htm#16">End Vertical Blanking
Register</A></LI>
<LI>
Extended Memory -- <A HREF="seqreg.htm#04">Sequencer Memory Mode Register</A></LI>
<LI>
<A NAME="F"></A>Feature Control Bit 0 -- <A HREF="extreg.htm#3CAR3xAW">Feature
Control Register</A></LI>
<LI>
Feature Control Bit 1 -- <A HREF="extreg.htm#3CAR3xAW">Feature Control
Register</A></LI>
<LI>
<A NAME="H"></A>Horizontal Retrace Skew -- <A HREF="crtcreg.htm#05">End
Horizontal Retrace Register</A></LI>
<LI>
Horizontal Sync Polarity -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous
Output Register</A></LI>
<LI>
Horizontal Total -- <A HREF="crtcreg.htm#00">Horizontal Total Register</A></LI>
<LI>
Host Odd/Even Memory Read Addressing Enable -- <A HREF="graphreg.htm#05">Graphics
Mode Register</A></LI>
<LI>
Host Odd/Even Memory Write Addressing Enable -- <A HREF="seqreg.htm#04">Sequencer
Memory Mode Register</A></LI>
<LI>
<A NAME="I"></A>Input/Output Address Select -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous
Output Register</A></LI>
<LI>
Internal Palette Index -- <A HREF="attrreg.htm#000F">Palette Registers</A></LI>
<LI>
<A NAME="L"></A>Line Compare -- bit 9: <A HREF="crtcreg.htm#09">Maximum
Scan Line Register</A>, bit 8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#18">Line Compare Register</A></LI>
<LI>
Line Graphics Enable -- <A HREF="attrreg.htm#10">Attribute Mode Control
Register</A></LI>
<LI>
Logical Operation -- <A HREF="graphreg.htm#03">Data Rotate Register</A></LI>
<LI>
<A NAME="M"></A>Map Display Address 13 -- <A HREF="crtcreg.htm#17">CRTC
Mode Control Register</A></LI>
<LI>
Map Display Address 14 -- <A HREF="crtcreg.htm#17">CRTC Mode Control Register</A></LI>
<LI>
Maximum Scan Line -- <A HREF="crtcreg.htm#09">Maximum Scan Line Register</A></LI>
<LI>
Memory Map Select -- <A HREF="graphreg.htm#06">Miscellaneous Graphics Register</A></LI>
<LI>
Memory Plane Write Enable -- <A HREF="seqreg.htm#02">Map Mask Register</A></LI>
<LI>
Memory Refresh Bandwidth -- <A HREF="crtcreg.htm#11">Vertical Retrace End
Register</A></LI>
<LI>
Monochrome Emulation -- <A HREF="attrreg.htm#10">Attribute Mode Control
Register</A></LI>
<LI>
<A NAME="O"></A>Odd/Even Page Select -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous
Output Register</A></LI>
<LI>
Offset -- <A HREF="crtcreg.htm#13">Offset Register</A></LI>
<LI>
Overscan Palette Index -- <A HREF="attrreg.htm#11">Overscan Color Register</A></LI>
<LI>
<A NAME="P"></A>Palette Address Source -- <A HREF="attrreg.htm#3C0">Attribute
Address Register</A></LI>
<LI>
Palette Bits 5-4 Select -- <A HREF="attrreg.htm#10">Attribute Mode Control
Register</A></LI>
<LI>
Pixel Panning Mode -- <A HREF="attrreg.htm#10">Attribute Mode Control Register</A></LI>
<LI>
Pixel Shift Count -- <A HREF="attrreg.htm#13">Horizontal Pixel Panning
Register</A></LI>
<LI>
Preset Row Scan -- <A HREF="crtcreg.htm#08">Preset Row Scan Register</A></LI>
<LI>
<A NAME="R"></A>RAM Enable -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous
Output Register</A></LI>
<LI>
Read Map Select -- <A HREF="graphreg.htm#04">Read Map Select Register</A></LI>
<LI>
Read Mode - <A HREF="graphreg.htm#05">Graphics Mode Register</A></LI>
<LI>
Rotate Count -- <A HREF="graphreg.htm#03">Data Rotate Register</A></LI>
<LI>
<A NAME="S"></A>Scan Doubling -- <A HREF="crtcreg.htm#09">Maximum Scan
Line Register</A></LI>
<LI>
Screen Disable -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Set/Reset -- <A HREF="graphreg.htm#00">Set/Reset Register</A></LI>
<LI>
Shift Four Enable -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Shift/Load Rate -- <A HREF="seqreg.htm#01">Clocking Mode Register</A></LI>
<LI>
Shift Register Interleave Mode -- <A HREF="graphreg.htm#05">Graphics Mode
Register</A></LI>
<LI>
Start Address -- bits 15-8: <A HREF="crtcreg.htm#0C">Start Address High
Register</A>, bits 7-0: <A HREF="crtcreg.htm#0D">Start Address Low Register</A></LI>
<LI>
Start Horizontal Blanking -- <A HREF="crtcreg.htm#02">Start Horizontal
Blanking Register</A></LI>
<LI>
Start Horizontal Retrace -- <A HREF="crtcreg.htm#04">Start Horizontal Retrace
Register</A></LI>
<LI>
Start Vertical Blanking -- bit 9: <A HREF="crtcreg.htm#09">Maximum Scan
Line Register</A>, bit 8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#15">Start Vertical Blanking Register</A></LI>
<LI>
Switch Sense -- <A HREF="extreg.htm#3C2R">Input Status #0 Register</A></LI>
<LI>
Sync Enable -- <A HREF="crtcreg.htm#17">CRTC Mode Control Register</A></LI>
<LI>
Sycnchronous Reset -- <A HREF="seqreg.htm#00">Reset Register</A></LI>
<LI>
<A NAME="U"></A>Underline Location -- <A HREF="crtcreg.htm#14">Underline
Location Register</A></LI>
<LI>
<A NAME="V"></A>Vertical Display End -- bits 9-8: <A HREF="crtcreg.htm#07">Overflow
Register</A>, bits 7-0: <A HREF="crtcreg.htm#12">Vertical Display End Register</A></LI>
<LI>
Vertical Retrace -- <A HREF="extreg.htm#3xAR">Input Status #1 Register</A></LI>
<LI>
Vertical Retrace End -- <A HREF="crtcreg.htm#11">Vertical Retrace End Register</A></LI>
<LI>
Vertical Retrace Start -- bits 9-8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#10">Vertical Retrace Start Register</A></LI>
<LI>
Vertical Sync Polarity -- <A HREF="extreg.htm#3CCR3C2W">Miscellaneous Output
Register</A></LI>
<LI>
Vertical Total -- bits 9-8: <A HREF="crtcreg.htm#07">Overflow Register</A>,
bits 7-0: <A HREF="crtcreg.htm#06">Vertical Total Register</A></LI>
<LI>
<A NAME="W"></A>Word/Byte Mode Select -- <A HREF="crtcreg.htm#17">CRTC
Mode Control Register</A></LI>
<LI>
Write Mode -- <A HREF="graphreg.htm#05">Graphics Mode Register</A></LI>
</UL>
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

View File

@@ -0,0 +1,206 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA - VGA Sequencer Operation</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="vga.htm#general">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>VGA Sequencer Operation&nbsp;
<HR></CENTER>
<B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The sequencer portion of
the VGA hardware reads the display memory and converts it into data that
is sent to the attribute controller.&nbsp; This would normally be a simple
part of the video hardware, but the VGA hardware was designed to provide
a degree of software compatibility with monochrome, CGA, EGA, and MCGA
adapters.&nbsp; For this reason, the sequencer has quite a few different
modes of operation.&nbsp; Further complicating programming, the sequencer
has been poorly documented, resulting in many variances between various
VGA/SVGA implementations.
<BR>&nbsp;
<BR><B>Sequencer Memory Addressing</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The sequencer operates by
loading a display address into memory, then shifting it out pixel by pixel.&nbsp;&nbsp;
The memory is organized internally as 64K addresses, 32 bits wide.&nbsp;
The seqencer maintains an internal 16-bit counter that is used to calculate
the actual index of the 32-bit location to be loaded and shifted out.&nbsp;
There are several different mappings from this counter to actual memory
addressing, some of which use other bits from other counters, as required
to provide compatibility with older hardware that uses those addressing
schemes.
<P>&lt;More to be added here>
<BR>&nbsp;
<BR><B>Graphics Shifting Modes</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; When the <A HREF="graphreg.htm#06">Alphanumeric
Mode Disable</A> field is set to 1, the sequencer operates in graphics
mode where data in memory references pixel values, as opposed to the character
map based operation used for alphanumeric mode.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The sequencer has three
methods of taking the 32-bit memory location loaded and shifting it into
4-bit pixel values suitable for graphics modes, one of which combines 2
pixel values to form 8-bit pixel values.&nbsp; The first method is the
one used for the VGA's 16 color modes.&nbsp; This mode is selected when
both the <A HREF="graphreg.htm#05">256-Color Shift Mode</A> and <A HREF="graphreg.htm#05">Shift
Register Interleave Mode</A> fields are set to 0.&nbsp; In this mode, one
bit from each of the four 8-bit planes in the 32-bit memory is used to
form a 16 color value. This is shown in the diagram below, where the most
significant bit of each of the four planes is shifted out into a pixel
value, which is then sent to the attribute controller to be converted into
an index into the DAC palette.&nbsp; Following this, the remaining bits
will be shifted out one bit at a time, from most to least significant bit,
with the bits from planes 0-3 going to pixel bits 0-3.
<BR>&nbsp;
<BR>&nbsp;
<CENTER><A HREF="seqplanr.txt"><IMG SRC="seqplanr.gif" ALT="Click here for Textified Planar Shift Mode Diagram" HEIGHT=256 WIDTH=376></A></CENTER>
&nbsp;
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The second shift mode is
the packed shift mode, which is selected when both the <A HREF="graphreg.htm#05">256-Color
Shift Mode</A> field is set to 0 and the <A HREF="graphreg.htm#05">Shift
Register Interleave Mode</A> field is set to 1.This is used by the VGA
bios to support video modes compatible with CGA video modes.&nbsp; However,
the CGA only uses planes 0 and 1 providing for a 4 color packed mode; however,
the VGA hardware actually uses bits from two different bit planes, providing
for 16 color modes.&nbsp; The bits for the first four pixels shifted out
for a given address are stored in planes 0 and 2.&nbsp; The second four
are stored in planes 1 and 3.&nbsp; For each pixel, bits 3-2 are shifted
out of the higher numbered plane and bits 1-0 are shifted out of the lower
numbered plane.&nbsp; For example, bits 3-2 of the first pixel shifted
out are located in bits 7-6 of plane 2; likewise, bits 1-0 of the same
pixel are located in bits 7-6 of plane 0.
<BR>&nbsp;
<BR>&nbsp;
<CENTER><A HREF="seqpack.txt"><IMG SRC="seqpack.gif" ALT="Click for Textified Packed Shift Mode Diagram" HEIGHT=256 WIDTH=376></A></CENTER>
&nbsp;
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The third shift mode is used for
256-color modes, which is selected when the <A HREF="graphreg.htm#05">256-Color
Shift Mode</A> field is set to 1 (this field takes precedence over the
<A HREF="graphreg.htm#05">Shift Register Interleave Mode</A> field.)&nbsp;
This behavior of this shift mode varies among VGA implementations, due
to it normally being used in combination with the <A HREF="attrreg.htm#10">8-bit
Color Enable</A> field of the attribute controller.&nbsp; Thus certain
variances in the sequencing operations can be masked by similar variances
in the attribute controller.&nbsp; However, the implementations I have
experimented with seem to fall into one of two similar behaviors, and thus
it is possible to describe both here.&nbsp; Note that one is essentially
a mirror image of the other, leading me to believe that the designers knew
how it should work to be 100% IBM VGA compatible, but managed to get it
backwards in the actual implementation. Due to being very poorly documented
and understood, it is very possible that there are other implementations
that vary significantly from these two cases.&nbsp; I do, however, feel
that attempting to specify each field's function as accurately possible
can allow more powerful utilization of the hardware.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; When this shift mode is
enabled, the VGA hardware shifts 4 bit pixel values out of the 32-bit memory
location each dot clock.&nbsp; This 4-bit value is processed by the attribute
controller, and the lower 4 bits of the resulting DAC index is combined
with the lower 4 bits of the previous attribute lookup to produce an 8-bit
index into the DAC palette.&nbsp; This is why, for example, a 320 pixel
wide 256 color mode needs to be programmed with timing values for a 640
pixel wide normal mode.&nbsp; In 256-color mode, each plane holds a 8-bit
value which is intended to be the DAC palette index for that pixel.&nbsp;
Every second 8-bit index generated should correspond to the values in planes
0-3, appearing left to right on the display.&nbsp; This is masked by the
attribute controller, which in 256 color mode latches every second 8-bit
value as well.&nbsp; This means that the intermediate 8-bit values are
not normally seen, and is where implementations can vary.&nbsp; Another
variance is whether the even or odd pixel values generated are the intended
data bytes.&nbsp; This also is masked by the attribute controller, which
latches the appropriate even or odd pixel values.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The first case is where
the 8-bit values are formed by shifting the 4 8-bit planes left.&nbsp;
This is shown in the diagram below.&nbsp; The first pixel value generated
will be the value held in bits 7-4 of plane 0, which is then followed by
bits 3-0 of plane 0.&nbsp; This continues, shifting out the upper four
bits of each plane in sequence before the lower four bits, ending up with
bits 3-0 of plane 3.&nbsp; Each pixel value is fed to the attribute controller,
where a lookup operation is performed using the attribute table.&nbsp;
The previous 8-bit DAC index is shifted left by four, moving from the lower
four bits to the upper four bits of the DAC index, and the lower 4 bits
of the attribute table entry for the current pixel is shifted into the
lower 4 bits of the 8-bit value, producing a new 8-bit DAC index.&nbsp;
Note how one 4-bit result carries over into the next display memory location
sequenced.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For example, assume planes
0-3 hold 01h, 23h, 45h, and 67h respectively, and the lower 4 bits of the
the attribute table entries hold the value of the index itself, essentially
using the index value as the result, and the last 8-bit DAC index generated
was FEh. The first cycle, the pixel value generated is 0h, which is fed
to the attribute controller and looked up, producing the table entry 0h
(surprise!) The previous DAC index, FEh, is shifted left by four bits,
while the new value, 0h is shifted into the lower four bits.&nbsp; Thus,
the new DAC index output for this pixel is E0h.&nbsp; The next pixel is
1h, which produces 1h at the other end of the attribute controller.&nbsp;
The previous DAC index, E0h is shifted again producing 01h.&nbsp; This
process continues, producing the DAC indexes, in order, 12h, 23h, 34h,
45h, 56h, and 67h.&nbsp; Note that every second DAC index is the appropriate
8-bit value for a 256-color mode, while the values in between contain four
bits of the previous and four bits of the next DAC index.
<BR>&nbsp;
<BR>&nbsp;
<CENTER><A HREF="256left.txt"><IMG SRC="256left.gif" ALT="Click for Textified 256-Color Shift Mode Diagram (Left)" HEIGHT=256 WIDTH=376></A></CENTER>
&nbsp;
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The second case is where the 8-bit
values are formed by shifting the 8-bit values right, as depicted in the
diagram below.&nbsp; The first pixel value generated is the lower four
bits of plane 0, followed by the upper four bits.&nbsp; This continues
for planes 1-3 until the last pixel value produced, which is the upper
four bits of Plane 3.&nbsp; These pixel values are fed to the attribute
controller, where the corresponding entry in the attribute table is looked
up.&nbsp; The previous 8-bit DAC index is shifted right 4 places. and the
lower four bits of the attribute table entry generated is used as the upper
four bits of the new DAC index.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For example, assume planes
0-3 hold 01h, 23h, 45h, and 67h respectively, and the lower 4 bits of the
the attribute table entries hold the value of the index itself, essentially
using the index value as the result, and the last 8-bit DAC index generated
was FEh. The first cycle, the pixel value generated is 1h, which is fed
to the attribute controller and looked up, producing the table entry 1h.
The previous DAC index, FEh, is shifted right by four bits, while the new
value, 1h is shifted into the upper four bits.&nbsp; Thus, the new DAC
index output for this pixel is 1Fh.&nbsp; The next pixel is 0h, which produces
0h at the other end of the attribute controller.&nbsp; The previous DAC
index, 1Fh is shifted again producing 01h.&nbsp; This process continues,
producing the DAC indexes, in order, 30h, 23h, 52h, 45h, 74h, and 67h.&nbsp;
Again, note that every second DAC index is the appropriate 8-bit value
for a 256-color mode, while the values in between contain four bits of
the previous and four bits of the next DAC index.
<BR>&nbsp;
<BR>&nbsp;
<CENTER><A HREF="256right.txt"><IMG SRC="256right.gif" ALT="Click for Textified 256-Color Shift Mode Diagram (Right)" HEIGHT=256 WIDTH=376></A></CENTER>
&nbsp;
<BR>&nbsp;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Another variance that can
exist is whether the first or second DAC index generated at the beginning
of a scan line is the appropriate 8-bit value.&nbsp; If it is the second,
the first DAC index contains 4 bits from the contents of the DAC index
prior to the start of the scan line.&nbsp; This could conceivably contain
any value, as it is normally masked by the attribute controller when in
256-color mode whcih would latch the odd pixel values.&nbsp; Likely this
value will be either 00h or whatever the contents were at the end of the
previous scan line.&nbsp; A similar circumstance arises where the last
pixel value generated falls on a boundary between memory addresses.&nbsp;
In this circumstance, however, the value generated is produced by sequencing
the next display memory address as if the line continued, and is thus more
predictable.
<BR>&nbsp;
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

View File

@@ -0,0 +1,185 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and other low-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>VGA/SVGA Video Programming--VGA Text Mode Operation</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="../home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#memory">Memory</A>
<A HREF="#attributes">Attributes</A> <A HREF="#fonts">Fonts</A> <A HREF="#cursor">Cursor</A>
<A HREF="vga.htm#general">Back</A>&nbsp;
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
Page</B></CENTER>
<CENTER>VGA Text Mode Operation&nbsp;
<HR WIDTH="100%"></CENTER>
<UL>
<LI>
<A HREF="#intro">Introduction</A> -- gives scope of this page.</LI>
<LI>
<A HREF="#memory">Display Memory Organization</A> -- details how the VGA's
planes are utilized when in text mode.</LI>
<LI>
<A HREF="#attributes">Attributes</A> -- details the fields of the attribute
byte.</LI>
<LI>
<A HREF="#fonts">Fonts</A> -- details the operation of the character generation
hardware.</LI>
<LI>
<A HREF="#cursor">Cursor</A> -- details on manipulating the text-mode cursor.</LI>
</UL>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This section is intended
to document the VGA's operation when it is in the text modes, including
attributes and fonts. While it would seem that the text modes are adequately
supported by the VGA BIOS, there is actually much that can be done with
the VGA text modes that can only be accomplished by going directly to the
hardware. Furthermore, I have found no good reference on the VGA text modes;
most VGA references take them for granted without delving into their operation.
<P><A NAME="memory"></A><B>Display Memory Organization</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The four display memory
planes are used for different purposes when the VGA is in text mode. Each
byte in plane 0 is used to store an index into the character font map.
The corresponding byte in plane 1 is used to specify the attributes of
the character possibly including color, font select, blink, underline and
reverse. For more details on attribute operation see the Attributes section
below. Display plane 2 is used to store the bitmaps for the characters
themselves. This is discussed in the Fonts section below. Normally, the
odd/even read and write addressing mode is used to make planes 0 and 1
accessible at interleaved host memory addresses.
<P><A NAME="attributes"></A><B>Attributes</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The attribute byte is divided
into two four bit fields. The field from 7-4 is used as an index into the
palette registers for the background color which used when a font bit is
0. The field from 3-0 is used as an index into the palette registers for
the foreground which is used when a font bit is 1. Also the attribute can
control several other aspects which may modify the way the character is
displayed.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If the <A HREF="attrreg.htm#10">Blink
Enable</A> field is set to 1, character blinking is enabled. When blinking
is enabled, bit 3 of the background color is forced to 0 for attribute
generation purposes, and if bit 7 of the attribute byte for a character
is set to 1, the foreground color alternates between the foreground and
background, causing the character to blink. The blink rate is determined
by the vertical sync rate divided by 32.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If the bits 2-0 of the attribute
byte is equal to 001b and bits 6-4 of the attribute byte is equal to 000b,
then the line of the character specified by the <A HREF="crtcreg.htm#14">Underline
Location</A> field is replaced with the foreground color. Note if the line
specified by the <A HREF="crtcreg.htm#14">Underline Location</A> field
is not normally displayed because it is greater than the maximum scan line
of the characters displayed, then the underline capability is effectively
disabled.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bit 3 of the attribute byte,
as well as selecting the foreground color for its corresponding character,
also is used to select between the two possible character sets (see <A HREF="#fonts">Fonts</A>
below.) If both character sets are the same, then the bit effectively functions
only to select the foreground color.
<P><A NAME="fonts"></A><B>Fonts</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA's text-mode hardware
provides for a very fast text mode. While this mode is not used as often
these days, it used to be the predominant mode of operation for applications.
The reason that the text mode was fast, much faster than a graphics mode
at the same resolution was that in text mode, the screen is partitioned
into characters. A single character/attribute pair is written to screen,
and the hardware uses a font table in video memory to map those character
and attribute pairs into video output, as opposed to having to write all
of the bits in a character, which could take over 16 operations to write
to screen. As CPU display memory bandwidth is somewhat limited (particularly
on on older cards), this made text mode the mode of choice for applications
which did not require graphics.
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For each character
position, bit 3 of the attribute byte selects which character set is used,
and the character byte selects which of the 256 characters in that font
are used. Up to eight sets of font bitmaps can be stored simultaneously
in display memory plane 2. The VGA's hardware provides for two banks of
256 character bitmaps to displayed simultaneously. Two fields, <A HREF="seqreg.htm#03">Character
Set A Select</A> and <A HREF="seqreg.htm#03">Character Set B Select</A>
field are used to determine which of the eight font bitmaps are currently
displayed. If bit 3 of a character's attribute byte is set to 1, then the
character set selected by <A HREF="seqreg.htm#03">Character Set A Select</A>
field, otherwise the character set specified by <A HREF="seqreg.htm#03">Character
Set B Select</A> field is used. Ordinarily, both character sets use the
same map in memory, as utilizing 2 different character sets causes character
set A to be limited to colors 0-7, and character set B to be limited to
colors 8-15.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Fonts are either 8 or 9
pixels wide and can be from 1 to 32 pixels high. The width is determined
by the <A HREF="seqreg.htm#01">9/8 Dot Mode</A> field. Characters normally
have a line of blank pixels to the right and bottom of the character to
separate the character from its neighbor. Normally this is included in
the character's bitmap, leaving only 7 bit columns for the character. Characters
such as the capital M have to be squished to fit this, and would look better
if all 8 pixels in the bitmap could be used, as in 9 Dot mode where the
characters have an extra ninth bit in width, which is displayed in the
text background color, However, this causes the line drawing characters
to be discontinuous due to the blank column. Fortunately, the <A HREF="attrreg.htm#10">Line
Graphics Enable</A> field can be set to allow character codes C0h-DFh to
have their ninth column be identical to their eighth column, providing
for continuity between line drawing characters. The height is determined
by the <A HREF="crtcreg.htm#09">Maximum Scan Line</A> field which is set
to one less than the number of scan lines in the character.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Display memory plane 2 is
divided up into eight 8K banks of characters, each of which holds 256 character
bitmaps. Each character is on a 32 byte boundary and is 32 bytes long.
The offset in plane 2 of a character within a bank is determined by taking
the character's value and multiplying it by 32. The first byte at this
offset contains the 8 pixels of the top scan line of the characters. Each
successive byte contains another scan line's worth of pixels. The best
way to read and write fonts to display memory, assuming familiarity with
the information from the <A HREF="vgamem.htm">Accessing the Display Memory</A>
page, is to use standard (not Odd/Even) addressing and Read Mode 0 and
Write Mode 0 with plane 2 selected for read or write.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The following example shows
three possible bitmap representations of text characters. In the left example
an 8x8 character box is used. In this case, the <A HREF="crtcreg.htm#09">Maximum
Scan Line</A> field is programmed to 7 and the <A HREF="seqreg.htm#01">9/8
Dot Mode</A> field is programmed to 0. Note that the bottom row and right-most
column is blank. This is used to provide inter-character spacing. The middle
example shows an 8x16 character. In this case the <A HREF="crtcreg.htm#09">Maximum
Scan Line</A> field is programmed to 15 and the <A HREF="seqreg.htm#01">9/8
Dot Mode</A> field is programmed to 0. Note that the character has extra
space at the bottom below the baseline of the character. This is used by
characters with parts descending below the baseline, such as the lowercase
letter "g". The right example shows a 9x16 character. In this case the
<A HREF="crtcreg.htm#09">Maximum Scan Line</A> field is programmed to 15
and the <A HREF="seqreg.htm#01">9/8 Dot Mode</A> field is programmed to
1. Note that the rightmost column is used by the character, as the ninth
column for 9-bit wide characters is assumed blank (excepting for the behavior
of the the <A HREF="attrreg.htm#10">Line Graphics Enable</A> field.) allowing
all eight bits of width to be used to specify the character, instead of
having to devote an entire column for inter-character spacing.
<CENTER><A HREF="char.txt"><IMG SRC="Char.gif" ALT="Click for Textified Examples of Text Mode Bitmap Characters" BORDER=0 HEIGHT=256 WIDTH=376></A></CENTER>
&nbsp;
<P>&nbsp;
<BR><A NAME="cursor"></A><B>Cursor</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The VGA has the hardware capability
to display a cursor in the text modes. Further details on the text-mode
cursor's operation can be found in the following section:
<UL>
<LI>
<A HREF="textcur.htm">Manipulating the Text-mode Cursor</A> -- details
controlling the appearance and location of the cursor.</LI>
</UL>
Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,22 @@
Virtual Screeen Mode Example
----------------------------
0 319 320 512
0 +----------------------------------------+---------------------+
| | |
| | |
| | |
| | |
| Actual Resolution (Displayed) | |
| 320x200 | |
| | |
| | |
| | |
199 +----------------------------------------+ |
200 | |
| |
| Virtual Resolution (Not Displayed) |
| 512x300 |
| |
299 +--------------------------------------------------------------+

226
specs/freevga/vtiming.htm Normal file
View File

@@ -0,0 +1,226 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Author" CONTENT="Joshua Neal">
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
<TITLE>FreeVGA - Video Timing Information</TITLE>
</HEAD>
<BODY>
<CENTER><A HREF="home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#basics">Basics</A>
<A HREF="#measure">Measurements</A> <A HREF="#horiz">Horizontal</A> <A HREF="#vert">Vertical</A>
<A HREF="#considerations">Considerations</A> <A HREF="home.htm#background">Back</A>&nbsp;
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
<CENTER>Video Timing Information&nbsp;
<HR></CENTER>
<A NAME="intro"></A><B>Introduction</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This page is written to give the
necessary background on video timing that is useful for video programming.&nbsp;
This is not a comprehensive reference on the subject, rather it just gives
the minimum information needed to know to perform mode setting and the
creation of custom video modes.&nbsp; It includes a small bit of information
about the messy side of video adapters, the electrical output and how that
is interpreted by the monitor.&nbsp; Much of this information pertains
both to monitors and other CRT devices such as television displays, and
is less applicable to LCD displays as they have different timing requirements.
<P><A NAME="basics"></A><B>Basic Description</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The video hardware produces
a continuous signal on its output connector, except when it is in reset
mode, where the video outputs are held in a single state.&nbsp; The continuous
signal is required because the pixel information is only displayed for
a short period of time, and relies on the persistence of the phosphor glow
on the monitor as well as the ability of eyesight to perform automatic
averaging to appear to be a steady image.&nbsp; That signal is usually
output on multiple pins of the monitor connector, although it could also
be a TV compatible output.&nbsp; LCD displays use a similar technique,
although the timing is more advanced and depends on the specific type of
panel and its driver circuitry.&nbsp; The signal includes both the pixel
data that the monitor displays, as well as timing and "framing" information
that the video display uses to drive its internal circuitry.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The image's pixels are "scanned"
on to the screen from left to right, top to bottom, and is broken up into
"dot periods" or pixels, which is controlled by the "dot clock" for the
mode, which is the basis for all the other video timings.&nbsp; Each horizontal
"scan line" of dot periods is called a horizontal refresh as it "refreshes"
the information on the display in a horizontal line.&nbsp; Many of these
scan lines (the amount depending on the video mode), scanning from top
to bottom, make up a vertical refresh, also known as a "frame".&nbsp; There
are many vertical refreshes per second, where a higher refresh rate produces
an image with less flicker.
<P><A NAME="measure"></A><B>Timing Measurements</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; One of the important pieces
of terminology to understand is how timing is measured.&nbsp; These include
terms such as megahertz, kilohertz, and hertz.&nbsp; The first three are
a measure of frequency which is based on the term hertz (abbreviated hz),
which can be replaced by the term "Cycles per second."&nbsp; In video timing,
hertz is used to describe the frequencies of the timing signals, such as
when saying that the vertical refresh frequency is 60 hertz (or 60hz).&nbsp;
This means that there are 60 cycles per second, which means that there
are 60 vertical refreshes per second.&nbsp; Another case where hertz is
used is when saying the horizontal refresh rate, such as when saying 31500
hz, which means that there are 31,500 horizontal refresh cycles per second.&nbsp;
One abbreviation frequently found is the term kilohertz (abbreviated Khz)
which means 1,000 cycles/per second.&nbsp; For example, 31.5 kilohertz
means 31.5 x 1000 hertz, or 31500 hz.&nbsp; This is used to save writing
a few zeros and is a bit more concise.&nbsp; Similarly the term megahertz
(abbreviated Mhz) is used, which means 1,000,000 cycles/per second.&nbsp;
For example, instead of saying that a certain mode uses a 25,000,000 hz
dot clock, or saying that it uses a 25,000 Khz clock, it can be concisely
be stated by saying that it uses a 25 Mhz dot clock.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Similarly, the periods of
time involved in video timing are very short as they are typically small
fractions of a second.&nbsp; The terms millisecond, microsecond, and nanosecond
are useful for expressing these small periods of time.&nbsp; The term millisecond
(abbreviated ms) means one thousandth of a second, or 0.001 seconds.&nbsp;
In one second, there are 1,000 milliseconds. This is used to describe things,
such as the length of time a vertical refresh takes, for example a 16.6
millisecond vertical refresh means 16.6 thousands of a second, or 0.0166
seconds.&nbsp; In one second, there are 1,000,000 microseconds.&nbsp; The
term microsecond (abbreviated us) is used to describe something in terms
of millionths of a second, or 0.000001 second.&nbsp; For example the length
of a horizontal refresh could be 31.7 microseconds, or 31.7 millionths
of a second, 0.0000317 second, or 0.0317 ms.&nbsp; The term nanosecond
(abbreviated ns) is used to describe one billionth of a second, or 0.000000001
seconds.&nbsp; There are 1,000,000,000 nanoseconds in one second.&nbsp;
One circumstance where this is used, is to describe the period of time
one dot period takes.&nbsp; For example, one dot period could be stated
as 40 nanoseconds, 0.04 us, 0.00004 ms, or 0.00000004 seconds.&nbsp; In
each case, the most concise term is used, to provide a shorter, more concise
description.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Because the unit hertz is
defined using a unit of time (second), the period of one cycle can be determined
by division.&nbsp; The simplest example is 1 hz, where the length of the
cycle, by definition would be 1 second. For other values, it can be calculated
according to the following formula:
<UL>
<LI>
Period (in seconds) = 1 / frequency (in hertz)</LI>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For example, a 60 hertz vertical
refresh would last 1 / 60 second, which is approximately 0.0166 seconds,
or 16.6 ms.&nbsp; Similarly, a 31.5 Khz horizontal refresh would be 1 /
31500 second, which is approximately 0.000031 seconds, or 31.7 us.&nbsp;
A 25 Mhz dot clock would produce a dot period of 1 / 25000000 second, which
is 0.00000004 seconds, or 40 ns.&nbsp; If the period of a cycle is known,
then the frequency can be calculated as:
<UL>
<LI>
Frequency (in hertz) = 1 / Period (in seconds).</LI>
</UL>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For example, a 16.6 ms period
would equate to 1 / 0.0166, which produces a frequency of approximately
60 hz.&nbsp; Similarly a 31.7 us period would produce approximately a 31.5
Khz frequency, and a 40 ns period would produce a 25 Mhz frequency.
<P><A NAME="horiz"></A><B>Horizontal Timing</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; From a monitor's standpoint,
the timing is fairly simple.&nbsp; It detects the horizontal sync pulses
on the hsync line, then based on the polarity, frequency, and/or duration
of those pulses sets up its horizontal scan circuitry to scan across the
screen at the desired rate.&nbsp; During this period it continuously displays
the signal input on the analog RGB pins/connectors.&nbsp; It is important
to to know the horizontal sync frequency ranges of the monitor, as well
as the acceptable width of the sync pulse for those sync ranges.&nbsp;
If the width of the sync pulse is incorrect, it can make the displayed
information too large or too small, as well as possibly preventing the
monitor from synchronizing to the generated signal.&nbsp; The acceptable
range of sync pulse width and polarity for a given frequency should be
given in the specifications for the monitor; however, this is frequently
overlooked by the manufacturer.&nbsp; It is recommended to contact the
manufacturer, otherwise the result has to be determined by trial and error
which can be damaging to the monitor's circuitry.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In addition to those that
control horizontal sync frequency and width, there are other horizontal
timing registers which tell the display generation hardware when to output
the active display, when to output the overscan, and when to perform blanking.&nbsp;
The active display is when pixel data from the frame buffer are being output
and displayed.&nbsp; This could also be overlaid by data from another source,
such as a TV or MPEG decoder, or a hardware cursor.&nbsp; The overscan
is the border to the left and right of the screen.&nbsp; This was more
important on older video hardware such as those monitors lacking horizontal
and vertical picture controls, and is provided for compatibility reasons
although current hardware typically reduces the need for this portion completely.&nbsp;
The blanking period is used during the retrace portion of the horizontal
display cycle which is the period in which the horizontal sweeps from the
right of the screen back to the left.&nbsp; Outputting non-zero intensities
during this period would end up being stretched, in reverse across the
end of the current scan line to the beginning of the next scan line which,
while interesting and possibly useful in a small number of circumstances.
would add a bit of blurring to the image.&nbsp; Blanking is signaled to
the monitor by sending zero intensities of the red, green, and blue components
on the analog lines.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; In the display generator,&nbsp;
horizontal timings are specified by the number of dot periods they take.&nbsp;
The dot period is controlled by selecting the desired dot clock frequency
by programming certain registers.
<P><A NAME="vert"></A><B>Vertical Timing</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vertical timing is nearly
the same as the horizontal timing, except that it controls the vertical
movement of the display scan, spacing the scan lines the right width apart
so that they seem to form a rectangular image.&nbsp; The monitor detects
the vertical sync pulses on the vsync line, then based on the polarity,
frequency, and/or duration of those pulses sets up its vertical circuitry
to scan down the screen at the desired rate.&nbsp; It is necessary to know
the vertical sync frequency ranges for a given monitor, and the range of
acceptable vertical sync widths and polarities for those ranges.&nbsp;
The rage of vertical sync frequencies supported by the monitor are nearly
always given my the monitor's specifications, but like the horizontal sync
widths, the vertical sync widths are not commonly specified.&nbsp; Contact
the manufacturer, as attempting to guess the correct vertical sync width
can possibly cause the monitor to fail.
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; As well as being programmed
with the vertical sync frequency and pulse width, the display generation
hardware has other registers which control when to output the active display,
when to output the overscan, and when to perform blanking. In vertical
terms, the active display is the scan lines which contain horizontal active
display periods.&nbsp; The overscan is the border on top and bottom of
the screen and, if present, consists of one or more entire scan lines in
which the active display period is replaced with the overscan color.&nbsp;
The blanking is used during the vertical retrace, and consists of one or
more (usually more) scan lines in which the active display and overscan
periods are replaced with blanking period, making the entire line effectively
blanking.&nbsp; This prevents intensity from overlaying the screen during
the vertical retrace where the monitor sweeps the vertical back to the
top of the screen.&nbsp; Non-zero intensities output during this period
would be written in a zig-zag pattern from the bottom to the top of the
screen.&nbsp; In the display generator, the vertical timings are specified
in terms of how many horizontal sync periods they take.
<BR>&nbsp;
<BR><A NAME="considerations"></A><B>Programming Considerations</B>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For maximum flexibility,
video timings should be configurable by the end users to allow for the
specifications of their monitor.&nbsp; However, it is probably a wise idea
to maintain a table of monitors and their rated specifications, to allow
the users to select thieir monitor and determine whether or not the configured
video timings are within the rated specifications of their monitor and
warn the user about this.&nbsp; There is a distinct need for a comprehensive
and accurate software-usable database of monitor specifications in a platform
and video hardware independent form with sufficient information for a program
to both select timings for a particular video mode, as well as verify that
a given set of timings will function properly on the end-user's hardware.&nbsp;
This database should contain a human readable description of the monitor
make and model, as well as software parsable fields giving corresponding
ranges of horizontal and vertical frequencies and sync polarities for those
ranges if applicable, as well as a method of determining the acceptable
widths of horizontal and vertical sync pulses for a given frequency in
the corresponding rages.&nbsp; Framing information could be included in
this table in a frequency independent fashion, although this is something
that can be safely adjusted by the end user without risk of damage to the
monitor, thus it is preferrable to provide a method or interface for the
end-user to adjust these parameters to their preference.
<BR>&nbsp;
<P>Notice: All trademarks used or referred to on this page are the property
of their respective owners.
<BR>All pages are Copyright &copy; 1997, 1998, J. D. Neal, except where
noted. Permission for utilization and distribution is subject to the terms
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
<BR>&nbsp;
<BR>&nbsp;
</BODY>
</HTML>

View File

@@ -0,0 +1,88 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>ABNT keypad</TITLE>
</HEAD>
<BODY>
<CENTER><H2>ABNT keyboard keypad layout</H2></CENTER>
<CENTER>Key label and scancode (hex) and Linux keycode (decimal)
for a Brazilian ABNT keyboard keypad.</CENTER>
<p>
<TABLE BORDER=1 ALIGN="CENTER"
<TR>
<TD ALIGN="Center" WIDTH=40>Num<br>Lock</TD>
<TD ALIGN="Center" WIDTH=40> / </TD>
<TD ALIGN="Center" WIDTH=40> * </TD>
<TD ALIGN="Center" WIDTH=40> - </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> <B>45</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>e0 45</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>37</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>4a</B> </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> 69 </TD>
<TD ALIGN="Center" WIDTH=40> 98 </TD>
<TD ALIGN="Center" WIDTH=40> 55 </TD>
<TD ALIGN="Center" WIDTH=40> 74 </TD>
</TR>
<TR>
<TD ALIGN="Center" WIDTH=40> 7<br>Home </TD>
<TD ALIGN="Center" WIDTH=40> 8<br>Up </TD>
<TD ALIGN="Center" WIDTH=40> 9<br>PgUp </TD>
<TD ALIGN="Center" WIDTH=40> + </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> <B>47</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>48</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>49</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>4e</B> </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> 71 </TD>
<TD ALIGN="Center" WIDTH=40> 72 </TD>
<TD ALIGN="Center" WIDTH=40> 73 </TD>
<TD ALIGN="Center" WIDTH=40> 78 </TD>
</TR>
<TR>
<TD ALIGN="Center" WIDTH=40> 4<br>Left </TD>
<TD ALIGN="Center" WIDTH=40> 5 </TD>
<TD ALIGN="Center" WIDTH=40> 6<br>Right </TD>
<TD ALIGN="Center" WIDTH=40> . </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> <B>4b</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>4c</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>4d</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>7e</B> </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> 75 </TD>
<TD ALIGN="Center" WIDTH=40> 76 </TD>
<TD ALIGN="Center" WIDTH=40> 77 </TD>
<TD ALIGN="Center" WIDTH=40> 121 </TD>
</TR>
<TR>
<TD ALIGN="Center" WIDTH=40> 1<br>End </TD>
<TD ALIGN="Center" WIDTH=40> 2<br>Down </TD>
<TD ALIGN="Center" WIDTH=40> 3<br>PgDn </TD>
<TD ALIGN="Center" WIDTH=40 ROWSPAN=2> Enter </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> <B>4f</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>50</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>51</B> </TD>
<TD ALIGN="Center" WIDTH=40 ROWSPAN=2> <B>e0 1c</B> </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" WIDTH=40> 79 </TD>
<TD ALIGN="Center" WIDTH=40> 80 </TD>
<TD ALIGN="Center" WIDTH=40> 81 </TD>
<TD ALIGN="Center" WIDTH=40 ROWSPAN=2> 96 </TD>
</TR>
<TR>
<TD ALIGN="Center" COLSPAN=2> 0<br>Ins </TD>
<TD ALIGN="Center" WIDTH=40> ,<br>Del </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" COLSPAN=2> <B>52</B> </TD>
<TD ALIGN="Center" WIDTH=40> <B>53</B> </TD>
<TD ALIGN="Center" WIDTH=60> </TD>
<TD ALIGN="Center" COLSPAN=2> 82 </TD>
<TD ALIGN="Center" WIDTH=40> 83 </TD>
</TR>
</TABLE>
</BODY>
</HTML>

BIN
specs/kbd/amstrad-s.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
specs/kbd/amstrad.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
specs/kbd/compaq_unkn-s.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
specs/kbd/compaq_unkn.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
specs/kbd/imb5576-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
specs/kbd/jp106.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

BIN
specs/kbd/jplaptop.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
specs/kbd/lk201-k.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
specs/kbd/lk411-left.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
specs/kbd/lk411-right.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

BIN
specs/kbd/lk411-s.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
specs/kbd/lk411.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
specs/kbd/m24.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
specs/kbd/m24kbd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
specs/kbd/ms_office.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
specs/kbd/ncr-s.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Some files were not shown because too many files have changed in this diff Show More