Our Google group is set up, based on .forward email
addresses
Thus
after boot-up, the SAPC’s x86 CPU is running in 32-bit protected mode and in
kernel mode. 32-bit protected mode means that we can use 32-bit addresses,
addressing up to 4G locations. 16-bit mode would only allow 64K different
addresses in one sequence, a terrible handicap for today’s programs. Even
our measly 3M user memory would constitute 0x30 = 48 different sequences of 64K
(or 0x10000). In 32-bit mode, an address of 0x300000 (3M) is just an
ordinary address, in fact seen to be on the small side if you write all 32 bits
out like this: 0x00300000.
Warning:
many texts on Pentium architecture treat only the real mode architecture.
To tell, look at the register names in use. AX = 16-bit register, whereas
EAX = 32-bit register. Similarly SP vs. ESP. We can use AX in
32-bit mode, but we wouldn’t use it a lot (it’s just the lower 16 bits of EAX.)
See
www.cs.umb.edu/ulab for first
steps--get the ulab module load into your .cshrc and build and run
test.c. Note that the ulab module adds environment variables to your UNIX
process to make SAPC work easier. $pcex is the examples directory
path. Try “echo $pcex” to check, “env | grep pc” to see more.
Note
that we use a cross-compiler i386-gcc and other cross-tools—they run on Sparc
but generate or work with x86 machine code. The makefile in $pcex can
build from any single C source xyz.c by “make C=xyc”. This will make
xyz.lnx, an SAPC executable stored in a UNIX file.
We
can download a .lnx file by using mtip, a Sparc UNIX program usable on
ulab.cs.umb.edu. The reason it has to be ulab is that the serial lines to
the 14 SAPCs are connected to ulab. mtip finds a SAPC not in use already
and assigns it to you, and then provides a conduit between your keyboard and
monitor and the console of your SAPC. It watches the characters as they
go by, and if you type “~r”, it springs into action and arranges a reboot for
you, or if you type “~d”, a download.
If
you are logged in to ulab using ssh, the ~ character is used as a command
escape for ssh, so you need to double up tildas to get them through, that is,
type ~~r to reset the SAPC and ~~d to download.
Alternatively, use the <esc> character (new feature).
With
the help of mtip, you will see the Tutor prompt “Tutor>” coming from your
SAPC. Tutor was listed above as SAPC software—it is running on the SAPC.
System
setup for SAPCs
Each
SAPC is (effectively) connected to the UNIX host “ulab” by a serial line from
COM2 on the SAPC to (effectively) a serial port on ulab. We call this the
console line. (Actually, there is a terminal concentrator involved.) When
Tutor prints a prompt, those bytes are going out COM2 and are handled by the
UNIX program “mtip” that we run on ulab.
mtip
shuttles bytes back and forth between your stdin/stdout user i/o setup and the
console line. When you type a character during an mtip session, it goes
via stdin to the mtip program, and from there out to COM2 of the connected
SAPC. If you type “~” or <esc>, the mtip escape character, mtip
takes notice and then waits for the next character to see what to do, for
example ~d (or <esc>d) for download.
Each
SAPC numbered 5 or more has its COM1 separately connected to another serial
port on ulab. This connection is used by remote gdb to provide debugging.
When
you type “~r” (or <esc>r) in mtip, the connected SAPC gets
rebooted. This works by first being interpreted by mtip, and then mtip
runs another program that sends a command via a serial port on ulab to the
“reset server”, a little machine that John Lentz built for this purpose.
It interprets the command and then generates a signal on a wire into the reset
circuitry of the right SAPC, that is, a signal equivalent to pressing the reset
button on the SAPC box.
Intro
to hw1—
Problem
1—warmup for 2. Just duplicate a given remgdb session –due Sun,
Sept. 22
Rest
due following Oct 1--
Problem
2--finishing an i/o library for the SAPC.
Problem 3—designing an extension of the
i/o library to handle LPT1
Main part of hw1--finishing an i/o library for the SAPC.
As a library, it
implements certain useful functions for apps. Its API is in io_public.h:
void ioinit(void);
int read(int dev, char *buf, int nchar);
int write(int dev, char *buf, int nchar);
also “control”
Read
and write look very much like the same-named UNIX system calls, except for
“dev” instead of “fd”. The dev parameter is the device number, for the io
library. Here dev can be TTY0 (value 0, standing for COM1) or TTY1 (value 1,
standing for COM2). See tty_public.h for the following:
#define
TTY0 0
#define
TTY1 1
Look
at the API again. This can be called a “device-independent” i/o library because the interface is generic,
not specific to any particular device. The actual device in use can be
determined at runtime, for example, by asking the user for a device number.
Recall
from CS341 that the SAPC device numbers COM1 (value 1) and COM2 (value 2) are
in a system of numbers set up in $pcinc/sysapi.h, which is included from
$pcinc/stdio.h, and thus is in effect in any program with “#include
<stdio.h>” or equivalent. In hw1,
we’ll use TTY0 and TTY1 instead, following the UNIX convention to number devices
from 0.
Serial lines for SAPC
SAPC
library name cs444 i/o library name use
COM1 = 1 in $pcinc/stdio.h |
TTY0 = 0 in tty_public.h |
Remote gdb protocol |
COM2 = 2 in $pcinc/stdio.h |
TTY1 = 1 in tty_public.h |
Console i/o via mtip |
Note:
you should have the environment variable pcinc defined for you by the ulab
module, so if you can run mtip, you can also use $pcinc, for example by doing
"cd $pcinc" or "ls $pcinc" or "more
$pcinc/stdio.h". To see what it stands for, do "echo
$pcinc". It's just a directory in the UNIX filesystem. Similarly
$pcex stands for the file path to the SAPC examples directory.
In
our programs, we put “#include <stdio.h>” and somehow end up using
$pcinc/stdio.h. How does this work?
Answer:
gcc is given a flag –Idirectory that tells it where to look for header files. See the makefile.
Here is part of the provided test program testio.c, to show that it calls into the library using the API quoted above.
testio.c:
… /* make ldev = TTY1
*/
ioinit(); /* Initialize devices */
kprintf("\nTrying simple
write...\n");
got =
write(ldev,"hi!\n",4); /*
here ldev = TTY1, i.e. COM2, the console line for an SAPC */
…
testio.c
is the test program calling through the API. After making sure it’s
talking to the user over a serial line, device ldev, it does ioinit() and then
write(ldev, “hi!\n”, 4) as a first test. As delivered, output works but
without using interrupts. Your job is to reimplement it with interrupts.
In
"write(ldev, buf, nchar)", seen in testio.c, ldev is TTY0 or TTY1.
These numbers are defined in the header file tty_public.h provided with the hw1
project files. These device numbers are special to hw1, hw2, etc.
kprintf. Note the use of kprintf instead of printf in testio.c
and elsewhere. kprintf (for kernel printf, currently called printk in Linux
sources) first turns off all interrupts then executes printf with the same
arguments as it was called with, and then restores interrupts to their previous
state. This means that if execution
reaches the kprintf code it will definitely print out the message, even if
interrupts are enabled in the program.
That is a great help for debugging, since it’s important to know where
execution is in the code. So be sure to use kprintf instead of printf for
debugging hw1 code.
The
edits you need to make for hw1 are all in tty.c, in ttyread and ttywrite and
the interrupt handler. A call to read ends up at ttyread and a call to
write at ttywrite. I’ll let you trace out how this happens. Look at
io.c and ioconf.c. This shows how device independent i/o systems work—the
device number specifies which device-specific function to actually
execute. Here the device-specific functions are ttyread and ttywrite, and
the bundle of tty-functions in tty.c is called the tty driver, or serial port
driver.
SAPC
Support Library
Uses
device numbers: COM1, COM2, CONSOLE, etc., #define’d via stdio.h for SAPC
#include
<stdio.h> includes special stdio.h for SAPC, in $pcinc.
In
the SAPC library, also arranged for access in the makefile:
Note
that kprintf and some other functions in the SAPC library are utilizing the
fact that our SAPC code is running in kernel mode, not user mode as is normal
for C applications. In user mode, we
cannot turn off the interrupt system, as is done in kprintf!
C
“Objects”, a quick intro/review.
Here
the Queue ADT in C is provided in the queue subdirectory, along with a unit
test testqueue.c. queue.h defines the Queue API and the Queue type.
You
know how to do objects in Java, what about in C? Recall the Chip object
in CS341. Also the Cmd object for tutor.
Example:
Rectangle objects
struct rect {
int x1, y1, x2, y2;
};
struct rect *recp;
recp->x1 = 10;
Watch
out!, there’s no (validly-allocated) memory pointed to by recp! This is a
garbage pointer, a pointer that points nowhere good. Using it
usually causes segmentation violations on UNIX and similar exceptions on
Windows. But on SAPC, all user memory is writable, so it may quietly work
to damage some memory.
Normally
under UNIX or Windows, we could malloc space for the Rectangle, but we have no
malloc in the SAPC library. Anyway, malloc is quite expensive in CPU, and
we can easily avoid using it. Just set up whole objects like this:
struct rect rect;
Now
we can put
rect.x1 = 10;
As a Java programmer, you’re used to
“Rectangle rect;” meaning rect is a ref to a Rectangle, but in C, rect is the
whole object, more like int x; in C or Java.
To make a rectangle pointer, we have to use * in the
type: “struct rect *rp;” defines rp to be a struct rect pointer.