provided code
26
.gitignore
vendored
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
96
doc/localgitinstructions.texi
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
104
doc/sample.tmpl
Normal 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
@@ -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
@@ -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
@@ -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
6976
doc/texinfo.tex
Normal file
501
doc/threads.texi
Normal 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
@@ -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
116
doc/userprog.tmpl
Normal 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
@@ -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
@@ -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?
|
||||
59
specs/freevga/feedback.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Feedback Form
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
255
specs/freevga/freevga.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>About the FreeVGA Project
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
|
||||
<P><A NAME="intro"></A><B>Introduction</B>
|
||||
<BR> 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> 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> 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> </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> 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> 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> 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>
|
||||
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>
|
||||
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> </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> </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>
|
||||
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> </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 © 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>. <IMG SRC="http://www.goodnet.com/~tinara/cgi-bin/imgserv.cgi?logo2.gif" >
|
||||
</BODY>
|
||||
</HTML>
|
||||
100
specs/freevga/glossary.htm
Normal 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
|
||||
<HR></CENTER>
|
||||
<B>Introduction</B>
|
||||
<BR> This page is a glossary
|
||||
covering video programming related terms. 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>
|
||||
<BR>
|
||||
<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. This is used in video chipsets to produce the analog
|
||||
signals that are sent to the monitor. 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. 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 & 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. 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>
|
||||
<BR>
|
||||
|
||||
<P>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
92
specs/freevga/hardovr.htm
Normal 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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>Overview of Video Hardware Functionality
|
||||
<HR></CENTER>
|
||||
<A NAME="intro"></A><B>Introduction</B>
|
||||
<BR> 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. This is
|
||||
intended to be a general description for those unfamiliar to the functionality
|
||||
and capabilities of graphics hardware. 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> This is the component of
|
||||
the video hardware that stores the pixels and information to be displayed
|
||||
on the monitor. This is the center of the video hardware, as nearly
|
||||
all operations are performed on or using this data. 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.
|
||||
The amount of video memory that is present determines the maximum resolution
|
||||
that the hardware can generate. 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. 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. 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> This is the video chipset's
|
||||
host interface to the frame buffer, and is part of the main graphics chip
|
||||
or chips. It allows the host CPU to manipulate the frame buffer in
|
||||
a fashion suited to the task of graphics operations. 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. 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> 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.
|
||||
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.
|
||||
The CRT controller at the same time adds timing signals that allow the
|
||||
monitor to display the analog color information on the display. For
|
||||
example, in the VGA these components are made up of the sequencer, attribute
|
||||
controller, CRT controller, DAC, and palette table. 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. This
|
||||
color information is formatted by the attribute controller in such a way
|
||||
that the pixel values can be submitted to the DAC. 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. 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 © 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>
|
||||
</BODY>
|
||||
</HTML>
|
||||
127
specs/freevga/hardrec.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Product Recommendations for Video Developers
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
<A NAME="intro"></A><B>Introduction</B>
|
||||
<BR> This page is to provide
|
||||
hardware recommendations for those implementing the information on this
|
||||
site. 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.
|
||||
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> <A NAME="monitors"></A>Monitors Recommended</B>
|
||||
<BR> 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. It should
|
||||
also be tolerant to extremely frequent mode changes. Damage due to
|
||||
this kind of operation should not be excluded by the standard manufacturer's
|
||||
warranty. 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. 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> 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. This does not imply that the programmer was at fault, as
|
||||
these things naturally happen when developing drivers. 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.
|
||||
It was a fixed frequency model, and the horizontal circuitry was damaged.
|
||||
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. 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. The
|
||||
monitor synced to the frequency, but may have been slightly overdriven.
|
||||
The horizontal output transistor and some capacitors were replaced and
|
||||
the monitor was restored to working order. 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.
|
||||
The explosion from the capacitors shattered the rear of the picture tube,
|
||||
damaging the monitor beyond repair. Not recommended due to the catastrophic
|
||||
nature of the failure. The operation being performed when the failure
|
||||
occurred was frequent mode changing.
|
||||
|
||||
<P><A NAME="test"></A><B>Test Equipment Recommended</B>
|
||||
<BR> There are certain pieces
|
||||
of test equipment that can come in handy when working with video cards.
|
||||
This can be especially important when verifying that the video signal being
|
||||
generated is, in fact the one intended by the programmer. 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. 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 © 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>. <IMG SRC="http://www.goodnet.com/~tinara/cgi-bin/imgserv.cgi?logo3.gif" >
|
||||
</BODY>
|
||||
</HTML>
|
||||
486
specs/freevga/home.htm
Normal 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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>Home
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
<CENTER> </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> </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. <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> 08/01/1998</B> -- More
|
||||
information is now up, including a large portion of the "standard" VGA
|
||||
reference. Some other minor changes have been made to other information.
|
||||
Expect more updates in the not too far future.
|
||||
|
||||
<P> <B>06/20/1998</B> -- The
|
||||
work contiues. Added three new mirrors. 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. 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. Thank you!
|
||||
|
||||
<P><B> 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. Also, the first section of *real* information is
|
||||
online, the low-level programming introduction. This section has
|
||||
been relatively stable for quite some time, and seems to be releasable.
|
||||
It is my goal to release the information after it stabilizes, and has been
|
||||
verified for accuracy.
|
||||
|
||||
<P><B> 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>.
|
||||
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. 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> At this time, the project
|
||||
is experimenting with the feasibility of maintaining mirror sites to make
|
||||
this information more widely available. The following mirror sites
|
||||
are provided for your convenience. 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> 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> 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> </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> 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> </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> 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> </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øgersen's <A HREF="http://www.datashopper.dk/~finth/">VGADOC
|
||||
& 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. 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. 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 & Hoffman's PC Underground: Unconventional Programming
|
||||
Topics -- I bought this book on markdown, due to it having some VGA information
|
||||
in it. 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.
|
||||
Particularly helpful is the section on intellectual property protection
|
||||
for fonts, as the copyright legality of fonts and typefaces is somewhat
|
||||
confusing. 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> 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.
|
||||
However, there are other products that can be extremely helpful when implementing
|
||||
the information found here, such as monitors, test equipment, and software.
|
||||
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.
|
||||
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. If the monitor
|
||||
makes unusual noises, or the internal temperature exceeds the rated temperature
|
||||
of its components, the monitor is likely to experience failure. This
|
||||
failure may not be immediate, but is under most circumstances inevitable. <B>
|
||||
<U>Monitor failures can be violent in nature, and can explode and produce
|
||||
shrapnel, as well as overheat and catch fire</U>. </B>In no circumstance
|
||||
should one leave a monitor unattended in an uncertain state. 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. The rated frequencies are rated and verified according
|
||||
to batch yield. As clock frequencies increase, the failure rate of
|
||||
the chips during manufacturing testing increases. 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. <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> If they
|
||||
occur, the entire semiconductor must be rejected due to these failures
|
||||
being irrepairable. 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. Attempting to
|
||||
find the maximum frequency is impossible, as by the time a failure is noticable
|
||||
the semiconductor has already been permanently damaged. 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.
|
||||
Semiconductors such as fast CPU's are rated with the required heat sink
|
||||
and/or cooling fan in place. 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. <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>
|
||||
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. 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> I can be reached online
|
||||
via the <A HREF="feedback.htm">Feedback Form</A>. 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>
|
||||
|
||||
<P>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>. <IMG SRC="http://www.goodnet.com/~tinara/cgi-bin/imgserv.cgi?logo.gif" >
|
||||
</BODY>
|
||||
</HTML>
|
||||
124
specs/freevga/license.htm
Normal 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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>FreeVGA Project Copyright License
|
||||
<HR></CENTER>
|
||||
<B>Introduction</B>
|
||||
<BR> This document contains the
|
||||
FreeVGA Copyright License which states the conditions under which the FreeVGA
|
||||
Project's Copyrighted information may be used and distributed. 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> 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. License
|
||||
to use this information is only granted where this disclaimer applies in
|
||||
whole.
|
||||
|
||||
<P><B>License</B>
|
||||
<BR> 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. 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. 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. 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.
|
||||
The FreeVGA Project documentation must be excluded from any compilation
|
||||
copyright or other restrictions. No fee other than the cost of transmission
|
||||
or the physical media containing the archive may be charged without prior
|
||||
approval by the author. 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. 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. The URL of the
|
||||
FreeVGA project online documentation must be provided. 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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
246
specs/freevga/llintro.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Introduction to Low-level Programming
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
|
||||
<P><A NAME="intro"></A><B>Introduction</B>
|
||||
<BR> 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> </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> 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> 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> 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> 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> 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> 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> 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> 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> </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> 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>
|
||||
|
||||
<P><A NAME="memory"></A><B>How do memory and I/O ports work?</B>
|
||||
<BR> 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> 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> 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> 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> 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 © 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>
|
||||
BIN
specs/freevga/vga/256left.gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
20
specs/freevga/vga/256left.txt
Normal 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
|
||||
BIN
specs/freevga/vga/256right.gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
18
specs/freevga/vga/256right.txt
Normal 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
|
||||
360
specs/freevga/vga/attrreg.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Attribute Controller Registers
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
|
||||
<P> 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>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<UL>
|
||||
<LI>
|
||||
<B>Color Plane Enable<BR>
|
||||
</B>"<I>Setting a bit to 1, enables the corresponding display-memory color
|
||||
plane.</I>"</LI>
|
||||
</UL>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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 8-bit digital color value
|
||||
to the video DAC. Selecting these bits is done in the Attribute Mode Control
|
||||
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 © 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>
|
||||
22
specs/freevga/vga/char.txt
Normal 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????????
|
||||
253
specs/freevga/vga/colorreg.htm
Normal 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>
|
||||
<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>
|
||||
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.
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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 © 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>
|
||||
1355
specs/freevga/vga/crtcreg.htm
Normal file
282
specs/freevga/vga/extreg.htm
Normal 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>
|
||||
<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>
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
<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> = 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> = 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> = 0 selects the low page</I>
|
||||
<BR><I> = 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. The standard hardware has 2 clocks available
|
||||
to it, nominally 25 Mhz and 28 Mhz. It is possible that there may
|
||||
be other "external" clocks that can be selected by programming this register
|
||||
with the undefined values. 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> = 0 disables address decode for the display buffer from the
|
||||
system</I>
|
||||
<BR><I> = 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. 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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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 © 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>
|
||||
585
specs/freevga/vga/graphreg.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Graphics Registers
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
|
||||
<P> 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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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. 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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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 © 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>
|
||||
124
specs/freevga/vga/license.htm
Normal 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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>FreeVGA Project Copyright License
|
||||
<HR></CENTER>
|
||||
<B>Introduction</B>
|
||||
<BR> This document contains the
|
||||
FreeVGA Copyright License which states the conditions under which the FreeVGA
|
||||
Project's Copyrighted information may be used and distributed. 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> 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. License
|
||||
to use this information is only granted where this disclaimer applies in
|
||||
whole.
|
||||
|
||||
<P><B>License</B>
|
||||
<BR> 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. 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. 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. 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.
|
||||
The FreeVGA Project documentation must be excluded from any compilation
|
||||
copyright or other restrictions. No fee other than the cost of transmission
|
||||
or the physical media containing the archive may be charged without prior
|
||||
approval by the author. 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. 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. The URL of the
|
||||
FreeVGA project online documentation must be provided. 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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
specs/freevga/vga/paging.gif
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
29
specs/freevga/vga/paging.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
Paging Memory Utilization Example
|
||||
---------------------------------
|
||||
|
||||
0 +-------------------------+ 79
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| PAGE 0 |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
1920 | | 1999
|
||||
+-------------------------+
|
||||
| 48 bytes unused |
|
||||
+-------------------------+
|
||||
2048 | | 2127
|
||||
| |
|
||||
| |
|
||||
| PAGE 1 |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
3968 | | 4047
|
||||
+-------------------------+
|
||||
| |
|
||||
+-------------------------+
|
||||
| |
|
||||
|_ __ __ __ _ _|
|
||||
-- --_- - --___-- --
|
||||
99
specs/freevga/vga/portidx.htm
Normal 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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>VGA I/O Port Index
|
||||
<HR></CENTER>
|
||||
Introduction
|
||||
<BR> This index lists the VGA's
|
||||
I/O ports in numerical order, making looking up a specific I/O port access
|
||||
simpler.
|
||||
<BR>
|
||||
<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 © 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>
|
||||
<BR>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
specs/freevga/vga/seqpack.gif
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
25
specs/freevga/vga/seqpack.txt
Normal 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
|
||||
|
||||
BIN
specs/freevga/vga/seqplanr.gif
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
31
specs/freevga/vga/seqplanr.txt
Normal 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
|
||||
|
||||
381
specs/freevga/vga/seqreg.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Sequencer Registers
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
|
||||
<P> 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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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> A0 A1
|
||||
Map Selected</I>
|
||||
<BR><I> 0 0
|
||||
0</I>
|
||||
<BR><I> 0 1
|
||||
1</I>
|
||||
<BR><I> 1 0
|
||||
2</I>
|
||||
<BR><I> 1 1
|
||||
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 © 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>
|
||||
137
specs/freevga/vga/textcur.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Manipulating the Text-mode Cursor
|
||||
<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> </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> 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> </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> 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> </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> 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> 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>
|
||||
|
||||
<P>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>
|
||||
</BODY>
|
||||
</HTML>
|
||||
226
specs/freevga/vga/vga.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>VGA Chipset Reference
|
||||
<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> 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> 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> 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> 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> </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> 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> 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> 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>
|
||||
<A HREF="vgareg.htm">Accessing the VGA Registers</A> -- methods of
|
||||
manipulating the VGA registers</LI>
|
||||
</UL>
|
||||
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>"
|
||||
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.
|
||||
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> 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 © 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>
|
||||
</BODY>
|
||||
</HTML>
|
||||
210
specs/freevga/vga/vgacrtc.htm
Normal 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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>VGA Display Generation
|
||||
<HR></CENTER>
|
||||
<A NAME="intro"></A><B>Introduction</B>
|
||||
<BR> 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> The standard VGA has two
|
||||
"standard" dot clock frequencies available to it, as well as a possible
|
||||
"external" clock source, which is implementation dependent. The two
|
||||
standard clock frequencies are nominally 25 Mhz and 28 MHz. Some
|
||||
chipsets use 25.000 MHz and 28.000 MHz, while others use slightly greater
|
||||
clock frequencies. The IBM VGA chipset I have uses 25.1750 MHz
|
||||
Mhz and 28.3220 crystals. Some newer cards use the closest generated
|
||||
frequency produced by their clock chip. 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> The dot clock source in
|
||||
the VGA hardware is selected using the <A HREF="extreg.htm#3CCR3C2W">Clock
|
||||
Select</A> field. 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. 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> 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. 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> The start of the active
|
||||
display period coincides with the resetting of the horizontal character
|
||||
counter, thus is fixed at zero. 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> The end of the active display
|
||||
period is controlled by the <A HREF="crtcreg.htm#01">End Horizontal Display</A>
|
||||
field. 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. This continues
|
||||
until the active display begins at the beginning of the next scan line
|
||||
when the active display begins again. Note that the horizontal blanking
|
||||
takes precedence over the sequencer and attribute controller.
|
||||
<BR> The horizontal blanking
|
||||
period begins when the character clock equals the value of the <A HREF="crtcreg.htm#02">Start
|
||||
Horizontal Blanking</A> field. During the horizontal blanking period,
|
||||
the output voltages of the DAC signal the monitor to turn off the guns.
|
||||
Under normal conditions, this prevents the overscan color from being displayed
|
||||
during the horizontal retrace period. 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.
|
||||
This allows for a blanking period from 1 to 64 character clocks, although
|
||||
some implementations may treat 64 as 0 character clocks in length.
|
||||
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. It takes precedence over all other VGA output. There
|
||||
is also no requirement that blanking occur at all. 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. 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> 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. 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. 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> 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. 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. 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.
|
||||
It seems to be totally safe to set these fields to 0 and ignore them.
|
||||
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> The VGA maintains a scanline
|
||||
counter which is used to measure vertical timing periods. This counter
|
||||
begins at zero which coincides with the first scan line of the active display.
|
||||
This counter is set to zero before the beginning of the first scanline
|
||||
of the active display. 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. 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. The maximum
|
||||
value of the scanline counter is specified by the <A HREF="crtcreg.htm#06">Vertical
|
||||
Total</A> field. 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>. 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> 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. 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.
|
||||
This continues until the start of the next frame when the active display
|
||||
begins again.
|
||||
<BR> 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. 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. 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> 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. 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. 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> 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. 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> The <A HREF="extreg.htm#3xAR">Vertical
|
||||
Retrace</A> field signals whether or not the VGA is in a vertical retrace
|
||||
period. 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. 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> There are a few registers
|
||||
that affect display generation, but don't fit neatly into the horizontal
|
||||
or vertical timing categories. 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. 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. 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> 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. This
|
||||
field controls whether the VGA hardware provides 3 or 5 memory refresh
|
||||
cycles per scanline. At or above VGA horizontal refresh rates, this
|
||||
field should be programmed for 3 memory refresh cycles per scanline.
|
||||
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>
|
||||
<BR>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>
|
||||
190
specs/freevga/vga/vgadac.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>DAC Operation
|
||||
<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> 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> 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> 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> 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> 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> 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> 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>
|
||||
|
||||
<P>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>
|
||||
</BODY>
|
||||
</HTML>
|
||||
402
specs/freevga/vga/vgafunc.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>VGA Functional Index
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
|
||||
<P><A NAME="register"></A><B>Register Access Functions</B>
|
||||
<BR> 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> 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> 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> 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> 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> 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> 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> 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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
295
specs/freevga/vga/vgafx.htm
Normal 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
|
||||
<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> 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> 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> 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> 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> 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> 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> <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> <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> 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> 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> 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> 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> 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>
|
||||
<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> 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> 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> 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> 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> 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>
|
||||
|
||||
<P>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>
|
||||
334
specs/freevga/vga/vgamem.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Accessing the VGA Display Memory
|
||||
<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> 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> </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> 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> 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><More to be added here.></B>
|
||||
|
||||
<P><A NAME="manip"></A><B>Manipulating Display Memory</B>
|
||||
<BR> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> </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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
508
specs/freevga/vga/vgareg.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>Accessing the VGA Registers
|
||||
<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> 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> </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> 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> 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> 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> 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>
|
||||
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> 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>
|
||||
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> 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> 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> </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>
|
||||
<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> 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>
|
||||
<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> 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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
385
specs/freevga/vga/vgargidx.htm
Normal 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> <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 <A HREF="vga.htm#index">Back</A>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>VGA Field Index
|
||||
<HR WIDTH="100%"></CENTER>
|
||||
|
||||
<CENTER><A HREF="#A">A</A> | <A HREF="#B">B</A> | <A HREF="#C">C</A> |
|
||||
<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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
206
specs/freevga/vga/vgaseq.htm
Normal 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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>VGA Sequencer Operation
|
||||
<HR></CENTER>
|
||||
<B>Introduction</B>
|
||||
<BR> The sequencer portion of
|
||||
the VGA hardware reads the display memory and converts it into data that
|
||||
is sent to the attribute controller. 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. For this reason, the sequencer has quite a few different
|
||||
modes of operation. Further complicating programming, the sequencer
|
||||
has been poorly documented, resulting in many variances between various
|
||||
VGA/SVGA implementations.
|
||||
<BR>
|
||||
<BR><B>Sequencer Memory Addressing</B>
|
||||
<BR> The sequencer operates by
|
||||
loading a display address into memory, then shifting it out pixel by pixel.
|
||||
The memory is organized internally as 64K addresses, 32 bits wide.
|
||||
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.
|
||||
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><More to be added here>
|
||||
<BR>
|
||||
<BR><B>Graphics Shifting Modes</B>
|
||||
<BR> 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> 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. The first method is the
|
||||
one used for the VGA's 16 color modes. 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. 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. 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>
|
||||
<BR>
|
||||
<CENTER><A HREF="seqplanr.txt"><IMG SRC="seqplanr.gif" ALT="Click here for Textified Planar Shift Mode Diagram" HEIGHT=256 WIDTH=376></A></CENTER>
|
||||
|
||||
|
||||
<P> 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. 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. The bits for the first four pixels shifted out
|
||||
for a given address are stored in planes 0 and 2. The second four
|
||||
are stored in planes 1 and 3. 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. 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>
|
||||
<BR>
|
||||
<CENTER><A HREF="seqpack.txt"><IMG SRC="seqpack.gif" ALT="Click for Textified Packed Shift Mode Diagram" HEIGHT=256 WIDTH=376></A></CENTER>
|
||||
|
||||
|
||||
<P> 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.)
|
||||
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. Thus certain
|
||||
variances in the sequencing operations can be masked by similar variances
|
||||
in the attribute controller. 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. 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. I do, however, feel
|
||||
that attempting to specify each field's function as accurately possible
|
||||
can allow more powerful utilization of the hardware.
|
||||
<BR> When this shift mode is
|
||||
enabled, the VGA hardware shifts 4 bit pixel values out of the 32-bit memory
|
||||
location each dot clock. 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. 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. In 256-color mode, each plane holds a 8-bit
|
||||
value which is intended to be the DAC palette index for that pixel.
|
||||
Every second 8-bit index generated should correspond to the values in planes
|
||||
0-3, appearing left to right on the display. This is masked by the
|
||||
attribute controller, which in 256 color mode latches every second 8-bit
|
||||
value as well. This means that the intermediate 8-bit values are
|
||||
not normally seen, and is where implementations can vary. Another
|
||||
variance is whether the even or odd pixel values generated are the intended
|
||||
data bytes. This also is masked by the attribute controller, which
|
||||
latches the appropriate even or odd pixel values.
|
||||
<BR> The first case is where
|
||||
the 8-bit values are formed by shifting the 4 8-bit planes left.
|
||||
This is shown in the diagram below. 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. 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. Each pixel value is fed to the attribute controller,
|
||||
where a lookup operation is performed using the attribute table.
|
||||
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.
|
||||
Note how one 4-bit result carries over into the next display memory location
|
||||
sequenced.
|
||||
<BR> 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. Thus,
|
||||
the new DAC index output for this pixel is E0h. The next pixel is
|
||||
1h, which produces 1h at the other end of the attribute controller.
|
||||
The previous DAC index, E0h is shifted again producing 01h. This
|
||||
process continues, producing the DAC indexes, in order, 12h, 23h, 34h,
|
||||
45h, 56h, and 67h. 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>
|
||||
<BR>
|
||||
<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>
|
||||
|
||||
|
||||
<P> The second case is where the 8-bit
|
||||
values are formed by shifting the 8-bit values right, as depicted in the
|
||||
diagram below. The first pixel value generated is the lower four
|
||||
bits of plane 0, followed by the upper four bits. This continues
|
||||
for planes 1-3 until the last pixel value produced, which is the upper
|
||||
four bits of Plane 3. These pixel values are fed to the attribute
|
||||
controller, where the corresponding entry in the attribute table is looked
|
||||
up. 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> 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. Thus, the new DAC
|
||||
index output for this pixel is 1Fh. The next pixel is 0h, which produces
|
||||
0h at the other end of the attribute controller. The previous DAC
|
||||
index, 1Fh is shifted again producing 01h. This process continues,
|
||||
producing the DAC indexes, in order, 30h, 23h, 52h, 45h, 74h, and 67h.
|
||||
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>
|
||||
<BR>
|
||||
<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>
|
||||
|
||||
<BR>
|
||||
<BR> 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. 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. 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. Likely this
|
||||
value will be either 00h or whatever the contents were at the end of the
|
||||
previous scan line. A similar circumstance arises where the last
|
||||
pixel value generated falls on a boundary between memory addresses.
|
||||
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>
|
||||
|
||||
<P>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>
|
||||
<BR>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
185
specs/freevga/vga/vgatext.htm
Normal 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>
|
||||
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
||||
Page</B></CENTER>
|
||||
|
||||
<CENTER>VGA Text Mode Operation
|
||||
<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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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>
|
||||
|
||||
|
||||
<P>
|
||||
<BR><A NAME="cursor"></A><B>Cursor</B>
|
||||
<BR> 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 © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
specs/freevga/vga/virtual.gif
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
22
specs/freevga/vga/virtual.txt
Normal 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
@@ -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>
|
||||
<HR><B>Hardware Level VGA and SVGA Video Programming Information Page</B></CENTER>
|
||||
|
||||
<CENTER>Video Timing Information
|
||||
<HR></CENTER>
|
||||
<A NAME="intro"></A><B>Introduction</B>
|
||||
<BR> This page is written to give the
|
||||
necessary background on video timing that is useful for video programming.
|
||||
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. 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. 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> 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. 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. That signal is usually
|
||||
output on multiple pins of the monitor connector, although it could also
|
||||
be a TV compatible output. LCD displays use a similar technique,
|
||||
although the timing is more advanced and depends on the specific type of
|
||||
panel and its driver circuitry. 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> 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. Each horizontal
|
||||
"scan line" of dot periods is called a horizontal refresh as it "refreshes"
|
||||
the information on the display in a horizontal line. 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". 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> One of the important pieces
|
||||
of terminology to understand is how timing is measured. These include
|
||||
terms such as megahertz, kilohertz, and hertz. 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." 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).
|
||||
This means that there are 60 cycles per second, which means that there
|
||||
are 60 vertical refreshes per second. 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.
|
||||
One abbreviation frequently found is the term kilohertz (abbreviated Khz)
|
||||
which means 1,000 cycles/per second. For example, 31.5 kilohertz
|
||||
means 31.5 x 1000 hertz, or 31500 hz. This is used to save writing
|
||||
a few zeros and is a bit more concise. Similarly the term megahertz
|
||||
(abbreviated Mhz) is used, which means 1,000,000 cycles/per second.
|
||||
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> Similarly, the periods of
|
||||
time involved in video timing are very short as they are typically small
|
||||
fractions of a second. The terms millisecond, microsecond, and nanosecond
|
||||
are useful for expressing these small periods of time. The term millisecond
|
||||
(abbreviated ms) means one thousandth of a second, or 0.001 seconds.
|
||||
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. In one second, there are 1,000,000 microseconds. The
|
||||
term microsecond (abbreviated us) is used to describe something in terms
|
||||
of millionths of a second, or 0.000001 second. 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. The term nanosecond
|
||||
(abbreviated ns) is used to describe one billionth of a second, or 0.000000001
|
||||
seconds. There are 1,000,000,000 nanoseconds in one second.
|
||||
One circumstance where this is used, is to describe the period of time
|
||||
one dot period takes. For example, one dot period could be stated
|
||||
as 40 nanoseconds, 0.04 us, 0.00004 ms, or 0.00000004 seconds. In
|
||||
each case, the most concise term is used, to provide a shorter, more concise
|
||||
description.
|
||||
<BR> Because the unit hertz is
|
||||
defined using a unit of time (second), the period of one cycle can be determined
|
||||
by division. 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>
|
||||
For example, a 60 hertz vertical
|
||||
refresh would last 1 / 60 second, which is approximately 0.0166 seconds,
|
||||
or 16.6 ms. Similarly, a 31.5 Khz horizontal refresh would be 1 /
|
||||
31500 second, which is approximately 0.000031 seconds, or 31.7 us.
|
||||
A 25 Mhz dot clock would produce a dot period of 1 / 25000000 second, which
|
||||
is 0.00000004 seconds, or 40 ns. 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>
|
||||
For example, a 16.6 ms period
|
||||
would equate to 1 / 0.0166, which produces a frequency of approximately
|
||||
60 hz. 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> From a monitor's standpoint,
|
||||
the timing is fairly simple. 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. During this period it continuously displays
|
||||
the signal input on the analog RGB pins/connectors. 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.
|
||||
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. 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. 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> 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.
|
||||
The active display is when pixel data from the frame buffer are being output
|
||||
and displayed. This could also be overlaid by data from another source,
|
||||
such as a TV or MPEG decoder, or a hardware cursor. The overscan
|
||||
is the border to the left and right of the screen. 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.
|
||||
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. 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. Blanking is signaled to
|
||||
the monitor by sending zero intensities of the red, green, and blue components
|
||||
on the analog lines.
|
||||
<BR> In the display generator,
|
||||
horizontal timings are specified by the number of dot periods they take.
|
||||
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> 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. 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. 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.
|
||||
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. Contact
|
||||
the manufacturer, as attempting to guess the correct vertical sync width
|
||||
can possibly cause the monitor to fail.
|
||||
<BR> 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. 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.
|
||||
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. This prevents intensity from overlaying the screen during
|
||||
the vertical retrace where the monitor sweeps the vertical back to the
|
||||
top of the screen. Non-zero intensities output during this period
|
||||
would be written in a zig-zag pattern from the bottom to the top of the
|
||||
screen. In the display generator, the vertical timings are specified
|
||||
in terms of how many horizontal sync periods they take.
|
||||
<BR>
|
||||
<BR><A NAME="considerations"></A><B>Programming Considerations</B>
|
||||
<BR> For maximum flexibility,
|
||||
video timings should be configurable by the end users to allow for the
|
||||
specifications of their monitor. 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. 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.
|
||||
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. 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>
|
||||
|
||||
<P>Notice: All trademarks used or referred to on this page are the property
|
||||
of their respective owners.
|
||||
<BR>All pages are Copyright © 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>
|
||||
<BR>
|
||||
</BODY>
|
||||
</HTML>
|
||||
88
specs/kbd/abnt-keypad.html
Normal 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
|
After Width: | Height: | Size: 17 KiB |
BIN
specs/kbd/amstrad.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
specs/kbd/compaq_easy_access.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
specs/kbd/compaq_unkn-s.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
specs/kbd/compaq_unkn.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
specs/kbd/ibm_rapid_access.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
specs/kbd/ibm_rapid_access_II.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
specs/kbd/imb5576-2.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
specs/kbd/jp106-with-scancodes.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
specs/kbd/jp106.jpg
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
specs/kbd/jplaptop.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
specs/kbd/lk201-k.gif
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
specs/kbd/lk411-left.jpg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
specs/kbd/lk411-right.jpg
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
specs/kbd/lk411-s.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
specs/kbd/lk411.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
specs/kbd/logitech-access.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
specs/kbd/logitech-internet-s.jpg
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
specs/kbd/logitech-internet.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
specs/kbd/m24.jpg
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
specs/kbd/m24kbd.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
specs/kbd/ms_office.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
specs/kbd/ncr-s.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |