add directory study
This commit is contained in:
9
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/Makefile
Normal file
9
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
all:
|
||||
@echo /usr/lib/cpp needs 50000 bytes of stack space. Current size is:
|
||||
@size /usr/lib/cpp
|
||||
@echo If it has less than 50K, het DEL and use chmem to change it.
|
||||
cd kernel; make
|
||||
cd fs; make
|
||||
cd mm; make
|
||||
cd ../tools; make net
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
CFLAGS=-F
|
||||
all: client1 server1 client2 server2 client3 server3
|
||||
|
||||
client1: header.h client1.s
|
||||
cc -o client1 client1.s
|
||||
|
||||
client2: header.h client2.s
|
||||
cc -o client2 client2.s
|
||||
|
||||
client3: header.h client3.s
|
||||
cc -o client3 client3.s
|
||||
|
||||
server1: header.h server1.s
|
||||
cc -o server1 server1.s
|
||||
chmem =1000 server1
|
||||
|
||||
server2: header.h server2.s
|
||||
cc -o server2 server2.s
|
||||
chmem =1000 server2
|
||||
|
||||
server3: header.h server3.s
|
||||
cc -o server3 server3.s
|
||||
chmem =1000 server3
|
||||
@@ -0,0 +1,59 @@
|
||||
This directory contains several examples of networking code. These examples
|
||||
also serve as programs to test the correctness and performance of the
|
||||
networking and to provide some useful utility functions. In all the tests,
|
||||
the client and server may run on the same machine, or if an Ethernet is
|
||||
installed, on different machines. The ports 'xyz' used in tests 1 and 2
|
||||
are examples. It is possible to run multiple tests at the same time (e.g.,
|
||||
n1 sets of (client1, server1) and n2 sets of (client2, server2), provided
|
||||
that each pair of (clientX, serverX) uses a port not used by any other process.
|
||||
|
||||
1. Test 1 consists of two programs, server1.c and client1.c. This test
|
||||
transfers 1 megabyte from the client to the server in 1K chunks, has the
|
||||
server transform the data and send it back. The client then verifies if
|
||||
the returned data is correct. To run the test, type the following lines:
|
||||
|
||||
make client1 server1
|
||||
server1 xyz &
|
||||
client1 xyz
|
||||
|
||||
If an Ethernet is installed and the kernel has been compiled with
|
||||
-DAM_KERNEL, the server and client may either be on the same machine or
|
||||
one different ones. If there is no Ethernet and the kernel has been
|
||||
compiled with _DAM_KERNEL -DNONET, both processes must be on the same CPU.
|
||||
|
||||
At the end of the test, "ok" is printed if no errors occurred. Otherwise
|
||||
the number of bad transactions is printed. Both the client and server exit
|
||||
by themselves after the test has been completed.
|
||||
|
||||
2. Test 2 consists of two programs, server2.c and client2.c. This test
|
||||
measures the performance of the transactions. Like test 1, it can be run
|
||||
either locally or remotely. The test consists of having the client request
|
||||
n bytes of data from the server, where n grows from 1 to 30,000 bytes per
|
||||
transaction. For each value of n, the test is run 1000 times to increase
|
||||
the statistical accuracy. For each value of n, the value of n, the delay
|
||||
(transaction time in milliseconds), and the throughput (bytes/sec moved)
|
||||
is reported. To run the test, type:
|
||||
|
||||
make client2 server2
|
||||
server2 xyz &
|
||||
client2 xyz
|
||||
|
||||
|
||||
3. Test 3 is an example of how one might go about making a remote file server
|
||||
for MINIX to service diskless PCs. In this approach, one writes a server,
|
||||
server3.c in this example, and a set of library routines, contained in
|
||||
client3.c. These library routines should have the same names as the MINIX
|
||||
system calls, such as open(), read(), and write(). When programs are linked
|
||||
with these routines instead of the usual ones, the routines make calls to
|
||||
the remote file server instead of FS. The file client3.c contains not only
|
||||
a few of these library routines, but also a short main program to test them.
|
||||
The main program fetches a file from the remote file server and copies it to
|
||||
stdout. To test the program, type:
|
||||
|
||||
make client3 server3
|
||||
server3 &
|
||||
client3 <filename>
|
||||
|
||||
where <filename> is the name of a file on the same machine as server3. The
|
||||
result of this command will be that <filename> is written to client3's
|
||||
standard output.
|
||||
@@ -0,0 +1,56 @@
|
||||
/* This program tests the basic RPC to see if it works. */
|
||||
|
||||
#include <amoeba.h>
|
||||
#include "header.h"
|
||||
|
||||
#define MAX_TRIALS 1000
|
||||
|
||||
char buffer1[BUF_SIZE], buffer2[BUF_SIZE];
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
|
||||
header hdr1, hdr2;
|
||||
int cnt, i, base = 0, size, errors, blocks, iterations = 0;
|
||||
long bad_trans = 0;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: client1 portname\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Copy the filename into the start of the buffer. */
|
||||
strncpy(&hdr1.h_port, argv[1], PORTSIZE);
|
||||
hdr1.h_command = WORK;
|
||||
|
||||
printf("Number of tests performed = %5d ", 0);
|
||||
|
||||
while (iterations < MAX_TRIALS) {
|
||||
/* Initialize the buffer. */
|
||||
for (i = 0; i < BUF_SIZE; i++) buffer1[i] = base + i;
|
||||
|
||||
size = trans(&hdr1, buffer1, BUF_SIZE, &hdr2, buffer2, BUF_SIZE);
|
||||
if (size < 0) {
|
||||
printf("\nTransaction failed. Error = %d. ", size);
|
||||
printf("Hit F1 to see if AMTASK running.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check reply. */
|
||||
errors = 0;
|
||||
for (i = 0; i < BUF_SIZE; i++)
|
||||
if ( (buffer2[i]&0377) != ( (buffer1[i]+1)&0377)) errors++;
|
||||
if (errors > 0) bad_trans++;
|
||||
blocks++;
|
||||
base++;
|
||||
iterations++;
|
||||
if (iterations % 10 == 0) printf("\b\b\b\b\b\b%5d ", iterations);
|
||||
}
|
||||
|
||||
/* Test done. Send null trans to tell server. Report on errors. */
|
||||
hdr1.h_command = QUIT;
|
||||
trans(&hdr1, buffer1, 0, &hdr2, buffer2, BUF_SIZE);
|
||||
printf("\b. Number of errors = %d.\n", bad_trans);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/* This file is the client of a test program for measuring RPC speed. */
|
||||
|
||||
#include <amoeba.h>
|
||||
#include <minix/callnr.h>
|
||||
#include "header.h"
|
||||
|
||||
#define TRIALS 1000
|
||||
|
||||
char buffer[MAX_TRANS];
|
||||
int bytes[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096,
|
||||
8192, 16384, 30000, 0};
|
||||
|
||||
header hdr1, hdr2;
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i, cnt;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: client2 portname\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Copy the filename into the start of the buffer. */
|
||||
strncpy(&hdr1.h_port, argv[1], PORTSIZE);
|
||||
hdr1.h_command = READ;
|
||||
|
||||
printf("Buf size Delay Throughput (Each test repeated %d times)\n", TRIALS);
|
||||
printf(" (msec/trans) (bytes/sec)\n");
|
||||
printf("-------- ------------ -----------\n");
|
||||
|
||||
i = 0;
|
||||
while (bytes[i] != 0) {
|
||||
run_test(bytes[i], TRIALS);
|
||||
i++;
|
||||
}
|
||||
hdr1.h_command = QUIT;
|
||||
trans(&hdr1, buffer, 0, &hdr2, buffer, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
run_test(count, trials)
|
||||
int count, trials;
|
||||
{
|
||||
/* Run a performance test. */
|
||||
|
||||
int i, n;
|
||||
long start, finish, traffic, sec, msec, delay, throughput;
|
||||
|
||||
time(&start); /* record starting time */
|
||||
for (i = 0; i < trials; i++) {
|
||||
hdr1.h_command = READ;
|
||||
hdr1.h_size = (unshort) count;
|
||||
n = trans(&hdr1, buffer, 0, &hdr2, buffer, MAX_TRANS);
|
||||
if (n < 0) {
|
||||
printf("Transaction failed. Error = %d. ", n);
|
||||
printf("Hit F1 to see if AMTASK running.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
time(&finish);
|
||||
sec = finish - start; /* time for this trial in seconds */
|
||||
msec = 1000L * sec;
|
||||
traffic = (long) trials * (long) count;
|
||||
delay = msec/trials; /* msec per transaction */
|
||||
if (sec != 0L)
|
||||
throughput = traffic/sec;
|
||||
else
|
||||
throughput = 0L;
|
||||
printf(" %5d %4D %7D\n", count, delay, throughput);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
/* This file shows how one could build a remote file server for MINIX.
|
||||
* In this file there are several library routines for the basic system
|
||||
* calls. Unlike the "real" ones, these call a remote file server instead
|
||||
* of the local kernel. On client machines, one would replace the library
|
||||
* routines with these routines, and then recompile programs. In this way,
|
||||
* clients will then call the remote file server. It should be obvious that
|
||||
* this file is just an example, and that a productio version would have to
|
||||
* be much more complete.
|
||||
*
|
||||
* The file server3.c contains the start of a stateless file server. Because
|
||||
* MINIX is not stateless, the conversion must be done in this library. For
|
||||
* example, when an open() is done, the library records the name, but no
|
||||
* operation is performed on the file server.
|
||||
*
|
||||
* An alternative approach to making a remote file systems is to replace FS,
|
||||
* the local file server, with one that makes the calls to the remote file
|
||||
* server itself. This approach is less efficient, because a call then
|
||||
* consists of a local FS call plus a remote one, but it is more transparent
|
||||
* because no programs need to recompiled.
|
||||
*/
|
||||
|
||||
#include <amoeba.h>
|
||||
#include <errno.h>
|
||||
#include <minix/callnr.h>
|
||||
#include "header.h"
|
||||
|
||||
#define MAX_FD 20
|
||||
#define LOCAL 100
|
||||
#define HEAPSIZE 512 /* space for file names */
|
||||
#define WRITING 2
|
||||
#define ER -1
|
||||
#define FS 1
|
||||
#define NIL_PTR (char*) 0
|
||||
|
||||
/* The local array is indexed by file descriptor. Those entries containing
|
||||
* LOCAL are local (e.g., stdin), those containing REMOTE are remote, and
|
||||
* those containing 0 are unassigned.
|
||||
*/
|
||||
|
||||
char where[MAX_FD] = {LOCAL, LOCAL, LOCAL};
|
||||
long pos[MAX_FD]; /* current offset */
|
||||
char *server_name = "filsrv";
|
||||
char *file_name[MAX_FD];
|
||||
|
||||
char heap[HEAPSIZE];
|
||||
char *heap_ptr = heap;
|
||||
header hdr1, hdr2;
|
||||
char buffer[BUF_SIZE+NAME_SIZE];
|
||||
|
||||
extern int errno;
|
||||
|
||||
|
||||
/*============================= Remote Library ==============================*/
|
||||
int open(name, how)
|
||||
char *name;
|
||||
int how;
|
||||
{
|
||||
/* Open is entirely local. */
|
||||
|
||||
int i, len;
|
||||
|
||||
if (how < 0 || how > 2) { errno = EINVAL; return(ER);}
|
||||
|
||||
/* Find a free file descriptor. */
|
||||
for (i = 0; i < MAX_FD; i++) {
|
||||
if (where[i] == 0) {
|
||||
len = strlen(name);
|
||||
file_name[i] = heap_ptr;
|
||||
bcopy(name, heap_ptr, len);
|
||||
heap_ptr += len;
|
||||
*heap_ptr++ = 0;
|
||||
where[i] = how+1;
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
errno = EMFILE;
|
||||
return(ER);
|
||||
}
|
||||
|
||||
int creat(name, mode)
|
||||
char *name;
|
||||
int mode;
|
||||
{
|
||||
/* Create a file. */
|
||||
|
||||
int i, len, n;
|
||||
|
||||
/* Find a free file descriptor. */
|
||||
for (i = 0; i < MAX_FD; i++) {
|
||||
if (where[i] == 0) {
|
||||
len = strlen(name);
|
||||
file_name[i] = heap_ptr;
|
||||
bcopy(name, heap_ptr, len);
|
||||
heap_ptr += len;
|
||||
*heap_ptr++ = 0;
|
||||
where[i] = WRITING;
|
||||
|
||||
strncpy(&hdr1.h_port, server_name, PORTSIZE);
|
||||
hdr1.h_command = CREAT;
|
||||
hdr1.h_size = mode;
|
||||
n = trans(&hdr1, file_name[i], len+1, &hdr2, buffer, 0);
|
||||
if (n < 0) {errno = EIO; return(ER);}
|
||||
return(hdr2.h_status);
|
||||
}
|
||||
}
|
||||
errno = EMFILE;
|
||||
return(ER);
|
||||
}
|
||||
|
||||
|
||||
/* int close(fd)
|
||||
int fd;
|
||||
{
|
||||
|
||||
if (where[fd] == LOCAL) return(Xclose(fd));
|
||||
if (where[fd] == 0) {errno = EBADF; return(ER);}
|
||||
where[fd] = 0;
|
||||
return(OK);
|
||||
}
|
||||
*/
|
||||
|
||||
int read(fd, buf, bytes)
|
||||
int fd, bytes;
|
||||
char buf[];
|
||||
{
|
||||
/* Primitive read() routine for reads up to 1K. */
|
||||
|
||||
int n;
|
||||
|
||||
if (where[fd] == LOCAL) return (Xread(fd, buf, bytes));
|
||||
if ((where[fd]&1) == 0) {errno = EBADF; return(ER);}
|
||||
if (bytes > BUF_SIZE) return(EINVAL); /* in a real version, fix this */
|
||||
strncpy(&hdr1.h_port, server_name, PORTSIZE);
|
||||
|
||||
hdr1.h_command = READ;
|
||||
hdr1.h_size = bytes;
|
||||
hdr1.h_offset = pos[fd];
|
||||
n = trans(&hdr1, file_name[fd], strlen(file_name[fd])+1, &hdr2, buf, bytes);
|
||||
if (n < 0) {errno = EIO; return(ER);}
|
||||
if (hdr2.h_extra != 0) errno = hdr2.h_extra;
|
||||
pos[fd] += hdr2.h_status; /* advance file position */
|
||||
return(hdr2.h_status);
|
||||
}
|
||||
|
||||
|
||||
int write(fd, buf, bytes)
|
||||
int fd, bytes;
|
||||
char buf[];
|
||||
{
|
||||
/* Primitive write() routine for writes up to 1K. This is a very simple
|
||||
* routine. Because the server is stateless, for a write we must send both
|
||||
* the data and the file name. In this example, the first 1K of the buffer
|
||||
* is reserved for the data, with the file name starting at position 1024.
|
||||
*/
|
||||
|
||||
int n, len;
|
||||
|
||||
if (where[fd] == LOCAL) return (Xwrite(fd, buf, bytes));
|
||||
if ((where[fd]&02) == 0) {errno = EBADF; return(ER);}
|
||||
if (bytes > BUF_SIZE) return(EINVAL); /* in a real version, fix this */
|
||||
strncpy(&hdr1.h_port, server_name, PORTSIZE);
|
||||
|
||||
len = strlen(file_name[fd]);
|
||||
hdr1.h_command = WRITE;
|
||||
hdr1.h_size = bytes;
|
||||
hdr1.h_offset = pos[fd];
|
||||
bcopy(buf, buffer, bytes); /* copy data to message */
|
||||
bcopy(file_name[fd], &buffer[BUF_SIZE], len+1);
|
||||
n = trans(&hdr1, buffer, BUF_SIZE+len+1, &hdr2, buf, 0);
|
||||
if(n < 0) {errno = EIO; return(ER);}
|
||||
if (hdr2.h_extra != 0) errno = hdr2.h_extra;
|
||||
pos[fd] += hdr2.h_status;
|
||||
return(hdr2.h_status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Below are the real calls, which are sometimes needed. */
|
||||
|
||||
int Xread(fd, buffer, nbytes)
|
||||
int fd;
|
||||
char *buffer;
|
||||
int nbytes;
|
||||
{
|
||||
int n;
|
||||
n = callm1(FS, READ, fd, nbytes, 0, buffer, NIL_PTR, NIL_PTR);
|
||||
return(n);
|
||||
}
|
||||
|
||||
int Xwrite(fd, buffer, nbytes)
|
||||
char *buffer;
|
||||
int nbytes;
|
||||
{
|
||||
return callm1(FS, WRITE, fd, nbytes, 0, buffer, NIL_PTR, NIL_PTR);
|
||||
}
|
||||
|
||||
|
||||
int Xclose(fd)
|
||||
int fd;
|
||||
{
|
||||
return callm1(FS, CLOSE, fd, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ========================= test program =============================*/
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int fd1, n;
|
||||
char b[1024];
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: client3 file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd1 = open(argv[1], 0);
|
||||
if (fd1 < 0) {
|
||||
printf("Open of %s failed\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
do {
|
||||
if ((n=read(fd1, b, 1024) < 0)) {
|
||||
printf("Cannot read %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
if (write(1, b, n) < 0) {
|
||||
printf("Cannot write stdout\n");
|
||||
exit(1);
|
||||
}
|
||||
} while (n > 0);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* Some declarations need by the example clients and servers. */
|
||||
|
||||
char *file_server = "filsrv";
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
#define NAME_SIZE 512
|
||||
#define WORK 1
|
||||
#define QUIT 999
|
||||
#define MAX_TRANS 30000
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <amoeba.h>
|
||||
#include "header.h"
|
||||
|
||||
char buffer[BUF_SIZE];
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
unshort getreq(), putrep();
|
||||
|
||||
header hdr;
|
||||
int cnt, i, iterations = 0;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: server1 portname\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strncpy( (char *) &hdr.h_port, argv[1], PORTSIZE); /* init port */
|
||||
|
||||
while (1) {
|
||||
|
||||
/* Wait for a request to arrive. */
|
||||
if ((cnt = (short) getreq(&hdr, buffer, BUF_SIZE)) < 0) {
|
||||
printf("Server's getreq failed. Error = %d. ", cnt);
|
||||
printf("Hit F1 to see if AMTASK running.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Opcode QUIT indicates that we are done. */
|
||||
if (hdr.h_command == QUIT) {
|
||||
putrep(&hdr, buffer, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* We have a request. Increment each byte. */
|
||||
for (i = 0; i < cnt; i++) buffer[i]++;
|
||||
|
||||
/* Send back reply. */
|
||||
hdr.h_status = 0;
|
||||
putrep(&hdr, buffer, cnt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <amoeba.h>
|
||||
#include "header.h"
|
||||
|
||||
char buffer[MAX_TRANS];
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
|
||||
header hdr;
|
||||
int count;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("Usage: server2 portname\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strncpy( (char *) &hdr.h_port, argv[1], PORTSIZE); /* init port */
|
||||
|
||||
while (1) {
|
||||
/* Wait for a request to arrive. */
|
||||
count = (short) getreq(&hdr, buffer, MAX_TRANS);
|
||||
if (count < 0) {
|
||||
printf("Server's getreq failed. Error = %d. ", count);
|
||||
printf("Hit F1 to see if AMTASK running.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Opcode QUIT indicates that we are done. */
|
||||
if (hdr.h_command == QUIT) {
|
||||
putrep(&hdr, buffer, 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* We have a request. Reply. */
|
||||
count = hdr.h_size;
|
||||
putrep(&hdr, buffer, count);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#include <amoeba.h>
|
||||
#include <minix/callnr.h>
|
||||
#include <errno.h>
|
||||
#include "header.h"
|
||||
|
||||
header hdr; /* header for incoming messages */
|
||||
char buffer[BUF_SIZE+NAME_SIZE]; /* buffer for incoming messages */
|
||||
char *server_name = "filsrv";
|
||||
int repsize;
|
||||
extern int errno;
|
||||
|
||||
main()
|
||||
{
|
||||
/* This is a primitive file server. The client runs with a special set of
|
||||
* routines for read(), write(), etc. that call this server. The server is
|
||||
* stateless.
|
||||
*/
|
||||
|
||||
int s;
|
||||
int count;
|
||||
unshort opcode, size;
|
||||
|
||||
strncpy( (char *) &hdr.h_port, server_name, PORTSIZE); /* init port */
|
||||
|
||||
while (1) {
|
||||
/* Wait for a request to arrive. */
|
||||
count = (short) getreq(&hdr, buffer, MAX_TRANS);
|
||||
if (count < 0) {
|
||||
printf("Server's getreq failed. Error = %d. ", count);
|
||||
printf("Hit F1 to see if AMTASK running.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Dispatch on opcode. */
|
||||
opcode = hdr.h_command;
|
||||
repsize = 0;
|
||||
errno = 0;
|
||||
switch(opcode) {
|
||||
case CREAT: s = do_creat(); break;
|
||||
case READ: s = do_read(); break;
|
||||
case WRITE: s = do_write(); break;
|
||||
default: s = EINVAL; break;
|
||||
}
|
||||
|
||||
/* Work done. Send a reply. */
|
||||
hdr.h_status = (unshort) s;
|
||||
hdr.h_extra = (unshort) errno;
|
||||
putrep(&hdr, buffer, repsize);
|
||||
}
|
||||
}
|
||||
|
||||
int do_read()
|
||||
{
|
||||
/* Stateless read. */
|
||||
|
||||
int fd, n;
|
||||
long offset;
|
||||
unshort count;
|
||||
|
||||
offset = hdr.h_offset;
|
||||
count = hdr.h_size;
|
||||
if (count > MAX_TRANS) count = MAX_TRANS;
|
||||
|
||||
fd = open(buffer, 0); /* open the file for reading */
|
||||
if (fd < 0) return(errno);
|
||||
lseek(fd, offset, 0);
|
||||
n = read(fd, buffer, count);
|
||||
close(fd);
|
||||
repsize = n;
|
||||
return(n);
|
||||
}
|
||||
|
||||
int do_write()
|
||||
{
|
||||
/* Stateless write. */
|
||||
|
||||
int fd, n;
|
||||
long offset;
|
||||
unshort count;
|
||||
|
||||
offset = hdr.h_offset;
|
||||
count = hdr.h_size;
|
||||
if (count > MAX_TRANS) count = MAX_TRANS;
|
||||
|
||||
fd = open(&buffer[BUF_SIZE], 2); /* open the file for writing */
|
||||
if (fd < 0) return(errno);
|
||||
lseek(fd, offset, 0);
|
||||
n = write(fd, buffer, count);
|
||||
close(fd);
|
||||
return(n);
|
||||
}
|
||||
|
||||
int do_creat()
|
||||
{
|
||||
/* Stateless creat. */
|
||||
|
||||
int fd, n, mode;
|
||||
|
||||
|
||||
mode = hdr.h_size;
|
||||
fd = creat(buffer, mode); /* creat the file */
|
||||
close(fd);
|
||||
return(fd);
|
||||
}
|
||||
236
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/fs/Makefile
Normal file
236
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/fs/Makefile
Normal file
@@ -0,0 +1,236 @@
|
||||
CFLAGS= -DAM_KERNEL -I../../fs -I. -F
|
||||
|
||||
f=../../fs
|
||||
i=/usr/include
|
||||
s=/usr/include/sys
|
||||
h=/usr/include/minix
|
||||
l=/usr/lib
|
||||
a=$f/fs.h $h/config.h $h/const.h $h/type.h $s/types.h $i/limits.h $i/errno.h \
|
||||
$f/const.h $f/type.h $f/proto.h $f/glo.h
|
||||
|
||||
obj = main.s open.s read.s write.s pipe.s device.s \
|
||||
path.s mount.s link.s super.s inode.s cache.s filedes.s \
|
||||
stadir.s protect.s time.s misc.s utility.s table.s \
|
||||
putc.s
|
||||
|
||||
fs: Makefile $l/head.s $(obj) $l/libc.a $l/end.s
|
||||
asld -i -o fs $l/head.s $(obj) $l/libc.a $l/end.s
|
||||
|
||||
clean:
|
||||
@rm -f $(obj) fs *.bak
|
||||
|
||||
cache.s: $a
|
||||
cache.s: $h/com.h
|
||||
cache.s: $h/boot.h
|
||||
cache.s: $f/buf.h
|
||||
cache.s: $f/file.h
|
||||
cache.s: $f/fproc.h
|
||||
cache.s: $f/inode.h
|
||||
cache.s: $f/super.h
|
||||
cache.s: $f/cache.c
|
||||
$(CC) $(CFLAGS) -c $f/cache.c
|
||||
|
||||
device.s: $a
|
||||
device.s: $h/com.h
|
||||
device.s: $f/dev.h
|
||||
device.s: $f/file.h
|
||||
device.s: $f/fproc.h
|
||||
device.s: $f/inode.h
|
||||
device.s: $f/param.h
|
||||
device.s: $f/device.c
|
||||
$(CC) $(CFLAGS) -c $f/device.c
|
||||
|
||||
filedes.s: $a
|
||||
filedes.s: $f/file.h
|
||||
filedes.s: $f/fproc.h
|
||||
filedes.s: $f/inode.h
|
||||
filedes.s: $f/filedes.c
|
||||
$(CC) $(CFLAGS) -c $f/filedes.c
|
||||
|
||||
inode.s: $a
|
||||
inode.s: $s/stat.h
|
||||
inode.s: $h/boot.h
|
||||
inode.s: $f/buf.h
|
||||
inode.s: $f/file.h
|
||||
inode.s: $f/fproc.h
|
||||
inode.s: $f/inode.h
|
||||
inode.s: $f/super.h
|
||||
inode.s: $f/inode.c
|
||||
$(CC) $(CFLAGS) -c $f/inode.c
|
||||
|
||||
link.s: $a
|
||||
link.s: $s/stat.h
|
||||
link.s: $f/buf.h
|
||||
link.s: $f/file.h
|
||||
link.s: $f/fproc.h
|
||||
link.s: $f/inode.h
|
||||
link.s: $f/param.h
|
||||
link.s: $f/link.c
|
||||
$(CC) $(CFLAGS) -c $f/link.c
|
||||
|
||||
main.s: $a
|
||||
main.s: $h/callnr.h
|
||||
main.s: $h/com.h
|
||||
main.s: $h/boot.h
|
||||
main.s: $f/buf.h
|
||||
main.s: $f/file.h
|
||||
main.s: $f/fproc.h
|
||||
main.s: $f/inode.h
|
||||
main.s: $f/param.h
|
||||
main.s: $f/super.h
|
||||
main.s: $f/main.c
|
||||
$(CC) $(CFLAGS) -c $f/main.c
|
||||
|
||||
misc.s: $a
|
||||
misc.s: $i/fcntl.h
|
||||
misc.s: $h/callnr.h
|
||||
misc.s: $h/com.h
|
||||
misc.s: $h/boot.h
|
||||
misc.s: $f/buf.h
|
||||
misc.s: $f/file.h
|
||||
misc.s: $f/fproc.h
|
||||
misc.s: $f/inode.h
|
||||
misc.s: $f/param.h
|
||||
misc.s: $f/super.h
|
||||
misc.s: $f/misc.c
|
||||
$(CC) $(CFLAGS) -c $f/misc.c
|
||||
|
||||
mount.s: $a
|
||||
mount.s: $s/stat.h
|
||||
mount.s: $f/buf.h
|
||||
mount.s: $f/file.h
|
||||
mount.s: $f/fproc.h
|
||||
mount.s: $f/inode.h
|
||||
mount.s: $f/param.h
|
||||
mount.s: $f/super.h
|
||||
mount.s: $f/mount.c
|
||||
$(CC) $(CFLAGS) -c $f/mount.c
|
||||
|
||||
open.s: $a
|
||||
open.s: $i/fcntl.h
|
||||
open.s: $h/callnr.h
|
||||
open.s: $f/buf.h
|
||||
open.s: $f/file.h
|
||||
open.s: $f/fproc.h
|
||||
open.s: $f/inode.h
|
||||
open.s: $f/param.h
|
||||
open.s: $f/open.c
|
||||
$(CC) $(CFLAGS) -c $f/open.c
|
||||
|
||||
path.s: $a
|
||||
path.s: $f/buf.h
|
||||
path.s: $f/file.h
|
||||
path.s: $f/fproc.h
|
||||
path.s: $f/inode.h
|
||||
path.s: $f/super.h
|
||||
path.s: $f/path.c
|
||||
$(CC) $(CFLAGS) -c $f/path.c
|
||||
|
||||
pipe.s: $a
|
||||
pipe.s: $i/fcntl.h
|
||||
pipe.s: $i/signal.h
|
||||
pipe.s: $h/callnr.h
|
||||
pipe.s: $h/com.h
|
||||
pipe.s: $f/dev.h
|
||||
pipe.s: $f/file.h
|
||||
pipe.s: $f/fproc.h
|
||||
pipe.s: $f/inode.h
|
||||
pipe.s: $f/param.h
|
||||
pipe.s: $f/pipe.c
|
||||
$(CC) $(CFLAGS) -c $f/pipe.c
|
||||
|
||||
protect.s: $a
|
||||
protect.s: $f/buf.h
|
||||
protect.s: $f/file.h
|
||||
protect.s: $f/fproc.h
|
||||
protect.s: $f/inode.h
|
||||
protect.s: $f/param.h
|
||||
protect.s: $f/super.h
|
||||
protect.s: $f/protect.c
|
||||
$(CC) $(CFLAGS) -c $f/protect.c
|
||||
|
||||
putc.s: $a
|
||||
putc.s: $h/com.h
|
||||
putc.s: $f/putc.c
|
||||
$(CC) $(CFLAGS) -c $f/putc.c
|
||||
|
||||
read.s: $a
|
||||
read.s: $i/fcntl.h
|
||||
read.s: $h/com.h
|
||||
read.s: $f/buf.h
|
||||
read.s: $f/file.h
|
||||
read.s: $f/fproc.h
|
||||
read.s: $f/inode.h
|
||||
read.s: $f/param.h
|
||||
read.s: $f/super.h
|
||||
read.s: $f/read.c
|
||||
$(CC) $(CFLAGS) -c $f/read.c
|
||||
|
||||
stadir.s: $a
|
||||
stadir.s: $s/stat.h
|
||||
stadir.s: $f/file.h
|
||||
stadir.s: $f/fproc.h
|
||||
stadir.s: $f/inode.h
|
||||
stadir.s: $f/param.h
|
||||
stadir.s: $f/stadir.c
|
||||
$(CC) $(CFLAGS) -c $f/stadir.c
|
||||
|
||||
super.s: $a
|
||||
super.s: $h/boot.h
|
||||
super.s: $f/buf.h
|
||||
super.s: $f/inode.h
|
||||
super.s: $f/super.h
|
||||
super.s: $f/super.c
|
||||
$(CC) $(CFLAGS) -c $f/super.c
|
||||
|
||||
table.s: $a
|
||||
table.s: $s/stat.h
|
||||
table.s: $h/callnr.h
|
||||
table.s: $h/com.h
|
||||
table.s: $f/buf.h
|
||||
table.s: $f/dev.h
|
||||
table.s: $f/file.h
|
||||
table.s: $f/fproc.h
|
||||
table.s: $f/inode.h
|
||||
table.s: $f/super.h
|
||||
table.s: $f/table.c
|
||||
$(CC) $(CFLAGS) -c $f/table.c
|
||||
|
||||
time.s: $a
|
||||
time.s: $h/callnr.h
|
||||
time.s: $h/com.h
|
||||
time.s: $f/file.h
|
||||
time.s: $f/fproc.h
|
||||
time.s: $f/inode.h
|
||||
time.s: $f/param.h
|
||||
time.s: $f/time.c
|
||||
$(CC) $(CFLAGS) -c $f/time.c
|
||||
|
||||
utility.s: $a
|
||||
utility.s: $h/com.h
|
||||
utility.s: $h/boot.h
|
||||
utility.s: $f/buf.h
|
||||
utility.s: $f/file.h
|
||||
utility.s: $f/fproc.h
|
||||
utility.s: $f/inode.h
|
||||
utility.s: $f/param.h
|
||||
utility.s: $f/super.h
|
||||
utility.s: $f/utility.c
|
||||
$(CC) $(CFLAGS) -c $f/utility.c
|
||||
|
||||
write.s: $a
|
||||
write.s: $f/buf.h
|
||||
write.s: $f/file.h
|
||||
write.s: $f/fproc.h
|
||||
write.s: $f/inode.h
|
||||
write.s: $f/super.h
|
||||
write.s: $f/write.c
|
||||
$(CC) $(CFLAGS) -c $f/write.c
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
300
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/M
Normal file
300
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/M
Normal file
@@ -0,0 +1,300 @@
|
||||
# Makefile for networking kernel using standard Minix directory
|
||||
# layout and compiler.
|
||||
# CPP may need changing to /usr/lib/cpp.
|
||||
# The following nonstandard flags are used:
|
||||
# -F: run cpp and cem sequentially (used when memory is tight)
|
||||
# -T.: put temporaries in working directory (when RAM disk is small)
|
||||
#
|
||||
# Define AM_KERNEL and NONET to get a networking kernel without
|
||||
# a network interface (only local transactions). Define
|
||||
# AM_KERNEL if you have a Western Digital Etherplus card and
|
||||
# want remote transactions. Define STATISTICS to keep track of
|
||||
# Amoeba transaction statistics and to bind function key F5 to
|
||||
# dump them.
|
||||
#
|
||||
BIN =.
|
||||
CC =cc
|
||||
#CFLAGS =-F -T.
|
||||
CFLAGS =-DAM_KERNEL -DSTATISTICS -I../../kernel -I. -DNO_NET
|
||||
CPP =/lib/cpp
|
||||
CPPFLAGS =-DASLD -P
|
||||
END =/lib/end.s
|
||||
LD =asld
|
||||
LDFLAGS =-i
|
||||
LIBS =/lib/libc.a
|
||||
START =start.s
|
||||
|
||||
a =$k/kernel.h $h/config.h $h/const.h $h/type.h \
|
||||
$s/types.h $i/limits.h $i/errno.h \
|
||||
$k/const.h $k/type.h $k/proto.h $k/glo.h
|
||||
h =/usr/include/minix
|
||||
i =/usr/include
|
||||
k =../../kernel
|
||||
s =/usr/include/sys
|
||||
|
||||
|
||||
KEROBJS =cstart.s protect.s protect1.s klib.s mpx.s wini.s \
|
||||
table.s main.s tty.s floppy.s system.s proc.s \
|
||||
clock.s memory.s console.s rs232.s rs2.s printer.s \
|
||||
amoeba.s conf.s dp8390.s util.s etherplus.s portcache.s \
|
||||
trans.s dmp.s exception.s i8259.s misc.s keyboard.s
|
||||
SOBJS =start.s klib.s mpx.s rs2.s
|
||||
|
||||
# Rules.
|
||||
.SUFFIXES: .x # .x files are .s files which need C-preprocessing
|
||||
.x.s:
|
||||
$(CPP) $(CPPFLAGS) $k/$< >$@
|
||||
|
||||
# What to make.
|
||||
dummy: $(BIN)/kernel # this line fixes a bug in RAL's latest make
|
||||
|
||||
$(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
|
||||
$(LD) $(LDFLAGS) -o $(BIN)/kernel \
|
||||
$(START) $(KEROBJS) \
|
||||
$(LIBS) $(END)
|
||||
|
||||
clean:
|
||||
rm -f $(START) $(KEROBJS) $(SOBJS) *.bak
|
||||
|
||||
klib.s: $h/config.h $h/const.h $k/const.h $k/protect.h $k/sconst.h
|
||||
klib.s: $k/klib.x
|
||||
$(CPP) $(CPPFLAGS) $k/klib.x >$@
|
||||
|
||||
mpx.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
|
||||
mpx.s: $k/mpx.x
|
||||
$(CPP) $(CPPFLAGS) $k/mpx.x >$@
|
||||
|
||||
rs2.s: $h/config.h $h/const.h $k/const.h $k/sconst.h
|
||||
rs2.s: $k/rs2.x
|
||||
$(CPP) $(CPPFLAGS) $k/rs2.x >$@
|
||||
|
||||
start.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
|
||||
start.s: $k/start.x
|
||||
$(CPP) $(CPPFLAGS) $k/start.x >$@
|
||||
|
||||
clock.s: $a
|
||||
clock.s: $i/signal.h
|
||||
clock.s: $h/callnr.h
|
||||
clock.s: $h/com.h
|
||||
clock.s: $k/proc.h
|
||||
clock.s: $k/clock.c
|
||||
$(CC) $(CFLAGS) -c $k/clock.c
|
||||
|
||||
console.s: $a
|
||||
console.s: $i/sgtty.h
|
||||
console.s: $h/callnr.h
|
||||
console.s: $h/com.h
|
||||
console.s: $k/protect.h
|
||||
console.s: $k/tty.h
|
||||
console.s: $k/console.c
|
||||
$(CC) $(CFLAGS) -c $k/console.c
|
||||
|
||||
cstart.s: $a
|
||||
cstart.s: $h/boot.h
|
||||
cstart.s: $k/cstart.c
|
||||
$(CC) $(CFLAGS) -c $k/cstart.c
|
||||
|
||||
dmp.s: $a
|
||||
dmp.s: $h/callnr.h
|
||||
dmp.s: $h/com.h
|
||||
dmp.s: $k/proc.h
|
||||
dmp.s: $k/dmp.c
|
||||
$(CC) $(CFLAGS) -c $k/dmp.c
|
||||
|
||||
exception.s: $a
|
||||
exception.s: $i/signal.h
|
||||
exception.s: $k/proc.h
|
||||
exception.s: $k/exception.c
|
||||
$(CC) $(CFLAGS) -c $k/exception.c
|
||||
|
||||
floppy.s: $a
|
||||
floppy.s: $h/callnr.h
|
||||
floppy.s: $h/com.h
|
||||
floppy.s: $k/floppy.c
|
||||
$(CC) $(CFLAGS) -c $k/floppy.c
|
||||
|
||||
i8259.s: $a
|
||||
i8259.s: $k/i8259.c
|
||||
$(CC) $(CFLAGS) -c $k/i8259.c
|
||||
|
||||
keyboard.s: $a
|
||||
keyboard.s: $i/sgtty.h
|
||||
keyboard.s: $i/signal.h
|
||||
keyboard.s: $h/callnr.h
|
||||
keyboard.s: $h/com.h
|
||||
keyboard.s: $k/tty.h
|
||||
keyboard.s: $k/keyboard.c
|
||||
$(CC) $(CFLAGS) -c $k/keyboard.c
|
||||
|
||||
main.s: $a
|
||||
main.s: $i/signal.h
|
||||
main.s: $h/callnr.h
|
||||
main.s: $h/com.h
|
||||
main.s: $k/proc.h
|
||||
main.s: $k/main.c
|
||||
$(CC) $(CFLAGS) -c $k/main.c
|
||||
|
||||
memory.s: $a
|
||||
memory.s: $h/callnr.h
|
||||
memory.s: $h/com.h
|
||||
memory.s: $k/memory.c
|
||||
$(CC) $(CFLAGS) -c $k/memory.c
|
||||
|
||||
misc.s: $a
|
||||
misc.s: $h/com.h
|
||||
misc.s: $k/misc.c
|
||||
$(CC) $(CFLAGS) -c $k/misc.c
|
||||
|
||||
printer.s: $a
|
||||
printer.s: $h/callnr.h
|
||||
printer.s: $h/com.h
|
||||
printer.s: $k/printer.c
|
||||
$(CC) $(CFLAGS) -c $k/printer.c
|
||||
|
||||
proc.s: $a
|
||||
proc.s: $h/callnr.h
|
||||
proc.s: $h/com.h
|
||||
proc.s: $k/proc.h
|
||||
proc.s: $k/proc.c
|
||||
$(CC) $(CFLAGS) -c $k/proc.c
|
||||
|
||||
protect.s: $a
|
||||
protect.s: $k/protect.h
|
||||
protect.s: $k/protect1.c
|
||||
protect.s: $k/protect.c
|
||||
$(CC) $(CFLAGS) -c $k/protect.c
|
||||
|
||||
protect1.s: $a
|
||||
protect1.s: $k/proc.h
|
||||
protect1.s: $k/protect.h
|
||||
protect1.s: $k/protect1.c
|
||||
$(CC) $(CFLAGS) -c $k/protect1.c
|
||||
|
||||
rs232.s: $a
|
||||
rs232.s: $i/sgtty.h
|
||||
rs232.s: $k/tty.h
|
||||
rs232.s: $k/rs232.c
|
||||
$(CC) $(CFLAGS) -c $k/rs232.c
|
||||
|
||||
system.s: $a
|
||||
system.s: $i/signal.h
|
||||
system.s: $h/boot.h
|
||||
system.s: $h/callnr.h
|
||||
system.s: $h/com.h
|
||||
system.s: $k/proc.h
|
||||
system.s: $k/protect.h
|
||||
system.s: $k/system.c
|
||||
$(CC) $(CFLAGS) -c $k/system.c
|
||||
|
||||
table.s: $a
|
||||
table.s: $h/com.h
|
||||
table.s: $k/proc.h
|
||||
table.s: $k/tty.h
|
||||
table.s: $k/table.c
|
||||
$(CC) $(CFLAGS) -c $k/table.c
|
||||
|
||||
tty.s: $a
|
||||
tty.s: $i/sgtty.h
|
||||
tty.s: $i/signal.h
|
||||
tty.s: $h/callnr.h
|
||||
tty.s: $h/com.h
|
||||
tty.s: $k/tty.h
|
||||
tty.s: $k/tty.c
|
||||
$(CC) $(CFLAGS) -c $k/tty.c
|
||||
|
||||
wini.s: $a
|
||||
wini.s: $h/callnr.h
|
||||
wini.s: $h/com.h
|
||||
wini.s: $h/partition.h
|
||||
wini.s: $k/wini.c
|
||||
$(CC) $(CFLAGS) -c $k/wini.c
|
||||
|
||||
amoeba.s: $a
|
||||
amoeba.s: $i/amoeba.h
|
||||
amoeba.s: $i/host_os.h
|
||||
amoeba.s: $i/amparam.h
|
||||
amoeba.s: $i/signal.h
|
||||
amoeba.s: $i/assert.h
|
||||
amoeba.s: ./byteorder.h
|
||||
amoeba.s: ./dp8390info.h
|
||||
amoeba.s: ./etherformat.h
|
||||
amoeba.s: ./global.h
|
||||
amoeba.s: ./internet.h
|
||||
amoeba.s: ./mpx.H
|
||||
amoeba.s: ./portcache.H
|
||||
amoeba.s: $k/proc.h
|
||||
amoeba.s: ./task.h
|
||||
amoeba.s: ./trans.H
|
||||
amoeba.s: amoeba.c
|
||||
|
||||
conf.s: $a
|
||||
conf.s: $i/amoeba.h
|
||||
conf.s: ./conf.h
|
||||
conf.s: ./global.h
|
||||
conf.s: ./mpx.H
|
||||
conf.s: ./portcache.H
|
||||
conf.s: ./task.h
|
||||
conf.s: ./trans.H
|
||||
conf.s: conf.c
|
||||
|
||||
dp8390.s: $a
|
||||
dp8390.s: $h/com.h
|
||||
dp8390.s: $i/assert.h
|
||||
dp8390.s: ./dp8390.h
|
||||
dp8390.s: ./dp8390info.h
|
||||
dp8390.s: ./dp8390stat.h
|
||||
dp8390.s: ./etherformat.h
|
||||
dp8390.s: ./internet.h
|
||||
dp8390.s: dp8390.c
|
||||
|
||||
etherplus.s: $a
|
||||
etherplus.s: $h/com.h
|
||||
etherplus.s: $i/assert.h
|
||||
etherplus.s: ./dp8390.h
|
||||
etherplus.s: ./dp8390info.h
|
||||
etherplus.s: ./eplinfo.h
|
||||
etherplus.s: ./etherformat.h
|
||||
etherplus.s: ./etherplus.h
|
||||
etherplus.s: ./internet.h
|
||||
etherplus.s: etherplus.c
|
||||
|
||||
portcache.s: $a
|
||||
portcache.s: $i/amoeba.h
|
||||
portcache.s: $i/host_os.h
|
||||
portcache.s: ./assert.h
|
||||
portcache.s: ./conf.h
|
||||
portcache.s: ./global.h
|
||||
portcache.s: ./internet.h
|
||||
portcache.s: ./mpx.H
|
||||
portcache.s: ./portcache.H
|
||||
portcache.s: ./task.h
|
||||
portcache.s: ./trans.H
|
||||
portcache.s: portcache.c
|
||||
|
||||
trans.s: $a
|
||||
trans.s: $i/amoeba.h
|
||||
trans.s: $i/host_os.h
|
||||
trans.s: ./amstat.h
|
||||
trans.s: ./assert.h
|
||||
trans.s: ./byteorder.h
|
||||
trans.s: ./exception.h
|
||||
trans.s: ./global.h
|
||||
trans.s: ./internet.h
|
||||
trans.s: ./mpx.H
|
||||
trans.s: ./portcache.H
|
||||
trans.s: ./task.h
|
||||
trans.s: ./trans.H
|
||||
trans.s: trans.c
|
||||
|
||||
util.s: $a
|
||||
util.s: $h/com.h
|
||||
util.s: ./assert.h
|
||||
util.s: ./dp8390.h
|
||||
util.s: ./dp8390info.h
|
||||
util.s: ./eplinfo.h
|
||||
util.s: $k/proc.h
|
||||
util.s: util.c
|
||||
|
||||
|
||||
|
||||
|
||||
302
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/Makefile
Normal file
302
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/Makefile
Normal file
@@ -0,0 +1,302 @@
|
||||
# Makefile for networking kernel using standard Minix directory
|
||||
# layout and compiler.
|
||||
#
|
||||
# /usr/lib/cpp needs about 50K of stack, which is more than usual
|
||||
#
|
||||
# The following nonstandard flags are used:
|
||||
# -F: run cpp and cem sequentially (used when memory is tight)
|
||||
# -T.: put temporaries in working directory (when RAM disk is small)
|
||||
#
|
||||
# Define AM_KERNEL and NONET to get a networking kernel without
|
||||
# a network interface (only local transactions). Define
|
||||
# AM_KERNEL if you have a Western Digital Etherplus card and
|
||||
# want remote transactions. Define STATISTICS to keep track of
|
||||
# Amoeba transaction statistics and to bind function key F5 to
|
||||
# dump them.
|
||||
#
|
||||
BIN =.
|
||||
CC =cc
|
||||
#CFLAGS =-F -T.
|
||||
CFLAGS =-DAM_KERNEL -DSTATISTICS -I../../kernel -I. -F
|
||||
CPP =/usr/lib/cpp
|
||||
CPPFLAGS =-DASLD -P
|
||||
END =/usr/lib/end.s
|
||||
LD =asld
|
||||
LDFLAGS =-i
|
||||
LIBS =/usr/lib/libc.a
|
||||
START =start.s
|
||||
|
||||
a =$k/kernel.h $h/config.h $h/const.h $h/type.h \
|
||||
$s/types.h $i/limits.h $i/errno.h \
|
||||
$k/const.h $k/type.h $k/proto.h $k/glo.h
|
||||
h =/usr/include/minix
|
||||
i =/usr/include
|
||||
k =../../kernel
|
||||
s =/usr/include/sys
|
||||
|
||||
|
||||
KEROBJS =cstart.s protect.s protect1.s klib.s mpx.s wini.s \
|
||||
table.s main.s tty.s floppy.s system.s proc.s \
|
||||
clock.s memory.s console.s rs232.s rs2.s printer.s \
|
||||
amoeba.s conf.s dp8390.s util.s etherplus.s portcache.s \
|
||||
trans.s dmp.s exception.s i8259.s misc.s keyboard.s
|
||||
SOBJS =start.s klib.s mpx.s rs2.s
|
||||
|
||||
# Rules.
|
||||
.SUFFIXES: .x # .x files are .s files which need C-preprocessing
|
||||
.x.s:
|
||||
$(CPP) $(CPPFLAGS) $k/$< >$@
|
||||
|
||||
# What to make.
|
||||
dummy: $(BIN)/kernel # this line fixes a bug in RAL's latest make
|
||||
|
||||
$(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
|
||||
$(LD) $(LDFLAGS) -o $(BIN)/kernel \
|
||||
$(START) $(KEROBJS) \
|
||||
$(LIBS) $(END)
|
||||
|
||||
clean:
|
||||
rm -f $(START) $(KEROBJS) $(SOBJS) *.bak
|
||||
|
||||
klib.s: $h/config.h $h/const.h $k/const.h $k/protect.h $k/sconst.h
|
||||
klib.s: $k/klib.x
|
||||
$(CPP) $(CPPFLAGS) $k/klib.x >$@
|
||||
|
||||
mpx.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
|
||||
mpx.s: $k/mpx.x
|
||||
$(CPP) $(CPPFLAGS) $k/mpx.x >$@
|
||||
|
||||
rs2.s: $h/config.h $h/const.h $k/const.h $k/sconst.h
|
||||
rs2.s: $k/rs2.x
|
||||
$(CPP) $(CPPFLAGS) $k/rs2.x >$@
|
||||
|
||||
start.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
|
||||
start.s: $k/start.x
|
||||
$(CPP) $(CPPFLAGS) $k/start.x >$@
|
||||
|
||||
clock.s: $a
|
||||
clock.s: $i/signal.h
|
||||
clock.s: $h/callnr.h
|
||||
clock.s: $h/com.h
|
||||
clock.s: $k/proc.h
|
||||
clock.s: $k/clock.c
|
||||
$(CC) $(CFLAGS) -c $k/clock.c
|
||||
|
||||
console.s: $a
|
||||
console.s: $i/sgtty.h
|
||||
console.s: $h/callnr.h
|
||||
console.s: $h/com.h
|
||||
console.s: $k/protect.h
|
||||
console.s: $k/tty.h
|
||||
console.s: $k/console.c
|
||||
$(CC) $(CFLAGS) -c $k/console.c
|
||||
|
||||
cstart.s: $a
|
||||
cstart.s: $h/boot.h
|
||||
cstart.s: $k/cstart.c
|
||||
$(CC) $(CFLAGS) -c $k/cstart.c
|
||||
|
||||
dmp.s: $a
|
||||
dmp.s: $h/callnr.h
|
||||
dmp.s: $h/com.h
|
||||
dmp.s: $k/proc.h
|
||||
dmp.s: $k/dmp.c
|
||||
$(CC) $(CFLAGS) -c $k/dmp.c
|
||||
|
||||
exception.s: $a
|
||||
exception.s: $i/signal.h
|
||||
exception.s: $k/proc.h
|
||||
exception.s: $k/exception.c
|
||||
$(CC) $(CFLAGS) -c $k/exception.c
|
||||
|
||||
floppy.s: $a
|
||||
floppy.s: $h/callnr.h
|
||||
floppy.s: $h/com.h
|
||||
floppy.s: $k/floppy.c
|
||||
$(CC) $(CFLAGS) -c $k/floppy.c
|
||||
|
||||
i8259.s: $a
|
||||
i8259.s: $k/i8259.c
|
||||
$(CC) $(CFLAGS) -c $k/i8259.c
|
||||
|
||||
keyboard.s: $a
|
||||
keyboard.s: $i/sgtty.h
|
||||
keyboard.s: $i/signal.h
|
||||
keyboard.s: $h/callnr.h
|
||||
keyboard.s: $h/com.h
|
||||
keyboard.s: $k/tty.h
|
||||
keyboard.s: $k/keyboard.c
|
||||
$(CC) $(CFLAGS) -c $k/keyboard.c
|
||||
|
||||
main.s: $a
|
||||
main.s: $i/signal.h
|
||||
main.s: $h/callnr.h
|
||||
main.s: $h/com.h
|
||||
main.s: $k/proc.h
|
||||
main.s: $k/main.c
|
||||
$(CC) $(CFLAGS) -c $k/main.c
|
||||
|
||||
memory.s: $a
|
||||
memory.s: $h/callnr.h
|
||||
memory.s: $h/com.h
|
||||
memory.s: $k/memory.c
|
||||
$(CC) $(CFLAGS) -c $k/memory.c
|
||||
|
||||
misc.s: $a
|
||||
misc.s: $h/com.h
|
||||
misc.s: $k/misc.c
|
||||
$(CC) $(CFLAGS) -c $k/misc.c
|
||||
|
||||
printer.s: $a
|
||||
printer.s: $h/callnr.h
|
||||
printer.s: $h/com.h
|
||||
printer.s: $k/printer.c
|
||||
$(CC) $(CFLAGS) -c $k/printer.c
|
||||
|
||||
proc.s: $a
|
||||
proc.s: $h/callnr.h
|
||||
proc.s: $h/com.h
|
||||
proc.s: $k/proc.h
|
||||
proc.s: $k/proc.c
|
||||
$(CC) $(CFLAGS) -c $k/proc.c
|
||||
|
||||
protect.s: $a
|
||||
protect.s: $k/protect.h
|
||||
protect.s: $k/protect1.c
|
||||
protect.s: $k/protect.c
|
||||
$(CC) $(CFLAGS) -c $k/protect.c
|
||||
|
||||
protect1.s: $a
|
||||
protect1.s: $k/proc.h
|
||||
protect1.s: $k/protect.h
|
||||
protect1.s: $k/protect1.c
|
||||
$(CC) $(CFLAGS) -c $k/protect1.c
|
||||
|
||||
rs232.s: $a
|
||||
rs232.s: $i/sgtty.h
|
||||
rs232.s: $k/tty.h
|
||||
rs232.s: $k/rs232.c
|
||||
$(CC) $(CFLAGS) -c $k/rs232.c
|
||||
|
||||
system.s: $a
|
||||
system.s: $i/signal.h
|
||||
system.s: $h/boot.h
|
||||
system.s: $h/callnr.h
|
||||
system.s: $h/com.h
|
||||
system.s: $k/proc.h
|
||||
system.s: $k/protect.h
|
||||
system.s: $k/system.c
|
||||
$(CC) $(CFLAGS) -c $k/system.c
|
||||
|
||||
table.s: $a
|
||||
table.s: $h/com.h
|
||||
table.s: $k/proc.h
|
||||
table.s: $k/tty.h
|
||||
table.s: $k/table.c
|
||||
$(CC) $(CFLAGS) -c $k/table.c
|
||||
|
||||
tty.s: $a
|
||||
tty.s: $i/sgtty.h
|
||||
tty.s: $i/signal.h
|
||||
tty.s: $h/callnr.h
|
||||
tty.s: $h/com.h
|
||||
tty.s: $k/tty.h
|
||||
tty.s: $k/tty.c
|
||||
$(CC) $(CFLAGS) -c $k/tty.c
|
||||
|
||||
wini.s: $a
|
||||
wini.s: $h/callnr.h
|
||||
wini.s: $h/com.h
|
||||
wini.s: $h/partition.h
|
||||
wini.s: $k/wini.c
|
||||
$(CC) $(CFLAGS) -c $k/wini.c
|
||||
|
||||
amoeba.s: $a
|
||||
amoeba.s: $i/amoeba.h
|
||||
amoeba.s: $i/host_os.h
|
||||
amoeba.s: $i/amparam.h
|
||||
amoeba.s: $i/signal.h
|
||||
amoeba.s: $i/assert.h
|
||||
amoeba.s: ./byteorder.h
|
||||
amoeba.s: ./dp8390info.h
|
||||
amoeba.s: ./etherformat.h
|
||||
amoeba.s: ./global.h
|
||||
amoeba.s: ./internet.h
|
||||
amoeba.s: ./mpx.H
|
||||
amoeba.s: ./portcache.H
|
||||
amoeba.s: $k/proc.h
|
||||
amoeba.s: ./task.h
|
||||
amoeba.s: ./trans.H
|
||||
amoeba.s: amoeba.c
|
||||
|
||||
conf.s: $a
|
||||
conf.s: $i/amoeba.h
|
||||
conf.s: ./conf.h
|
||||
conf.s: ./global.h
|
||||
conf.s: ./mpx.H
|
||||
conf.s: ./portcache.H
|
||||
conf.s: ./task.h
|
||||
conf.s: ./trans.H
|
||||
conf.s: conf.c
|
||||
|
||||
dp8390.s: $a
|
||||
dp8390.s: $h/com.h
|
||||
dp8390.s: $i/assert.h
|
||||
dp8390.s: ./dp8390.h
|
||||
dp8390.s: ./dp8390info.h
|
||||
dp8390.s: ./dp8390stat.h
|
||||
dp8390.s: ./etherformat.h
|
||||
dp8390.s: ./internet.h
|
||||
dp8390.s: dp8390.c
|
||||
|
||||
etherplus.s: $a
|
||||
etherplus.s: $h/com.h
|
||||
etherplus.s: $i/assert.h
|
||||
etherplus.s: ./dp8390.h
|
||||
etherplus.s: ./dp8390info.h
|
||||
etherplus.s: ./eplinfo.h
|
||||
etherplus.s: ./etherformat.h
|
||||
etherplus.s: ./etherplus.h
|
||||
etherplus.s: ./internet.h
|
||||
etherplus.s: etherplus.c
|
||||
|
||||
portcache.s: $a
|
||||
portcache.s: $i/amoeba.h
|
||||
portcache.s: $i/host_os.h
|
||||
portcache.s: ./assert.h
|
||||
portcache.s: ./conf.h
|
||||
portcache.s: ./global.h
|
||||
portcache.s: ./internet.h
|
||||
portcache.s: ./mpx.H
|
||||
portcache.s: ./portcache.H
|
||||
portcache.s: ./task.h
|
||||
portcache.s: ./trans.H
|
||||
portcache.s: portcache.c
|
||||
|
||||
trans.s: $a
|
||||
trans.s: $i/amoeba.h
|
||||
trans.s: $i/host_os.h
|
||||
trans.s: ./amstat.h
|
||||
trans.s: ./assert.h
|
||||
trans.s: ./byteorder.h
|
||||
trans.s: ./exception.h
|
||||
trans.s: ./global.h
|
||||
trans.s: ./internet.h
|
||||
trans.s: ./mpx.H
|
||||
trans.s: ./portcache.H
|
||||
trans.s: ./task.h
|
||||
trans.s: ./trans.H
|
||||
trans.s: trans.c
|
||||
|
||||
util.s: $a
|
||||
util.s: $h/com.h
|
||||
util.s: ./assert.h
|
||||
util.s: ./dp8390.h
|
||||
util.s: ./dp8390info.h
|
||||
util.s: ./eplinfo.h
|
||||
util.s: $k/proc.h
|
||||
util.s: util.c
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,13 @@
|
||||
struct amstat {
|
||||
long ams_clfail;
|
||||
long ams_svfail;
|
||||
long ams_clcrash;
|
||||
long ams_rxcl;
|
||||
long ams_rxsv;
|
||||
long ams_trans;
|
||||
long ams_loctrans;
|
||||
long ams_remtrans;
|
||||
long ams_getreq;
|
||||
long ams_putrep;
|
||||
long ams_naks;
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
/****************************************************************************
|
||||
* *
|
||||
* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands *
|
||||
* *
|
||||
* This product is part of the Amoeba distributed operating system. *
|
||||
* Permission is hereby granted to use it exclusively for educational *
|
||||
* and research purposes. It may also be freely duplicated and given *
|
||||
* to others for educational and research purposes only. All other use *
|
||||
* requires written permission from the copyright owner. *
|
||||
* *
|
||||
* Requests for such permissions may be sent to *
|
||||
* *
|
||||
* *
|
||||
* Dr. Andrew S. Tanenbaum *
|
||||
* Dept. of Mathematics and Computer Science *
|
||||
* Vrije Universiteit *
|
||||
* De Boelelaan 1081 *
|
||||
* 1081 HV Amsterdam *
|
||||
* The Netherlands *
|
||||
* *
|
||||
/****************************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#ifdef NDEBUG
|
||||
#define assert(e) /* NOTHING */
|
||||
#define compare(a,t,b) /* NOTHING */
|
||||
#else
|
||||
#ifdef lint
|
||||
#define assert(e) use(e)
|
||||
#define compare(a,t,b) use(a, b)
|
||||
#else lint
|
||||
#define assert(x) if (!(x)) printf("assertion failed in %s at %d\n", __FILE__, __LINE__)
|
||||
#define compare(a,t,b) if (!((a) t (b))) \
|
||||
printf("comparison failed in %s at %d (%D)\n", \
|
||||
__FILE__, __LINE__, a)
|
||||
/*
|
||||
#define assert(e) do if (!(e)) badassertion(__FILE__,__LINE__); while (0)
|
||||
#define compare(a,t,b) do if (!((a) t (b))) \
|
||||
badcompare(__FILE__,__LINE__, (long) (a)); \
|
||||
while (0)
|
||||
*/
|
||||
#endif lint
|
||||
#endif NDEBUG
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* set of macros to do inplace byteorder changes
|
||||
* The dec_* routines decode a short (_s) or long (_l) from little endian(_le)
|
||||
* or bigendian(_be) to native format.
|
||||
* The enc_* are similar for native to net format
|
||||
*/
|
||||
|
||||
|
||||
/* littleendian version for ibm pc */
|
||||
|
||||
#define dec_s_le(s) /* nothing */
|
||||
#define dec_s_be(s) (*(s))=((((*(s))>>8)&0xFF)|(((*(s))&0xFF)<<8))
|
||||
|
||||
#define dec_l_le(l) /* nothing */
|
||||
#define dec_l_be(l) (*(l))=((((*(l))>>24)&0xFF)|(((*(l))>>8)&0xFF00)|(((*(l))<<8)&0xFF0000)|(((*(l))<<24)&0xFF000000))
|
||||
|
||||
#define enc_s_le(s) /* nothing */
|
||||
#define enc_s_be(s) dec_s_be(s)
|
||||
|
||||
#define enc_l_le(l) /* nothing */
|
||||
#define enc_l_be(l) dec_l_be(l)
|
||||
40
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/conf.c
Normal file
40
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/conf.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "kernel.h"
|
||||
#include "amoeba.h"
|
||||
#include "global.h"
|
||||
#include "conf.h"
|
||||
|
||||
/*
|
||||
** the following hack is imported from task.c under Amoeba to declare
|
||||
** a few pointers to the task table
|
||||
*/
|
||||
#define extern
|
||||
|
||||
#include "task.h"
|
||||
|
||||
#undef extern
|
||||
|
||||
/************************************************************************/
|
||||
/* TRANS CONFIGURATION */
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** various variables used for transactions
|
||||
*/
|
||||
|
||||
port NULLPORT; /* used in trans.c, declared here for compatability */
|
||||
long ticker; /* bogus global used by trans.c for statistics */
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
unshort minloccnt = MINLOCCNT;
|
||||
unshort maxloccnt = MAXLOCCNT;
|
||||
|
||||
unshort retranstime = RETRANSTIME;
|
||||
unshort crashtime = CRASHTIME;
|
||||
unshort clientcrash = CLIENTCRASH;
|
||||
|
||||
unshort maxretrans = MAXRETRANS;
|
||||
unshort mincrash = MINCRASH;
|
||||
unshort maxcrash = MAXCRASH;
|
||||
|
||||
#endif NONET
|
||||
15
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/conf.h
Normal file
15
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/conf.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
** constants used for configuring amoeba transactions
|
||||
*/
|
||||
#define MINLOCCNT 5 /* locate message sent every dsec */
|
||||
#define MAXLOCCNT 100 /* locate message sent every MAXLOCCNT dsec */
|
||||
|
||||
#define RETRANSTIME 5 /* retransmission time in dsec */
|
||||
#define CRASHTIME 100 /* crash timer in dsec */
|
||||
#define CLIENTCRASH 500 /* client must probe within this time */
|
||||
|
||||
#define MAXRETRANS 10 /* max. number of transmissions */
|
||||
#define MINCRASH 5 /* enquiry sent MINCRASH times during recv */
|
||||
#define MAXCRASH 10 /* enquiry sent MAXCRASH times during serv */
|
||||
|
||||
#define NPORTS 16 /* # ports in portcache */
|
||||
344
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/dp8390.c
Normal file
344
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/dp8390.c
Normal file
@@ -0,0 +1,344 @@
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
#include "minix/com.h"
|
||||
#include "internet.h"
|
||||
#include "etherformat.h"
|
||||
#include "dp8390.h"
|
||||
#include "dp8390info.h"
|
||||
#include "dp8390stat.h"
|
||||
#include "assert.h"
|
||||
|
||||
/* macros for device I/O */
|
||||
|
||||
#define input(devaddr, dp_register) \
|
||||
in_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg0rd.dp_register)
|
||||
#define input1(devaddr, dp_register) \
|
||||
in_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg1rdwr.dp_register)
|
||||
#define output(devaddr, dp_register, value) \
|
||||
out_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg0wr.dp_register, value)
|
||||
#define output1(devaddr, dp_register, value) \
|
||||
out_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg1rdwr.dp_register, value)
|
||||
|
||||
#define MAX_WAIT 10000
|
||||
|
||||
#ifdef DPSTAT
|
||||
struct dpstat dpstat;
|
||||
#endif
|
||||
|
||||
static int (*bufread)(); /* call when packet came in */
|
||||
static int (*bufwritten)(); /* call when packet has been written */
|
||||
|
||||
static disabled;
|
||||
static phys_bytes curopacket; /* packet being transmitted */
|
||||
static phys_bytes Curbuff; /* address of next read buffer to release */
|
||||
|
||||
static
|
||||
chipinit(myaddr)
|
||||
Eth_addr *myaddr;
|
||||
{
|
||||
register vir_bytes device;
|
||||
|
||||
device = dp8390info.dpi_devaddr;
|
||||
output(device, dp_cr, CR_PS_P0|CR_DM_ABORT); /* back to main register set */
|
||||
output(device, dp_pstart, dp8390info.dpi_pstart);
|
||||
output(device, dp_pstop, dp8390info.dpi_pstop);
|
||||
output(device, dp_bnry, dp8390info.dpi_pstart);
|
||||
output(device, dp_rcr, RCR_MON);
|
||||
output(device, dp_tcr, TCR_NORMAL);
|
||||
output(device, dp_dcr, DCR_BYTEWIDE|DCR_8BYTES);
|
||||
output(device, dp_rbcr0, 0);
|
||||
output(device, dp_rbcr1, 0);
|
||||
output(device, dp_isr, 0xFF);
|
||||
output(device, dp_cr, CR_PS_P1|CR_DM_ABORT); /* switch to register set 1 */
|
||||
output1(device, dp_par0, myaddr->e[0]);
|
||||
output1(device, dp_par1, myaddr->e[1]);
|
||||
output1(device, dp_par2, myaddr->e[2]);
|
||||
output1(device, dp_par3, myaddr->e[3]);
|
||||
output1(device, dp_par4, myaddr->e[4]);
|
||||
output1(device, dp_par5, myaddr->e[5]);
|
||||
output1(device, dp_curr, dp8390info.dpi_pstart+1);
|
||||
output1(device, dp_cr, CR_PS_P0|CR_DM_ABORT);
|
||||
output(device, dp_rcr, RCR_AB);
|
||||
input(device, dp_cntr0);
|
||||
input(device, dp_cntr1);
|
||||
input(device, dp_cntr2);
|
||||
|
||||
#ifdef TRMTINT
|
||||
output(device, dp_imr, IMR_TXEE|IMR_PTXE|IMR_PRXE|IMR_CNTE|IMR_OVWE);
|
||||
#endif
|
||||
output(device, dp_imr, IMR_PRXE|IMR_CNTE|IMR_OVWE);
|
||||
output(device, dp_cr, CR_STA|CR_DM_ABORT); /* fire it up */
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
* Interrupt handling
|
||||
*/
|
||||
|
||||
static
|
||||
dp_xmit_intr()
|
||||
#ifdef TRMTINT
|
||||
{
|
||||
register tsr;
|
||||
|
||||
if (curopacket == 0) {
|
||||
printf("Bogus transmit interrupt\n");
|
||||
STINC(ds_btint);
|
||||
return;
|
||||
}
|
||||
tsr = input(dp8390info.dpi_devaddr, dp_tsr);
|
||||
if (tsr&TSR_PTX)
|
||||
STINC(ds_written); /* It went OK! */
|
||||
if (tsr&TSR_DFR)
|
||||
STINC(ds_deferred);
|
||||
if (tsr&TSR_COL)
|
||||
STINC(ds_collisions);
|
||||
if (tsr&TSR_ABT)
|
||||
STINC(ds_xcollisions);
|
||||
if (tsr&TSR_CRS) {
|
||||
printf("Ethernet carrier sense lost\n");
|
||||
STINC(ds_carlost);
|
||||
}
|
||||
if (tsr&TSR_FU) {
|
||||
printf("Ethernet Fifo Underrun\n");
|
||||
STINC(ds_fifo);
|
||||
}
|
||||
if (tsr&TSR_CDH) {
|
||||
printf("Ethernet Heartbeat failure\n");
|
||||
STINC(ds_heartbeat);
|
||||
}
|
||||
if (tsr&TSR_OWC) {
|
||||
printf("Ethernet late collision\n");
|
||||
STINC(ds_lcol);
|
||||
}
|
||||
(*bufwritten)(curopacket);
|
||||
curopacket = 0;
|
||||
}
|
||||
#else
|
||||
{}
|
||||
#endif
|
||||
|
||||
|
||||
static
|
||||
recvintr()
|
||||
{
|
||||
register vir_bytes device;
|
||||
register phys_bytes paddr;
|
||||
struct rcvdheader pkthead;
|
||||
char pageno, curr, next;
|
||||
int length;
|
||||
|
||||
device = dp8390info.dpi_devaddr;
|
||||
pageno=input(device, dp_bnry)+1;
|
||||
if (pageno == dp8390info.dpi_pstop)
|
||||
pageno = dp8390info.dpi_pstart;
|
||||
while (!(disabled)) {
|
||||
output(device, dp_cr, CR_PS_P1);/* switch to register set 1 */
|
||||
curr = input1(device, dp_curr);
|
||||
output1(device, dp_cr, CR_PS_P0);/* back to main register set*/
|
||||
if (pageno==curr){
|
||||
break;
|
||||
}
|
||||
STINC(ds_read);
|
||||
paddr = dp8390info.dpi_membase+(pageno<<8);
|
||||
getheader(paddr, &pkthead);
|
||||
|
||||
next = pkthead.rp_next;
|
||||
if (pkthead.rp_status&RSR_PRX) {
|
||||
if (next < pageno && next > dp8390info.dpi_pstart) {
|
||||
/*
|
||||
* We copy end of packet to avoid break.
|
||||
*/
|
||||
phys_copy(dp8390info.dpi_membase+
|
||||
(dp8390info.dpi_pstart<<8),
|
||||
dp8390info.dpi_membase+
|
||||
(dp8390info.dpi_pstop<<8),
|
||||
(phys_bytes) (next-dp8390info.dpi_pstart)<<8);
|
||||
}
|
||||
length = (pkthead.rp_rbcl&0xFF)|(pkthead.rp_rbch<<8);
|
||||
Curbuff = paddr + sizeof (pkthead);
|
||||
disabled = 1;
|
||||
(*bufread)(Curbuff, length-4);
|
||||
}
|
||||
pageno = pkthead.rp_next;
|
||||
if (pageno >= dp8390info.dpi_pstop ||
|
||||
pageno < dp8390info.dpi_pstart)
|
||||
printf("page no %x\n", pageno);
|
||||
/* assert(pageno >= dp8390info.dpi_pstart);
|
||||
assert(pageno < dp8390info.dpi_pstop);*/
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
cntintr()
|
||||
{
|
||||
register vir_bytes device;
|
||||
int n;
|
||||
|
||||
printf("dp8390: counter overflow\n"); /*DEBUG*/
|
||||
device = dp8390info.dpi_devaddr;
|
||||
n = input(device, dp_cntr0);
|
||||
STADD(ds_fram, n);
|
||||
n = input(device, dp_cntr1);
|
||||
STADD(ds_crc, n);
|
||||
n =input(device, dp_cntr2);
|
||||
STADD(ds_lost, n);
|
||||
}
|
||||
|
||||
PUBLIC void
|
||||
dp8390_int()
|
||||
{
|
||||
register isr;
|
||||
register vir_bytes device;
|
||||
|
||||
device = dp8390info.dpi_devaddr;
|
||||
for(isr=input(device, dp_isr); isr&(ISR_OVW|ISR_PRX|ISR_PTX|ISR_CNT);
|
||||
isr=input(device, dp_isr)) {
|
||||
if (isr&ISR_OVW) {
|
||||
printf("OVW, do something\n");
|
||||
output(device, dp_isr, ISR_OVW); /* ack */
|
||||
}
|
||||
if (isr&ISR_PTX) {
|
||||
dp_xmit_intr();
|
||||
output(device, dp_isr, ISR_PTX); /* ack */
|
||||
}
|
||||
if (isr&ISR_TXE) {
|
||||
dp_xmit_intr();
|
||||
output(device, dp_isr, ISR_TXE); /* ack */
|
||||
}
|
||||
if (isr&ISR_PRX) {
|
||||
/*recvintr();*/
|
||||
got_packet();
|
||||
output(device, dp_isr, ISR_PRX); /* ack */
|
||||
}
|
||||
if (isr&ISR_CNT) {
|
||||
cntintr();
|
||||
output(device, dp_isr, ISR_CNT); /* ack */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eth_init(etheraddr, br, bw)
|
||||
Eth_addr *etheraddr;
|
||||
int (*br)(), (*bw)();
|
||||
{
|
||||
bufread = br;
|
||||
bufwritten = bw;
|
||||
epl_init(); /* activate on board memory */
|
||||
chipinit(etheraddr); /* start ethernet controller chip */
|
||||
}
|
||||
|
||||
|
||||
|
||||
eth_write(bufaddr, bufcnt)
|
||||
phys_bytes bufaddr;
|
||||
{
|
||||
int bpageno;
|
||||
register vir_bytes device;
|
||||
|
||||
|
||||
device = dp8390info.dpi_devaddr;
|
||||
/* assert(curopacket==0); */
|
||||
assert(((bufaddr-dp8390info.dpi_membase)&0xFF)==0);
|
||||
assert(bufcnt >= 60); /* magic Ethernet requirement */
|
||||
/* assert(bufcnt <= 1514); /* another one */
|
||||
bpageno = ((bufaddr-dp8390info.dpi_membase)>>8) & 0xFF;
|
||||
curopacket = bufaddr;
|
||||
output(device, dp_tpsr, bpageno);
|
||||
output(device, dp_tbcr1, bufcnt>>8);
|
||||
output(device, dp_tbcr0, bufcnt&0xFF);
|
||||
output(device, dp_cr, CR_TXP); /* there it goes */
|
||||
}
|
||||
|
||||
eth_release(bufaddr)
|
||||
phys_bytes bufaddr;
|
||||
{
|
||||
register vir_bytes device;
|
||||
register phys_bytes paddr;
|
||||
struct rcvdheader pkthead;
|
||||
char pageno;
|
||||
|
||||
device = dp8390info.dpi_devaddr;
|
||||
paddr = bufaddr-sizeof(pkthead);
|
||||
assert(((paddr-dp8390info.dpi_membase)&0xFF)==0);
|
||||
getheader(paddr, &pkthead);
|
||||
pageno = pkthead.rp_next;
|
||||
if (pageno == dp8390info.dpi_pstart)
|
||||
pageno = dp8390info.dpi_pstop;
|
||||
if (bufaddr != Curbuff)
|
||||
panic("eth_release: bad order", NO_NUM);
|
||||
output(device, dp_bnry, pageno-1);
|
||||
disabled = 0;
|
||||
/* recvintr(); */
|
||||
}
|
||||
|
||||
phys_bytes
|
||||
eth_getbuf()
|
||||
{
|
||||
int t_cnt;
|
||||
register vir_bytes device;
|
||||
register tsr;
|
||||
|
||||
device = dp8390info.dpi_devaddr;
|
||||
|
||||
t_cnt = 0;
|
||||
while (input(device,dp_cr)&CR_TXP) {
|
||||
if (t_cnt++ > MAX_WAIT)
|
||||
printf("transmitter frozen\n");
|
||||
return (phys_bytes)0;
|
||||
}
|
||||
|
||||
#ifndef TRMTINT
|
||||
#ifdef DPSTAT
|
||||
tsr = input(device, dp_tsr);
|
||||
if (tsr&TSR_PTX)
|
||||
STINC(ds_written); /* It went OK! */
|
||||
if (tsr&TSR_DFR)
|
||||
STINC(ds_deferred);
|
||||
if (tsr&TSR_COL)
|
||||
STINC(ds_collisions);
|
||||
if (tsr&TSR_ABT)
|
||||
STINC(ds_xcollisions);
|
||||
if (tsr&TSR_CRS) {
|
||||
printf("Ethernet carrier sense lost\n");
|
||||
STINC(ds_carlost);
|
||||
}
|
||||
if (tsr&TSR_FU) {
|
||||
printf("Ethernet Fifo Underrun\n");
|
||||
STINC(ds_fifo);
|
||||
}
|
||||
if (tsr&TSR_CDH) {
|
||||
printf("Ethernet Heartbeat failure\n");
|
||||
STINC(ds_heartbeat);
|
||||
}
|
||||
if (tsr&TSR_OWC) {
|
||||
printf("Ethernet late collision\n");
|
||||
STINC(ds_lcol);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return dp8390info.dpi_tbuf; /* return pointer to xmit buffer */
|
||||
}
|
||||
|
||||
#else NONET
|
||||
|
||||
PUBLIC void
|
||||
dp8390_int()
|
||||
{
|
||||
}
|
||||
|
||||
#endif NONET
|
||||
|
||||
PUBLIC void
|
||||
eth_stp()
|
||||
{
|
||||
/* called from reboot() (klib88.s) to stop the ethernet */
|
||||
#ifndef NONET
|
||||
output(dp8390info.dpi_devaddr, dp_cr, CR_STP|CR_DM_ABORT);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
165
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/dp8390.h
Normal file
165
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/dp8390.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* National Semiconductor DP8390 Network Interface Controller
|
||||
*/
|
||||
|
||||
typedef
|
||||
union dp8390reg {
|
||||
struct pg0rd { /* Page 0, for reading ------------- */
|
||||
char dp_cr; /* Read side of Command Register */
|
||||
char dp_clda0; /* Current Local Dma Address 0 */
|
||||
char dp_clda1; /* Current Local Dma Address 1 */
|
||||
char dp_bnry; /* Boundary Pointer */
|
||||
char dp_tsr; /* Transmit Status Register */
|
||||
char dp_ncr; /* Number of Collisions Register */
|
||||
char dp_fifo; /* Fifo ?? */
|
||||
char dp_isr; /* Interrupt Status Register */
|
||||
char dp_crda0; /* Current Remote Dma Address 0 */
|
||||
char dp_crda1; /* Current Remote Dma Address 1 */
|
||||
char dp_dum1; /* unused */
|
||||
char dp_dum2; /* unused */
|
||||
char dp_rsr; /* Receive Status Register */
|
||||
char dp_cntr0; /* Tally Counter 0 */
|
||||
char dp_cntr1; /* Tally Counter 1 */
|
||||
char dp_cntr2; /* Tally Counter 2 */
|
||||
} dp_pg0rd;
|
||||
struct pg0wr { /* Page 0, for writing ------------- */
|
||||
char dp_cr; /* Write side of Command Register */
|
||||
char dp_pstart; /* Page Start Register */
|
||||
char dp_pstop; /* Page Stop Register */
|
||||
char dp_bnry; /* Boundary Pointer */
|
||||
char dp_tpsr; /* Transmit Page Start Register */
|
||||
char dp_tbcr0; /* Transmit Byte Count Register 0 */
|
||||
char dp_tbcr1; /* Transmit Byte Count Register 1 */
|
||||
char dp_isr; /* Interrupt Status Register */
|
||||
char dp_rsar0; /* Remote Start Address Register 0 */
|
||||
char dp_rsar1; /* Remote Start Address Register 1 */
|
||||
char dp_rbcr0; /* Remote Byte Count Register 0 */
|
||||
char dp_rbcr1; /* Remote Byte Count Register 1 */
|
||||
char dp_rcr; /* Receive Configuration Register */
|
||||
char dp_tcr; /* Transmit Configuration Register */
|
||||
char dp_dcr; /* Data Configuration Register */
|
||||
char dp_imr; /* Interrupt Mask Register */
|
||||
} dp_pg0wr;
|
||||
struct pg1rdwr { /* Page 1, read/write -------------- */
|
||||
char dp_cr; /* Command Register */
|
||||
char dp_par0; /* Physical Address Register 0 */
|
||||
char dp_par1; /* Physical Address Register 1 */
|
||||
char dp_par2; /* Physical Address Register 2 */
|
||||
char dp_par3; /* Physical Address Register 3 */
|
||||
char dp_par4; /* Physical Address Register 4 */
|
||||
char dp_par5; /* Physical Address Register 5 */
|
||||
char dp_curr; /* Current Page Register */
|
||||
char dp_mar0; /* Multicast Address Register 0 */
|
||||
char dp_mar1; /* Multicast Address Register 1 */
|
||||
char dp_mar2; /* Multicast Address Register 2 */
|
||||
char dp_mar3; /* Multicast Address Register 3 */
|
||||
char dp_mar4; /* Multicast Address Register 4 */
|
||||
char dp_mar5; /* Multicast Address Register 5 */
|
||||
char dp_mar6; /* Multicast Address Register 6 */
|
||||
char dp_mar7; /* Multicast Address Register 7 */
|
||||
} dp_pg1rdwr;
|
||||
} dp8390;
|
||||
|
||||
/* Bits in dp_cr */
|
||||
|
||||
#define CR_STP 0x01 /* Stop: software reset */
|
||||
#define CR_STA 0x02 /* Start: activate NIC */
|
||||
#define CR_TXP 0x04 /* Transmit Packet */
|
||||
#define CR_DMA 0x38 /* Mask for DMA control */
|
||||
# define CR_DM_NOP 0x00 /* DMA: No Operation */
|
||||
# define CR_DM_RR 0x08 /* DMA: Remote Read */
|
||||
# define CR_DM_RW 0x10 /* DMA: Remote Write */
|
||||
# define CR_DM_SP 0x18 /* DMA: Send Packet */
|
||||
# define CR_DM_ABORT 0x20 /* DMA: Abort Remote DMA Operation */
|
||||
#define CR_PS 0xC0 /* Mask for Page Select */
|
||||
# define CR_PS_P0 0x00 /* Register Page 0 */
|
||||
# define CR_PS_P1 0x40 /* Register Page 1 */
|
||||
# define CR_PS_T0 0x80 /* Test Mode Register Map ?? */
|
||||
# define CR_SP_T1 0xC0 /* Test Mode Register Map ?? */
|
||||
|
||||
/* Bits in dp_isr */
|
||||
|
||||
#define ISR_PRX 0x01 /* Packet Received with no errors */
|
||||
#define ISR_PTX 0x02 /* Packet Transmitted with no errors */
|
||||
#define ISR_RXE 0x04 /* Receive Error */
|
||||
#define ISR_TXE 0x08 /* Transmit Error */
|
||||
#define ISR_OVW 0x10 /* Overwrite Warning */
|
||||
#define ISR_CNT 0x20 /* Counter Overflow */
|
||||
#define ISR_RDC 0x40 /* Remote DMA Complete */
|
||||
#define ISR_RST 0x80 /* Reset Status */
|
||||
|
||||
/* Bits in dp_imr */
|
||||
|
||||
#define IMR_PRXE 0x01 /* Packet Received iEnable */
|
||||
#define IMR_PTXE 0x02 /* Packet Transmitted iEnable */
|
||||
#define IMR_RXEE 0x04 /* Receive Error iEnable */
|
||||
#define IMR_TXEE 0x08 /* Transmit Error iEnable */
|
||||
#define IMR_OVWE 0x10 /* Overwrite Warning iEnable */
|
||||
#define IMR_CNTE 0x20 /* Counter Overflow iEnable */
|
||||
#define IMR_RDCE 0x40 /* DMA Complete iEnable */
|
||||
|
||||
/* Bits in dp_dcr */
|
||||
|
||||
#define DCR_WTS 0x01 /* Word Transfer Select */
|
||||
# define DCR_BYTEWIDE 0x00 /* WTS: byte wide transfers */
|
||||
# define DCR_WORDWIDE 0x01 /* WTS: word wide transfers */
|
||||
#define DCR_BOS 0x02 /* Byte Order Select */
|
||||
# define DCR_LTLENDIAN 0x00 /* BOS: Little Endian */
|
||||
# define DCR_BIGENDIAN 0x02 /* BOS: Big Endian */
|
||||
#define DCR_LAS 0x04 /* Long Address Select */
|
||||
#define DCR_BMS 0x08 /* Burst Mode Select */
|
||||
#define DCR_AR 0x10 /* Autoinitialize Remote */
|
||||
#define DCR_FTS 0x60 /* Fifo Threshold Select */
|
||||
# define DCR_2BYTES 0x00 /* 2 bytes */
|
||||
# define DCR_4BYTES 0x40 /* 4 bytes */
|
||||
# define DCR_8BYTES 0x20 /* 8 bytes */
|
||||
# define DCR_12BYTES 0x60 /* 12 bytes */
|
||||
|
||||
/* Bits in dp_tcr */
|
||||
|
||||
#define TCR_CRC 0x01 /* Inhibit CRC */
|
||||
#define TCR_ELC 0x06 /* Encoded Loopback Control */
|
||||
# define TCR_NORMAL 0x00 /* ELC: Normal Operation */
|
||||
# define TCR_INTERNAL 0x02 /* ELC: Internal Loopback */
|
||||
# define TCR_0EXTERNAL 0x04 /* ELC: External Loopback LPBK=0 */
|
||||
# define TCR_1EXTERNAL 0x06 /* ELC: External Loopback LPBK=1 */
|
||||
#define TCR_ATD 0x08 /* Auto Transmit */
|
||||
#define TCR_OFST 0x10 /* Collision Offset Enable (be nice) */
|
||||
|
||||
/* Bits in dp_tsr */
|
||||
|
||||
#define TSR_PTX 0x01 /* Packet Transmitted (without error)*/
|
||||
#define TSR_DFR 0x02 /* Transmit Deferred */
|
||||
#define TSR_COL 0x04 /* Transmit Collided */
|
||||
#define TSR_ABT 0x08 /* Transmit Aborted */
|
||||
#define TSR_CRS 0x10 /* Carrier Sense Lost */
|
||||
#define TSR_FU 0x20 /* Fifo Underrun */
|
||||
#define TSR_CDH 0x40 /* CD Heartbeat */
|
||||
#define TSR_OWC 0x80 /* Out of Window Collision */
|
||||
|
||||
/* Bits in tp_rcr */
|
||||
|
||||
#define RCR_SEP 0x01 /* Save Errored Packets */
|
||||
#define RCR_AR 0x02 /* Accept Runt Packets */
|
||||
#define RCR_AB 0x04 /* Accept Broadcast */
|
||||
#define RCR_AM 0x08 /* Accept Multicast */
|
||||
#define RCR_PRO 0x10 /* Physical Promiscuous */
|
||||
#define RCR_MON 0x20 /* Monitor Mode */
|
||||
|
||||
/* Bits in dp_rsr */
|
||||
|
||||
#define RSR_PRX 0x01 /* Packet Received Intact */
|
||||
#define RSR_CRC 0x02 /* CRC Error */
|
||||
#define RSR_FAE 0x04 /* Frame Alignment Error */
|
||||
#define RSR_FO 0x08 /* FIFO Overrun */
|
||||
#define RSR_MPA 0x10 /* Missed Packet */
|
||||
#define RSR_PHY 0x20 /* Multicast Address Match !! */
|
||||
#define RSR_DIS 0x40 /* Receiver Disabled */
|
||||
|
||||
|
||||
struct rcvdheader {
|
||||
char rp_status; /* Copy of rsr */
|
||||
char rp_next; /* Pointer to next packet */
|
||||
char rp_rbcl; /* Receive Byte Count Low */
|
||||
char rp_rbch; /* Receive Byte Count High */
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* parameters for driver for
|
||||
* National Semiconductor DP8390 Network Interface Controller
|
||||
*/
|
||||
|
||||
extern
|
||||
struct dp8390info {
|
||||
vir_bytes dpi_devaddr; /* device address */
|
||||
char dpi_pstart; /* start of recv ring */
|
||||
char dpi_pstop; /* end of recv ring */
|
||||
phys_bytes dpi_membase; /* memory address of page 0 */
|
||||
phys_bytes dpi_tbuf; /* memory address of transmit buffer */
|
||||
} dp8390info;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifdef DPSTAT
|
||||
/* statistics from dp8390 */
|
||||
struct dpstat {
|
||||
long ds_read; /* packets read */
|
||||
long ds_written; /* packets written */
|
||||
long ds_fram; /* Input framing errors */
|
||||
long ds_crc; /* Input CRC errors */
|
||||
long ds_lost; /* Packets lost */
|
||||
long ds_btint; /* Bogus transmit interrupts */
|
||||
long ds_deferred; /* Deferred packets */
|
||||
long ds_collisions; /* Packets collided at least once */
|
||||
long ds_xcollisions; /* Aborts due to excessive collisions */
|
||||
long ds_carlost; /* Carrier sense lost */
|
||||
long ds_fifo; /* Fifo underrun */
|
||||
long ds_heartbeat; /* Heart beat failure */
|
||||
long ds_lcol; /* Late collisions */
|
||||
};
|
||||
#define STINC(x) dpstat.x++
|
||||
#define STADD(x,y) dpstat.x += y
|
||||
#else
|
||||
#define STINC(x) /* nothing */
|
||||
#define STADD(x,y) /* nothing */
|
||||
#endif DPSTAT
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* parameters for initialisation of
|
||||
* Western Digital Ethercard Plus, or WD8003E
|
||||
*/
|
||||
|
||||
extern
|
||||
struct eplinfo {
|
||||
vir_bytes epi_devaddr; /* device address */
|
||||
} eplinfo;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Format of packets on the Ethernet */
|
||||
|
||||
#define AMOEBAPROTO 0x8145 /* Official Ethernet protocol number */
|
||||
#define ALTAMOEBAPROTO 2222 /* Old Amoeba protocol number */
|
||||
#define ETHERBITS 0x80 /* These addresses on Ethernet */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char e[6];
|
||||
} Eth_addr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Eth_addr f_dstaddr;
|
||||
Eth_addr f_srcaddr;
|
||||
unshort f_proto;
|
||||
struct pktheader f_ah;
|
||||
} Framehdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Framehdr ep_fr;
|
||||
char ep_data[1490];
|
||||
} Etherpacket;
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "kernel.h"
|
||||
#include "minix/com.h"
|
||||
#include "dp8390.h"
|
||||
#include "internet.h"
|
||||
#include "etherformat.h"
|
||||
#include "etherplus.h"
|
||||
#include "dp8390info.h"
|
||||
#include "eplinfo.h"
|
||||
#include "assert.h"
|
||||
|
||||
/* macros for device I/O */
|
||||
|
||||
#define input(devaddr, ep_register) \
|
||||
in_byte((vir_bytes)&((struct eplusreg *) devaddr)->ep_register)
|
||||
#define output(devaddr, ep_register, value) \
|
||||
out_byte((vir_bytes)&((struct eplusreg *) devaddr)->ep_register, value)
|
||||
|
||||
epl_init() {
|
||||
register vir_bytes device;
|
||||
register sum;
|
||||
|
||||
device = eplinfo.epi_devaddr;
|
||||
assert((dp8390info.dpi_membase&0x81FFF)==0x80000);
|
||||
sum =
|
||||
input(device, epl_ea5) +
|
||||
input(device, epl_ea4) +
|
||||
input(device, epl_ea3) +
|
||||
input(device, epl_ea2) +
|
||||
input(device, epl_ea1) +
|
||||
input(device, epl_ea0) +
|
||||
input(device, epl_res2) +
|
||||
input(device, epl_chksum);
|
||||
if ((sum&0xFF) != 0xFF)
|
||||
panic("No ethernet board", NO_NUM);
|
||||
output(device, epl_ctlstatus, CTL_RESET);
|
||||
output(device, epl_ctlstatus, CTL_MENABLE|((dp8390info.dpi_membase>>13)&CTL_MEMADDR));
|
||||
}
|
||||
|
||||
|
||||
etheraddr(eaddr) Eth_addr *eaddr; {
|
||||
register vir_bytes device;
|
||||
|
||||
device = eplinfo.epi_devaddr;
|
||||
eaddr->e[0] = input(device, epl_ea0);
|
||||
eaddr->e[1] = input(device, epl_ea1);
|
||||
eaddr->e[2] = input(device, epl_ea2);
|
||||
eaddr->e[3] = input(device, epl_ea3);
|
||||
eaddr->e[4] = input(device, epl_ea4);
|
||||
eaddr->e[5] = input(device, epl_ea5);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Western Digital Ethercard Plus, or WD8003E card
|
||||
*
|
||||
* This information seems to be guarded like the crown jewels
|
||||
*/
|
||||
|
||||
struct eplusreg {
|
||||
char epl_ctlstatus; /* Control(write) and status(read) */
|
||||
char epl_res1[7];
|
||||
char epl_ea0; /* Most significant eaddr byte */
|
||||
char epl_ea1;
|
||||
char epl_ea2;
|
||||
char epl_ea3;
|
||||
char epl_ea4;
|
||||
char epl_ea5; /* Least significant eaddr byte */
|
||||
char epl_res2;
|
||||
char epl_chksum; /* sum from epl_ea0 upto here is 0xFF */
|
||||
dp8390 epl_dp8390; /* NatSemi chip */
|
||||
};
|
||||
|
||||
/* Bits in epl_ctlstatus */
|
||||
|
||||
#define CTL_RESET 0x80 /* Software Reset */
|
||||
#define CTL_MENABLE 0x40 /* Memory Enable */
|
||||
#define CTL_MEMADDR 0x3F /* Bits SA18-SA13, SA19 implicit 1 */
|
||||
|
||||
#define STA_IIJ 0x7 /* Interrupt Indication Jumpers */
|
||||
@@ -0,0 +1 @@
|
||||
#define CRASH ((unshort) 0xFF)
|
||||
@@ -0,0 +1,44 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
|
||||
/* */
|
||||
/* This product is part of the Amoeba distributed operating system. */
|
||||
/* */
|
||||
/* Permission to use, sell, duplicate or disclose this software must be */
|
||||
/* obtained in writing. Requests for such permissions may be sent to */
|
||||
/* */
|
||||
/* */
|
||||
/* Dr. Andrew S. Tanenbaum */
|
||||
/* Dept. of Mathematics and Computer Science */
|
||||
/* Vrije Universiteit */
|
||||
/* Postbus 7161 */
|
||||
/* 1007 MC Amsterdam */
|
||||
/* The Netherlands */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#define KERNEL 0
|
||||
#define USER 1
|
||||
|
||||
typedef unshort address;
|
||||
typedef int func;
|
||||
|
||||
#define bufptr vir_bytes
|
||||
|
||||
#define NOWHERE ((address) 0)
|
||||
#define SOMEWHERE ((address) -1)
|
||||
#define NILVECTOR ((func (*)()) 0)
|
||||
|
||||
#ifdef lint
|
||||
#define ABSPTR(t, c) (use(c), (t) 0)
|
||||
#else
|
||||
#define ABSPTR(t, c) ((t) (c))
|
||||
#endif
|
||||
|
||||
#define bit(b) (1 << (b)) /* simulate type 'bit' */
|
||||
|
||||
#define lobyte(x) ((unshort) (x) & 0xFF)
|
||||
#define hibyte(x) ((unshort) (x) >> 8)
|
||||
#define concat(x, y) ((unshort) (x) << 8 | (unshort) (y) & 0xFF)
|
||||
|
||||
#define sizeoftable(t) (sizeof(t) / sizeof((t)[0]))
|
||||
@@ -0,0 +1,63 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
|
||||
/* */
|
||||
/* This product is part of the Amoeba distributed operating system. */
|
||||
/* */
|
||||
/* Permission to use, sell, duplicate or disclose this software must be */
|
||||
/* obtained in writing. Requests for such permissions may be sent to */
|
||||
/* */
|
||||
/* */
|
||||
/* Dr. Andrew S. Tanenbaum */
|
||||
/* Dept. of Mathematics and Computer Science */
|
||||
/* Vrije Universiteit */
|
||||
/* Postbus 7161 */
|
||||
/* 1007 MC Amsterdam */
|
||||
/* The Netherlands */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#define PACKETSIZE 1490 /* network packet size - sizeof(framehdr) */
|
||||
|
||||
#define BROADCAST ((address) 0xFF)
|
||||
|
||||
#define TYPE 0x0F /* message types */
|
||||
#define LOCATE 0x01
|
||||
#define HERE 0x02
|
||||
#define REQUEST 0x03
|
||||
#define REPLY 0x04
|
||||
#define ACK 0x05
|
||||
#define NAK 0x06
|
||||
#define ENQUIRY 0x07
|
||||
#define ALIVE 0x08
|
||||
#define DEAD 0x09
|
||||
|
||||
#define LAST 0x10 /* flags */
|
||||
#define RETRANS 0x20
|
||||
|
||||
struct pktheader {
|
||||
char ph_dstnode; /* 0: destination node */
|
||||
char ph_srcnode; /* 1: source node */
|
||||
char ph_dsttask; /* 2: destination task */
|
||||
char ph_srctask; /* 3: source task */
|
||||
char ph_ident; /* 4: transaction identifier */
|
||||
char ph_seq; /* 5: fragment no. */
|
||||
unshort ph_size; /* 6: total size of this packet */
|
||||
char ph_flags; /* 8: some flags (not used) */
|
||||
char ph_type; /* 9: locate, here, data, ack or nak (!= 0) */
|
||||
};
|
||||
|
||||
#define ph_signal ph_seq
|
||||
|
||||
#define NOSEND 0
|
||||
#define SEND 1
|
||||
|
||||
#define DONTKNOW 0
|
||||
#define LOCAL 1
|
||||
#define GLOBAL 2
|
||||
|
||||
#define siteaddr(x) lobyte(x)
|
||||
#define tasknum(x) hibyte(x)
|
||||
|
||||
#define pktfrom(ph) ((unshort) (ph->ph_srctask<<8 | ph->ph_srcnode & 0xFF))
|
||||
#define pktto(ph) ((unshort) (ph->ph_dsttask<<8 | ph->ph_dstnode & 0xFF))
|
||||
43
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/mpx.H
Normal file
43
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/mpx.H
Normal file
@@ -0,0 +1,43 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
|
||||
/* */
|
||||
/* This product is part of the Amoeba distributed operating system. */
|
||||
/* */
|
||||
/* Permission to use, sell, duplicate or disclose this software must be */
|
||||
/* obtained in writing. Requests for such permissions may be sent to */
|
||||
/* */
|
||||
/* */
|
||||
/* Dr. Andrew S. Tanenbaum */
|
||||
/* Dept. of Mathematics and Computer Science */
|
||||
/* Vrije Universiteit */
|
||||
/* Postbus 7161 */
|
||||
/* 1007 MC Amsterdam */
|
||||
/* The Netherlands */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct mpx {
|
||||
short MX_active; /* is a transaction in progress */
|
||||
unshort MX_flags; /* flags - see below */
|
||||
int MX_proc_nr; /* task identifier */
|
||||
header MX_hdr; /* storage space for header */
|
||||
} tk_mpx;
|
||||
|
||||
#ifdef MPX
|
||||
|
||||
#define mx_flags tk_mpx.MX_flags
|
||||
#define mx_active tk_mpx.MX_active
|
||||
#define mx_proc_nr tk_mpx.MX_proc_nr
|
||||
#define mx_hdr tk_mpx.MX_hdr
|
||||
|
||||
|
||||
/* bits in flags: */
|
||||
#define RUNNABLE bit(0) /* task is runnable */
|
||||
#define NESTED bit(1) /* nested getreq, trans or putrep */
|
||||
#define BETWEEN bit(2) /* between getreq and putrep */
|
||||
#else
|
||||
|
||||
#define tk_mpx tk_dummy /* other modules must not touch it */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
|
||||
/* */
|
||||
/* This product is part of the Amoeba distributed operating system. */
|
||||
/* */
|
||||
/* Permission to use, sell, duplicate or disclose this software must be */
|
||||
/* obtained in writing. Requests for such permissions may be sent to */
|
||||
/* */
|
||||
/* */
|
||||
/* Dr. Andrew S. Tanenbaum */
|
||||
/* Dept. of Mathematics and Computer Science */
|
||||
/* Vrije Universiteit */
|
||||
/* Postbus 7161 */
|
||||
/* 1007 MC Amsterdam */
|
||||
/* The Netherlands */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct portcache {
|
||||
address PE_location;
|
||||
struct task *PE_link;
|
||||
} tk_portcache;
|
||||
|
||||
#ifdef PORTCACHE
|
||||
|
||||
#define pe_location tk_portcache.PE_location
|
||||
#define pe_link tk_portcache.PE_link
|
||||
|
||||
#else
|
||||
|
||||
#define tk_portcache tk_dummy /* other modules must not touch it */
|
||||
|
||||
#endif
|
||||
|
||||
#define NOWAIT 0
|
||||
#define WAIT 1
|
||||
|
||||
#define LOOK 0
|
||||
#define DELETE 1
|
||||
@@ -0,0 +1,492 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
|
||||
/* */
|
||||
/* This product is part of the Amoeba distributed operating system. */
|
||||
/* */
|
||||
/* Permission to use, sell, duplicate or disclose this software must be */
|
||||
/* obtained in writing. Requests for such permissions may be sent to */
|
||||
/* */
|
||||
/* */
|
||||
/* Dr. Andrew S. Tanenbaum */
|
||||
/* Dept. of Mathematics and Computer Science */
|
||||
/* Vrije Universiteit */
|
||||
/* Postbus 7161 */
|
||||
/* 1007 MC Amsterdam */
|
||||
/* The Netherlands */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#define NDEBUG
|
||||
#define PORTCACHE
|
||||
|
||||
/*
|
||||
* This module does the port management. It keeps track of the local servers
|
||||
* doing a ``getreq'' on a port, local clients waiting for a server on some
|
||||
* port, and interlocal servers addressed by some port. This last category of
|
||||
* ports may be forgotten, or may be incorrect.
|
||||
*
|
||||
* The following routines are defined:
|
||||
* portinstall(port, where, wait);
|
||||
* portlookup(port, wait, delete);
|
||||
* portremove(port, location);
|
||||
* portquit(port, task);
|
||||
*
|
||||
* ``Portinstall'' is called when a port is assumed to be at location
|
||||
* ``where.'' If ``wait'' is set, the port is local.
|
||||
* ``Portlookup'' is called to find a port in the cache. If ``wait'' is
|
||||
* set, the routine will block until the port is found. If ``delete'' is
|
||||
* set, the port must be removed when it is found.
|
||||
* ``Portremove'' removes a port from the cache which is thought
|
||||
* of to be at the specified location.
|
||||
* When a port doesn't have to be located anymore for some task, ``portquit''
|
||||
* takes care of that.
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
#include "amoeba.h"
|
||||
#include "global.h"
|
||||
#include "task.h"
|
||||
#include "internet.h"
|
||||
#include "assert.h"
|
||||
|
||||
extern struct task task[];
|
||||
|
||||
#ifdef STATISTICS
|
||||
#include "portstat.h"
|
||||
|
||||
struct portstat portstat;
|
||||
#define STINC(x) portstat.x++
|
||||
#else
|
||||
#define STINC(x)
|
||||
#endif
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
#define LOGHASH 5 /* log sizeof hash table of local ports */
|
||||
|
||||
struct porttab {
|
||||
port p_port; /* the port this entry is about */
|
||||
unshort p_idle; /* idle timer */
|
||||
address p_location; /* where is it? (0 = being located) */
|
||||
address p_asker; /* address of someone interested */
|
||||
struct porttab *p_nextport; /* port with same hash value */
|
||||
struct task *p_tasklist; /* list of tasks */
|
||||
};
|
||||
|
||||
#define NILPORTTAB ((struct porttab *) 0)
|
||||
|
||||
#define NHASH (1 << LOGHASH)
|
||||
#define HASHMASK (NHASH - 1)
|
||||
|
||||
#define hash(p) (* (unshort *) (p) & HASHMASK)
|
||||
|
||||
/* MINIX can't allocate memory in the kernel at run-time
|
||||
extern unshort nport;
|
||||
PRIVATE struct porttab *porttab, *lastport, *hashtab[NHASH], *portfree;
|
||||
*/
|
||||
PRIVATE struct porttab porttab[NPORTS];
|
||||
PRIVATE struct porttab *lastport, *hashtab[NHASH], *portfree;
|
||||
|
||||
#ifndef NONET
|
||||
#ifndef NOCLIENT
|
||||
|
||||
#define NLOCATE 8 /* max. number of ports to locate */
|
||||
PRIVATE port loctab[NLOCATE];
|
||||
PRIVATE unshort loccnt, loctim, locthissweep;
|
||||
extern unshort minloccnt, maxloccnt;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Allocate an entry in the hash table at location ``ht.'' */
|
||||
static struct porttab *allocate(ht, p)
|
||||
struct porttab **ht;
|
||||
port *p;
|
||||
{
|
||||
register struct porttab *pt;
|
||||
STINC(pts_alloc);
|
||||
if ((pt=portfree) == 0) {
|
||||
STINC(pts_full);
|
||||
portpurge(); /* total cleanup, not likely to happen */
|
||||
if ((pt=portfree) == 0)
|
||||
return 0;
|
||||
}
|
||||
portfree = pt->p_nextport;
|
||||
pt->p_nextport = *ht;
|
||||
*ht = pt;
|
||||
pt->p_port = *p;
|
||||
return pt;
|
||||
}
|
||||
|
||||
/* Install a port in the hash table. If ``wait'' is set, the location will
|
||||
* be this machine and is certain. If not, the location is somewhere else
|
||||
* and uncertain.
|
||||
*/
|
||||
portinstall(p, where, wait)
|
||||
register port *p;
|
||||
address where;
|
||||
{
|
||||
register struct porttab **ht, *pt;
|
||||
register struct task *t;
|
||||
extern address local;
|
||||
|
||||
ht = &hashtab[hash(p)];
|
||||
for (pt = *ht; pt != NILPORTTAB; pt = pt->p_nextport)
|
||||
if (PortCmp(&pt->p_port, p)) {
|
||||
if (pt->p_location == SOMEWHERE) {
|
||||
compare(pt->p_tasklist, !=, NILTASK);
|
||||
do {
|
||||
t = pt->p_tasklist;
|
||||
t->pe_location = where;
|
||||
STINC(pts_wakeup);
|
||||
wakeup((event_t) &t->pe_location);
|
||||
} while ((pt->p_tasklist = t->pe_link) != NILTASK);
|
||||
}
|
||||
#ifndef NOCLIENT
|
||||
else if (siteaddr(pt->p_location) == local && !wait &&
|
||||
pt->p_tasklist != 0)
|
||||
return;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (pt == NILPORTTAB && (pt = allocate(ht, p)) == NILPORTTAB)
|
||||
#ifndef NOCLIENT
|
||||
if (wait)
|
||||
#endif
|
||||
panic("portcache full for servers", 0x8000);
|
||||
#ifndef NOCLIENT
|
||||
else /* no room left, so forget it */
|
||||
return;
|
||||
#endif
|
||||
pt->p_location = where;
|
||||
#ifndef NOCLIENT
|
||||
if (wait) { /* task is going to await a client, so leave it immortal */
|
||||
#endif
|
||||
compare(area(where), ==, LOCAL);
|
||||
t = &task[tasknum(where)];
|
||||
t->pe_location = where;
|
||||
t->pe_link = pt->p_tasklist;
|
||||
pt->p_tasklist = t;
|
||||
#ifndef NONET
|
||||
if (pt->p_asker != NOWHERE) {
|
||||
STINC(pts_here);
|
||||
hereport(pt->p_asker, p, (unsigned )1);
|
||||
pt->p_asker = NOWHERE;
|
||||
}
|
||||
#endif
|
||||
#ifndef NOCLIENT
|
||||
}
|
||||
#endif
|
||||
pt->p_idle = 0;
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
#ifndef NOCLIENT
|
||||
/* Broadcast a locate message
|
||||
*/
|
||||
static sendloc(){
|
||||
register struct porttab *pt;
|
||||
register unsigned n = 0;
|
||||
|
||||
if (locthissweep) {
|
||||
/* During this clocktick we already sent out a broadcast packet.
|
||||
* To prevent buggy userprograms from creating a broadcast storm
|
||||
* we do not send another one, we just prepare for it to be done
|
||||
*/
|
||||
STINC(pts_nolocate);
|
||||
loccnt = maxloccnt;
|
||||
return;
|
||||
}
|
||||
for (pt = porttab; pt < lastport; pt++)
|
||||
if (pt->p_location == SOMEWHERE) {
|
||||
loctab[n++] = pt->p_port;
|
||||
if (n == NLOCATE)
|
||||
break;
|
||||
}
|
||||
if (n) {
|
||||
locthissweep = 1;
|
||||
whereport(loctab, n); /* send out the broadcast locate */
|
||||
} else
|
||||
loctim = 0; /* No locates necessary anymore */
|
||||
loccnt = 0;
|
||||
}
|
||||
|
||||
#endif NOCLIENT
|
||||
#endif NONET
|
||||
|
||||
/* Look whether port p is in the portcache. You can specify whether you
|
||||
* want to wait for the information and whether you want to delete it.
|
||||
*/
|
||||
address portlookup(p, wait, del)
|
||||
register port *p;
|
||||
{
|
||||
register struct porttab **ht, *pt;
|
||||
register struct task *c, *t;
|
||||
register address location;
|
||||
|
||||
STINC(pts_lookup);
|
||||
ht = &hashtab[hash(p)];
|
||||
for (pt = *ht; pt != NILPORTTAB; pt = pt->p_nextport)
|
||||
if (PortCmp(&pt->p_port, p)) { /* found it */
|
||||
location = pt->p_location;
|
||||
switch (area(location)) {
|
||||
case LOCAL: /* local server */
|
||||
if (pt->p_tasklist == 0)
|
||||
break;
|
||||
if (del) { /* remove it */
|
||||
pt->p_tasklist = pt->p_tasklist->pe_link;
|
||||
if ((t = pt->p_tasklist) != NILTASK)
|
||||
pt->p_location = t->pe_location;
|
||||
}
|
||||
pt->p_idle = 0;
|
||||
STINC(pts_flocal);
|
||||
return(location);
|
||||
|
||||
case GLOBAL: /* remote server */
|
||||
compare(pt->p_tasklist, ==, NILTASK);
|
||||
pt->p_idle = 0;
|
||||
STINC(pts_fglobal);
|
||||
return(location);
|
||||
|
||||
case DONTKNOW: /* somebody else wants to know too */
|
||||
compare(pt->p_tasklist, !=, NILTASK);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* The port wasn't in the port cache */
|
||||
#ifndef NOCLIENT
|
||||
if (wait) { /* wait for it */
|
||||
if (pt == NILPORTTAB && (pt = allocate(ht, p)) == NILPORTTAB)
|
||||
panic("portcache full for clients", 0x8000);
|
||||
pt->p_location = SOMEWHERE;
|
||||
c = curtask;
|
||||
c->pe_link = pt->p_tasklist;
|
||||
pt->p_tasklist = c;
|
||||
#ifndef NONET
|
||||
STINC(pts_locate);
|
||||
sendloc();
|
||||
loctim = minloccnt;
|
||||
#endif
|
||||
c->pe_location = SOMEWHERE;
|
||||
if (sleep((event_t) &c->pe_location))
|
||||
assert(pt->p_tasklist != c);
|
||||
pt->p_idle = 0;
|
||||
return(c->pe_location);
|
||||
}
|
||||
else
|
||||
#endif NOCLIENT
|
||||
return(NOWHERE);
|
||||
}
|
||||
|
||||
/* Port p isn't at location ``location'' anymore */
|
||||
portremove(p, location)
|
||||
port *p;
|
||||
address location;
|
||||
{
|
||||
register struct porttab *pt, **ht;
|
||||
register struct task *t;
|
||||
|
||||
for (ht = &hashtab[hash(p)]; (pt= *ht) != NILPORTTAB; ht = &pt->p_nextport)
|
||||
if (PortCmp(&pt->p_port, p)) {
|
||||
if (pt->p_location == location) {
|
||||
if ((t = pt->p_tasklist) != NILTASK) {
|
||||
compare(area(location), ==, LOCAL);
|
||||
compare(t->pe_location, ==, location);
|
||||
if ((pt->p_tasklist = t->pe_link) != NILTASK) {
|
||||
pt->p_location =
|
||||
pt->p_tasklist->pe_location;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*ht = pt->p_nextport;
|
||||
pt->p_location = NOWHERE; /* for dump */
|
||||
pt->p_nextport = portfree;
|
||||
portfree = pt;
|
||||
}
|
||||
}
|
||||
else if ((t = pt->p_tasklist) != NILTASK)
|
||||
while (t->pe_link != NILTASK)
|
||||
if (t->pe_link->pe_location == location) {
|
||||
t->pe_link = t->pe_link->pe_link;
|
||||
break;
|
||||
}
|
||||
else
|
||||
t = t->pe_link;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NOCLIENT
|
||||
/* Task ``s'' isn't interested anymore */
|
||||
portquit(p, s)
|
||||
register port *p;
|
||||
register struct task *s;
|
||||
{
|
||||
register struct porttab *pt, **ht;
|
||||
register struct task *t;
|
||||
|
||||
for (ht = &hashtab[hash(p)]; (pt= *ht) != NILPORTTAB; ht = &pt->p_nextport)
|
||||
if (PortCmp(&pt->p_port, p)) {
|
||||
if (pt->p_location != SOMEWHERE)
|
||||
return;
|
||||
if ((t = pt->p_tasklist) == s) {
|
||||
if ((pt->p_tasklist = s->pe_link) == NILTASK) {
|
||||
*ht = pt->p_nextport;
|
||||
pt->p_location = NOWHERE; /* for dump */
|
||||
pt->p_nextport = portfree;
|
||||
portfree = pt;
|
||||
}
|
||||
s->pe_location = NOWHERE;
|
||||
wakeup((event_t) &s->pe_location);
|
||||
}
|
||||
else {
|
||||
while (t != NILTASK)
|
||||
if (t->pe_link == s) {
|
||||
t->pe_link = s->pe_link;
|
||||
s->pe_location = NOWHERE;
|
||||
wakeup((event_t) &s->pe_location);
|
||||
break;
|
||||
}
|
||||
else
|
||||
t = t->pe_link;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif NOCLIENT
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
#define NHERE 8
|
||||
PRIVATE port heretab[NHERE];
|
||||
|
||||
portask(asker, ptab, nports) /* handle locate request */
|
||||
address asker;
|
||||
register port *ptab;
|
||||
unsigned nports;
|
||||
{
|
||||
register port *p,*q;
|
||||
register struct porttab **ht, *pt;
|
||||
register unsigned nfound;
|
||||
|
||||
STINC(pts_portask);
|
||||
nfound = 0; q = heretab;
|
||||
for(p=ptab; nports--; p++) {
|
||||
ht = &hashtab[hash(p)];
|
||||
for (pt = *ht; pt != NILPORTTAB; pt = pt->p_nextport)
|
||||
if (PortCmp(&pt->p_port, p)) { /* found it */
|
||||
if (area(pt->p_location) == LOCAL) {
|
||||
if (pt->p_tasklist == 0) {
|
||||
/* just record someone was interested */
|
||||
pt->p_asker = asker;
|
||||
break;
|
||||
}
|
||||
if (nfound < NHERE) {
|
||||
*q++ = *p;
|
||||
nfound++;
|
||||
}
|
||||
pt->p_idle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nfound) {
|
||||
STINC(pts_portyes);
|
||||
hereport(asker, heretab, nfound);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
portdump(){
|
||||
register struct porttab *pt;
|
||||
register struct task *t;
|
||||
|
||||
printf("\n PORT LOCATION IDLE TASKS\n");
|
||||
for (pt = porttab; pt < lastport; pt++)
|
||||
if (pt->p_location != NOWHERE) {
|
||||
prport(&pt->p_port);
|
||||
printf(" %4x %4d", pt->p_location, pt->p_idle);
|
||||
for (t = pt->p_tasklist; t != NILTASK; t = t->pe_link)
|
||||
printf(" {%d, %x}", t - task, t->pe_location);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize tables and free list */
|
||||
portinit(){
|
||||
register struct porttab *pt;
|
||||
|
||||
/* MINIX can't allocate data in the kernel at run-time
|
||||
extern char *aalloc();
|
||||
|
||||
porttab = (struct porttab *) aalloc(nport * sizeof(struct porttab), 0);
|
||||
lastport = &porttab[nport];
|
||||
*/
|
||||
lastport = &porttab[NPORTS];
|
||||
for (pt = porttab; pt < lastport; pt++) {
|
||||
pt->p_nextport = portfree;
|
||||
portfree = pt;
|
||||
}
|
||||
}
|
||||
|
||||
/* called when freelist was empty, will throw away all mortal ports */
|
||||
portpurge() {
|
||||
register struct porttab *pt,**ht,**htp;
|
||||
|
||||
for (htp=hashtab; htp< &hashtab[NHASH]; htp++) {
|
||||
ht = htp;
|
||||
while ((pt = *ht) != 0) {
|
||||
if (pt->p_tasklist == 0){
|
||||
*ht = pt->p_nextport;
|
||||
pt->p_location = NOWHERE; /* for dump */
|
||||
pt->p_nextport = portfree;
|
||||
portfree = pt;
|
||||
} else
|
||||
ht = &pt->p_nextport;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MAXSWEEP 3000 /* dseconds maximum idle time for port */
|
||||
#define SWEEPRESOLUTION 100 /* accuracy */
|
||||
|
||||
portsweep() {
|
||||
register struct porttab *pt,**ht,**htp;
|
||||
static unshort cnt;
|
||||
|
||||
#ifndef NOCLIENT
|
||||
#ifndef NONET
|
||||
locthissweep = 0;
|
||||
if (loctim && ++loccnt > loctim) { /* send a locate message */
|
||||
STINC(pts_relocate);
|
||||
sendloc();
|
||||
loctim <<= 1;
|
||||
if (loctim > maxloccnt)
|
||||
loctim = maxloccnt;
|
||||
locthissweep = 0;
|
||||
}
|
||||
#endif NONET
|
||||
#endif
|
||||
if (++cnt<SWEEPRESOLUTION)
|
||||
return;
|
||||
for (htp=hashtab; htp< &hashtab[NHASH]; htp++) {
|
||||
ht = htp;
|
||||
while ((pt = *ht) != 0) {
|
||||
if (pt->p_tasklist == 0 && (pt->p_idle += cnt) > MAXSWEEP) {
|
||||
*ht = pt->p_nextport;
|
||||
pt->p_location = NOWHERE; /* for dump */
|
||||
pt->p_nextport = portfree;
|
||||
portfree = pt;
|
||||
STINC(pts_aged);
|
||||
} else
|
||||
ht = &pt->p_nextport;
|
||||
}
|
||||
}
|
||||
cnt=0;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
struct portstat {
|
||||
long pts_alloc;
|
||||
long pts_aged;
|
||||
long pts_full;
|
||||
long pts_wakeup;
|
||||
long pts_here;
|
||||
long pts_lookup;
|
||||
long pts_flocal;
|
||||
long pts_fglobal;
|
||||
long pts_portask;
|
||||
long pts_portyes;
|
||||
long pts_locate;
|
||||
long pts_nolocate;
|
||||
long pts_relocate;
|
||||
};
|
||||
40
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/task.h
Normal file
40
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/task.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
|
||||
/* */
|
||||
/* This product is part of the Amoeba distributed operating system. */
|
||||
/* */
|
||||
/* Permission to use, sell, duplicate or disclose this software must be */
|
||||
/* obtained in writing. Requests for such permissions may be sent to */
|
||||
/* */
|
||||
/* */
|
||||
/* Dr. Andrew S. Tanenbaum */
|
||||
/* Dept. of Mathematics and Computer Science */
|
||||
/* Vrije Universiteit */
|
||||
/* Postbus 7161 */
|
||||
/* 1007 MC Amsterdam */
|
||||
/* The Netherlands */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef BUFFERED /* HACK */
|
||||
#define BUFSIZE 100
|
||||
#define NETBUF ((buffer) -1)
|
||||
|
||||
typedef unshort buffer;
|
||||
#endif
|
||||
|
||||
struct task {
|
||||
|
||||
#include "mpx.H" /* mpx module */
|
||||
#include "trans.H" /* trans module */
|
||||
#include "portcache.H" /* portcache module */
|
||||
char *tk_aux; /* auxiliary pointer */
|
||||
/* really a hack to make process task more efficient */
|
||||
|
||||
};
|
||||
|
||||
extern struct task *curtask, *uppertask;
|
||||
extern unshort ntask;
|
||||
|
||||
#define NILTASK ((struct task *) 0)
|
||||
110
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/trans.H
Normal file
110
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/trans.H
Normal file
@@ -0,0 +1,110 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
|
||||
/* */
|
||||
/* This product is part of the Amoeba distributed operating system. */
|
||||
/* */
|
||||
/* Permission to use, sell, duplicate or disclose this software must be */
|
||||
/* obtained in writing. Requests for such permissions may be sent to */
|
||||
/* */
|
||||
/* */
|
||||
/* Dr. Andrew S. Tanenbaum */
|
||||
/* Dept. of Mathematics and Computer Science */
|
||||
/* Vrije Universiteit */
|
||||
/* Postbus 7161 */
|
||||
/* 1007 MC Amsterdam */
|
||||
/* The Netherlands */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct trans {
|
||||
char TS_state; /* see below */
|
||||
char TS_flags; /* several flags - see below */
|
||||
char TS_clident; /* ident number for client */
|
||||
char TS_svident; /* ident number for server */
|
||||
char TS_ident; /* transaction identifier */
|
||||
char TS_seq; /* fragment sequence number */
|
||||
char TS_count; /* max. number timer may expire */
|
||||
char TS_signal; /* signal being sent to the server */
|
||||
unshort TS_addr; /* network address of this task */
|
||||
unshort TS_timer; /* timer, decremented every sweep */
|
||||
unshort TS_cltim; /* client crash timer */
|
||||
address TS_client; /* if serving: who's the client */
|
||||
address TS_server; /* if in trans: who's the server */
|
||||
port TS_portcache; /* this port was used the last time */
|
||||
header *TS_rhdr; /* saved param in getreq or trans */
|
||||
header *TS_xhdr; /* saved param in putrep or trans */
|
||||
bufptr TS_rbuf; /* receiver buffer */
|
||||
bufptr TS_xbuf; /* transmitter buffer */
|
||||
unshort TS_rcnt; /* size of rbuf */
|
||||
unshort TS_xcnt; /* size of xbuf */
|
||||
unshort TS_offset; /* offset in buffer */
|
||||
unshort TS_maxloc; /* max. location time in seconds */
|
||||
long TS_totloc; /* total location time in ticks */
|
||||
long TS_totsvr; /* total server time in ticks */
|
||||
#ifdef BUFFERED
|
||||
address TS_sender; /* task that sent the buffer */
|
||||
char *TS_savehdr; /* saved header pointer */
|
||||
buffer TS_buffer; /* buffer */
|
||||
unshort TS_bufcnt; /* buffer size */
|
||||
unshort TS_what; /* REQUEST or REPLY */
|
||||
#endif
|
||||
} tk_trans;
|
||||
|
||||
#ifdef TRANS
|
||||
|
||||
#define ts_state tk_trans.TS_state
|
||||
#define ts_flags tk_trans.TS_flags
|
||||
#define ts_clident tk_trans.TS_clident
|
||||
#define ts_svident tk_trans.TS_svident
|
||||
#define ts_ident tk_trans.TS_ident
|
||||
#define ts_seq tk_trans.TS_seq
|
||||
#define ts_timer tk_trans.TS_timer
|
||||
#define ts_count tk_trans.TS_count
|
||||
#define ts_signal tk_trans.TS_signal
|
||||
#define ts_addr tk_trans.TS_addr
|
||||
#define ts_cltim tk_trans.TS_cltim
|
||||
#define ts_client tk_trans.TS_client
|
||||
#define ts_server tk_trans.TS_server
|
||||
#define ts_portcache tk_trans.TS_portcache
|
||||
#define ts_rhdr tk_trans.TS_rhdr
|
||||
#define ts_xhdr tk_trans.TS_xhdr
|
||||
#define ts_rbuf tk_trans.TS_rbuf
|
||||
#define ts_xbuf tk_trans.TS_xbuf
|
||||
#define ts_rcnt tk_trans.TS_rcnt
|
||||
#define ts_xcnt tk_trans.TS_xcnt
|
||||
#define ts_offset tk_trans.TS_offset
|
||||
#define ts_maxloc tk_trans.TS_maxloc
|
||||
#define ts_totloc tk_trans.TS_totloc
|
||||
#define ts_totsvr tk_trans.TS_totsvr
|
||||
#define ts_sender tk_trans.TS_sender
|
||||
#define ts_savehdr tk_trans.TS_savehdr
|
||||
#define ts_buffer tk_trans.TS_buffer
|
||||
#define ts_bufcnt tk_trans.TS_bufcnt
|
||||
#define ts_what tk_trans.TS_what
|
||||
|
||||
/* possible values of ts_state */
|
||||
#define IDLE 0
|
||||
#define SENDING 1
|
||||
#define DONE 2
|
||||
#define ACKED 3
|
||||
#define NACKED 4
|
||||
#define FAILED 5
|
||||
#define WAITBUF 6
|
||||
#define RECEIVING 7
|
||||
#define ABORT 8
|
||||
#define MEMFAULT 9
|
||||
|
||||
/* possible flags in ts_flags */
|
||||
#define LOCATING bit(0) /* blocked in trans locating a port */
|
||||
#define PUTREQ bit(1) /* blocked in trans sending a request */
|
||||
#define GETREQ bit(2) /* blocked in getreq */
|
||||
#define PUTREP bit(3) /* blocked in putrep */
|
||||
#define GETREP bit(4) /* blocked in trans getting a reply */
|
||||
#define SERVING bit(5) /* running between getreq and putrep */
|
||||
|
||||
#else
|
||||
|
||||
#define tk_trans tk_dummy /* other modules must not touch it */
|
||||
|
||||
#endif
|
||||
BIN
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/trans.c.gz
Normal file
BIN
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/trans.c.gz
Normal file
Binary file not shown.
50
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/util.c
Normal file
50
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/kernel/util.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "kernel.h"
|
||||
#include "minix/com.h"
|
||||
#include "proc.h"
|
||||
#include "dp8390.h"
|
||||
#include "assert.h"
|
||||
#include "dp8390info.h"
|
||||
|
||||
#include "eplinfo.h"
|
||||
|
||||
|
||||
struct eplinfo eplinfo = {0x280};
|
||||
|
||||
struct dp8390info dp8390info = {0x290, 6, 27, EPLUS_BASE, EPLUS_BASE};
|
||||
|
||||
extern vir_bytes eplus_seg;
|
||||
|
||||
|
||||
#if !NONET
|
||||
getheader(paddr, pkthead)
|
||||
phys_bytes paddr;
|
||||
struct rcvdheader *pkthead;
|
||||
{
|
||||
vir_bytes offset;
|
||||
char get_byte();
|
||||
|
||||
offset = (paddr - EPLUS_BASE)&0xFFFF;
|
||||
pkthead->rp_status = get_byte(eplus_seg, offset);
|
||||
pkthead->rp_next = get_byte(eplus_seg, offset+1);
|
||||
pkthead->rp_rbcl = get_byte(eplus_seg, offset+2);
|
||||
pkthead->rp_rbch = get_byte(eplus_seg, offset+3);
|
||||
}
|
||||
|
||||
|
||||
short
|
||||
getbint(paddr)
|
||||
phys_bytes paddr;
|
||||
{
|
||||
vir_bytes offset;
|
||||
short t;
|
||||
|
||||
offset = (paddr - EPLUS_BASE)&0xFFFF;
|
||||
return (((short)get_byte(eplus_seg, offset) & 0xFF)<<8) +
|
||||
((short)get_byte(eplus_seg, offset+1) & 0xFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
106
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/mm/Makefile
Normal file
106
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/mm/Makefile
Normal file
@@ -0,0 +1,106 @@
|
||||
i=/usr/include
|
||||
s=/usr/include/sys
|
||||
h=/usr/include/minix
|
||||
l=/usr/lib
|
||||
m=../../mm
|
||||
|
||||
a=$m/mm.h $h/config.h $h/const.h $h/type.h $s/types.h $i/limits.h $i/errno.h \
|
||||
$m/const.h $m/type.h $m/proto.h $m/glo.h
|
||||
|
||||
CFLAGS = -DAM_KERNEL -I../../mm -I. -F
|
||||
|
||||
obj = main.s forkexit.s break.s exec.s signal.s getset.s \
|
||||
alloc.s utility.s table.s putc.s trace.s amoeba.s
|
||||
|
||||
mm: Makefile $l/head.s $(obj) $l/libc.a $l/end.s
|
||||
asld -o mm $l/head.s $(obj) $l/libc.a $l/end.s
|
||||
|
||||
clean:
|
||||
@rm -f $(obj) mm *.bak
|
||||
|
||||
alloc.s: $a
|
||||
$(CC) $(CFLAGS) -c $m/alloc.c
|
||||
|
||||
amoeba.s: $a
|
||||
amoeba.s: $h/com.h
|
||||
amoeba.s: $i/amoeba.h
|
||||
|
||||
break.s: $a
|
||||
break.s: $i/signal.h
|
||||
break.s: $m/mproc.h
|
||||
break.s: $m/param.h
|
||||
break.s: $m/break.c
|
||||
$(CC) $(CFLAGS) -c $m/break.c
|
||||
|
||||
exec.s: $a
|
||||
exec.s: $s/stat.h
|
||||
exec.s: $h/callnr.h
|
||||
exec.s: $m/mproc.h
|
||||
exec.s: $m/param.h
|
||||
exec.s: $m/exec.c
|
||||
$(CC) $(CFLAGS) -c $m/exec.c
|
||||
|
||||
forkexit.s: $a
|
||||
forkexit.s: $h/callnr.h
|
||||
forkexit.s: $m/mproc.h
|
||||
forkexit.s: $m/param.h
|
||||
forkexit.s: $m/forkexit.c
|
||||
$(CC) $(CFLAGS) -c $m/forkexit.c
|
||||
|
||||
getset.s: $a
|
||||
getset.s: $h/callnr.h
|
||||
getset.s: $m/mproc.h
|
||||
getset.s: $m/param.h
|
||||
getset.s: $m/getset.c
|
||||
$(CC) $(CFLAGS) -c $m/getset.c
|
||||
|
||||
main.s: $a
|
||||
main.s: $h/callnr.h
|
||||
main.s: $h/com.h
|
||||
main.s: $m/mproc.h
|
||||
main.s: $m/param.h
|
||||
main.s: $m/main.c
|
||||
$(CC) $(CFLAGS) -c $m/main.c
|
||||
|
||||
putc.s: $a
|
||||
putc.s: $h/com.h
|
||||
putc.s: $m/putc.c
|
||||
$(CC) $(CFLAGS) -c $m/putc.c
|
||||
|
||||
signal.s: $a
|
||||
signal.s: $s/stat.h
|
||||
signal.s: $i/signal.h
|
||||
signal.s: $h/callnr.h
|
||||
signal.s: $h/com.h
|
||||
signal.s: $m/mproc.h
|
||||
signal.s: $m/param.h
|
||||
signal.s: $m/signal.c
|
||||
$(CC) $(CFLAGS) -c $m/signal.c
|
||||
|
||||
table.s: $a
|
||||
table.s: $h/callnr.h
|
||||
table.s: $m/mproc.h
|
||||
table.s: $m/param.h
|
||||
table.s: $m/table.c
|
||||
$(CC) $(CFLAGS) -c $m/table.c
|
||||
|
||||
trace.s: $a
|
||||
trace.s: $i/signal.h
|
||||
trace.s: $m/mproc.h
|
||||
trace.s: $m/param.h
|
||||
trace.s: $m/trace.c
|
||||
$(CC) $(CFLAGS) -c $m/trace.c
|
||||
|
||||
utility.s: $a
|
||||
utility.s: $s/stat.h
|
||||
utility.s: $h/callnr.h
|
||||
utility.s: $h/com.h
|
||||
utility.s: $m/mproc.h
|
||||
utility.s: $m/utility.c
|
||||
$(CC) $(CFLAGS) -c $m/utility.c
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
163
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/mm/amoeba.c
Normal file
163
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/mm/amoeba.c
Normal file
@@ -0,0 +1,163 @@
|
||||
#ifdef AM_KERNEL
|
||||
/*
|
||||
** The Amoeba Transaction Layer System Call
|
||||
**
|
||||
** Amoeba transactions are implemented as a single system call
|
||||
** which implements trans(), getreq() and putrep(). timeout() is
|
||||
** implemented in the user library.
|
||||
** The job of the transaction layer is to ensure that a user task gets
|
||||
** only one kernel task. The kernel task is the exclusive domain of
|
||||
** the user task for the duration of a transaction.
|
||||
**
|
||||
** A note on programming style:
|
||||
** macros names are upper case (all of them except those from andy)
|
||||
** global variable names start with an upper case letter
|
||||
** local variables names are lower case
|
||||
**
|
||||
** The amoeba transactions use message type 2, just like the device
|
||||
** drivers. This is for compatibility with the revive code.
|
||||
*/
|
||||
|
||||
#include "mm.h"
|
||||
#include "minix/com.h"
|
||||
#include "amoeba.h"
|
||||
|
||||
/*
|
||||
** There are several external global variables which you need to know about
|
||||
** but due to the hacks everywhere they are declared in an include file.
|
||||
** who - the task # of the task that sent the request = mm_in.m_source
|
||||
** mm_in - the message from that task
|
||||
** mm_out - a message buffer normally used by reply()
|
||||
** dont_reply - a flag to indicate that no reply should go to sender
|
||||
**
|
||||
** do_amoeba returns the error status that will be given to the requesting
|
||||
** task. The kernel has already done all the data transfers for the task
|
||||
** so no return message is required.
|
||||
*/
|
||||
|
||||
|
||||
PUBLIC int
|
||||
do_amoeba()
|
||||
{
|
||||
int ktasknr; /* # of kernel task to perform operation */
|
||||
int proc_nr; /* # of user task requesting the operation */
|
||||
int r; /* return status */
|
||||
int cmd;
|
||||
|
||||
/* if it is a revive message from kernel then handle it */
|
||||
if (mm_in.AM_OP == AM_REVIVE)
|
||||
return am_revive(mm_in.AM_PROC_NR, mm_in.AM_STATUS, (int)mm_in.AM_FREE_IT);
|
||||
/*
|
||||
** check to see if this task already has a kernel task engaged.
|
||||
** if so then use that one, else find a free kernel task.
|
||||
*/
|
||||
if ((ktasknr = alloc_ktask()) >= 0)
|
||||
return TRYAGAIN; /* no free kernel task, try again? */
|
||||
proc_nr = who;
|
||||
mm_in.AM_PROC_NR = proc_nr;
|
||||
cmd = mm_in.AM_OP;
|
||||
if ((r = sendrec(ktasknr, &mm_in)) != OK)
|
||||
panic("do_amoeba: can't send", NO_NUM);
|
||||
/*
|
||||
** if necessary suspend. the kernel task will be freed during the revival.
|
||||
** otherwise we got an immediate answer.
|
||||
** in that case it was an error or an instant response. probably it
|
||||
** was an error. if so free the kernel task. if it was not an error
|
||||
** then don't free the kernel task if it was a getrequest.
|
||||
*/
|
||||
if (mm_in.AM_STATUS == SUSPEND)
|
||||
dont_reply = TRUE;
|
||||
else
|
||||
if (mm_in.AM_STATUS < 0 || cmd != AM_GETREQ)
|
||||
free_ktask(proc_nr);
|
||||
return mm_in.AM_STATUS;
|
||||
}
|
||||
|
||||
|
||||
/* task number of task in control of kernel task, 0 if task is free */
|
||||
PRIVATE struct
|
||||
{
|
||||
int proc;
|
||||
int signalled;
|
||||
} In_use[AM_NTASKS];
|
||||
|
||||
PRIVATE int
|
||||
alloc_ktask()
|
||||
{
|
||||
int i;
|
||||
int slot = -1;
|
||||
|
||||
for (i = 0; i < AM_NTASKS; i++) /* look at all kernel tasks!! */
|
||||
if (In_use[i].proc == who)
|
||||
{ /* already has a kernel task */
|
||||
slot = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (In_use[i].proc == 0)
|
||||
slot = i; /* slot i is free, but keep looking */
|
||||
if (slot < 0) /* no free slot was found */
|
||||
return 0;
|
||||
In_use[slot].proc = who;
|
||||
In_use[slot].signalled = 0;
|
||||
return AMOEBA_CLASS - slot;
|
||||
}
|
||||
|
||||
|
||||
PRIVATE int
|
||||
free_ktask(n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AM_NTASKS; i++)
|
||||
if (In_use[i].proc == n)
|
||||
{
|
||||
In_use[i].proc = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PRIVATE int
|
||||
am_revive(task, status, free_it)
|
||||
int task;
|
||||
int status;
|
||||
int free_it;
|
||||
{
|
||||
if (who > 0)
|
||||
return EPERM;
|
||||
if (free_it)
|
||||
free_ktask(task); /* it was not a getreq! */
|
||||
reply(task, status, 0, (char *) 0); /* revive the task */
|
||||
dont_reply = TRUE;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
PUBLIC int
|
||||
am_check_sig(proc, type)
|
||||
int proc;
|
||||
int type;
|
||||
{
|
||||
/* return 0 if the signal was for a transacting task. otherwise return 1 */
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AM_NTASKS; i++)
|
||||
if (In_use[i].proc == proc && (!In_use[i].signalled || type == 1))
|
||||
{
|
||||
/* mm_out is not being used by anyone right now! */
|
||||
In_use[i].signalled = 1;
|
||||
if (type == 1)
|
||||
{
|
||||
In_use[i].proc = 0;
|
||||
mm_out.m_type = AM_TASK_DIED;
|
||||
}
|
||||
else
|
||||
mm_out.m_type = AM_PUTSIG;
|
||||
mm_out.AM_COUNT = i;
|
||||
send(AMINT_CLASS, &mm_out);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif AM_KERNEL
|
||||
33
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/Makefile
Normal file
33
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/Makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
SHELL = /bin/sh
|
||||
CFLAGS =
|
||||
CC = cc
|
||||
|
||||
all: from to rsh sherver master
|
||||
|
||||
from: from.s
|
||||
$(CC) -o $@ from.s
|
||||
|
||||
to: to.s
|
||||
$(CC) -o $@ to.s
|
||||
|
||||
rsh: rsh.s prot.s
|
||||
$(CC) -o $@ rsh.s prot.s
|
||||
chmem =500 $@
|
||||
|
||||
sherver: sherver.s prot.s
|
||||
$(CC) -o $@ sherver.s prot.s
|
||||
chmem =500 $@
|
||||
|
||||
master: master.s
|
||||
$(CC) -o $@ master.s
|
||||
chmem =500 $@
|
||||
|
||||
sherver.s: sherver.h
|
||||
rsh.s: sherver.h
|
||||
|
||||
clean:
|
||||
rm -f sherver.s from.s to.s master.s rsh.s prot.s
|
||||
rm -f sherver from to master rsh
|
||||
|
||||
|
||||
|
||||
29
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/READ_ME
Normal file
29
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/READ_ME
Normal file
@@ -0,0 +1,29 @@
|
||||
This directory contains the sources for amoeba based utilities. These are
|
||||
mainly of interest if you have an ethernet connection. Master and sherver
|
||||
should not be installed if you do not have an ethernet connection since they
|
||||
will take up precious memory.
|
||||
|
||||
|
||||
Installation:
|
||||
|
||||
1. Type make
|
||||
|
||||
2. Copy files as follows:
|
||||
|
||||
cp rsh /usr/bin
|
||||
cp rcp /usr/bin
|
||||
cp to /usr/bin
|
||||
cp from /usr/bin
|
||||
|
||||
3. Edit /etc/rc and add the lines:
|
||||
|
||||
echo "Starting sherver(s)"
|
||||
/usr/bin/master 1 <uid> <gid> /etc/sherver port
|
||||
|
||||
where port is the name that your node is to be known by. It should not be
|
||||
more than 6 characters long. It can be made up of any characters you like.
|
||||
Note that the flags <uid> and <gid> are the uid and group id that the
|
||||
sherver will run under.
|
||||
|
||||
|
||||
|
||||
79
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/from.c
Normal file
79
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/from.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include "amoeba.h"
|
||||
|
||||
#define BUFSIZE 20480
|
||||
|
||||
char * cmd;
|
||||
|
||||
|
||||
catchalarm()
|
||||
{
|
||||
fprintf(stderr, "%s: timeout\n", cmd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char ** argv;
|
||||
{
|
||||
unshort getreq();
|
||||
unshort putrep();
|
||||
char * malloc();
|
||||
int catchalarm();
|
||||
|
||||
char * buf;
|
||||
header hdr;
|
||||
unshort cnt;
|
||||
unshort bufsize = BUFSIZE;
|
||||
unsigned tim = 15 * 60; /* #secs before timeout */
|
||||
|
||||
cmd = *argv;
|
||||
if (argc > 1 && strncmp(argv[1], "-t", 2) == 0)
|
||||
{
|
||||
tim = atoi(&argv[1][2]);
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if (tim)
|
||||
signal(SIGALRM, catchalarm);
|
||||
if (argc != 2 && argc != 3) /* if (!(argc & 2))?? */
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-ttime] [bufsize] port\n", cmd);
|
||||
exit(-1);
|
||||
}
|
||||
if (argc == 3)
|
||||
bufsize = atoi(argv[2]);
|
||||
if ((buf = malloc(bufsize * sizeof (char))) == NULL)
|
||||
{
|
||||
fprintf(stderr, "%s: out of memory\n", cmd);
|
||||
exit(-1);
|
||||
}
|
||||
strncpy(&hdr.h_port, argv[1], PORTSIZE);
|
||||
for (;;)
|
||||
{
|
||||
if (tim)
|
||||
alarm(tim);
|
||||
cnt = getreq(&hdr, buf, bufsize);
|
||||
if (tim)
|
||||
alarm(0);
|
||||
if ((short)cnt < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: getreq failed\n", cmd);
|
||||
exit(-3);
|
||||
}
|
||||
hdr.h_status = 0;
|
||||
if (cnt != 0)
|
||||
if (write(1, buf, cnt) < 0)
|
||||
{
|
||||
perror(cmd);
|
||||
hdr.h_status = -1;
|
||||
}
|
||||
putrep(&hdr, NILBUF, 0);
|
||||
if (hdr.h_status)
|
||||
exit(-4);
|
||||
if (cnt == 0)
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
78
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/master.c
Normal file
78
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/master.c
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <signal.h>
|
||||
|
||||
char console[] = "/dev/console";
|
||||
|
||||
run(uid, gid, argv)
|
||||
char **argv;
|
||||
{
|
||||
|
||||
for (;;)
|
||||
switch (fork()) {
|
||||
default:
|
||||
return;
|
||||
case 0:
|
||||
if (setgid(gid) < 0) perror("can't set gid");
|
||||
if (setuid(uid) < 0) perror("can't set uid");
|
||||
/*
|
||||
execvp(*argv, argv);
|
||||
*/
|
||||
execv(*argv, argv);
|
||||
perror("master: exec'ing");
|
||||
prints("can't execute %s\n", *argv);
|
||||
/*
|
||||
kill(getppid(), SIGTERM);
|
||||
*/
|
||||
/* If the exec failed, don't try it again immediately.
|
||||
* Give the kernel a chance to do something else.
|
||||
*/
|
||||
sleep (5);
|
||||
_exit(1);
|
||||
case -1:
|
||||
sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
register n, uid, gid;
|
||||
|
||||
/* Minix can't do this
|
||||
setpgrp(getpid(), getpid());
|
||||
*/
|
||||
if (argc < 4) {
|
||||
prints("Usage: master # uid gid command args ...\n");
|
||||
return(1);
|
||||
}
|
||||
n = atoi(argv[1]);
|
||||
if (n < 1 || n > 20) {
|
||||
prints("Bad count.\n");
|
||||
return(1);
|
||||
}
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
|
||||
/* Put the program into the background. */
|
||||
switch (fork()) {
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
perror(argv[0]);
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
uid = atoi(argv[2]);
|
||||
gid = atoi(argv[3]);
|
||||
|
||||
/* Start n copies of the program. */
|
||||
do
|
||||
run(uid, gid, &argv[4]);
|
||||
while (--n);
|
||||
|
||||
/* Replace each one that dies. */
|
||||
while (wait((int *) 0) > 0)
|
||||
run(uid, gid, &argv[4]);
|
||||
return(0);
|
||||
}
|
||||
78
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/prot.c
Normal file
78
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/prot.c
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#define isblank(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
|
||||
|
||||
#define MAXTOKEN 16
|
||||
|
||||
static char *gettok(fp)
|
||||
FILE *fp;
|
||||
{
|
||||
static char buf[MAXTOKEN + 1];
|
||||
register char c, *p = buf;
|
||||
|
||||
do /* skip blanks */
|
||||
if ((c = getc(fp)) == EOF)
|
||||
return(0);
|
||||
while (isblank(c));
|
||||
do {
|
||||
if (c == '#') { /* skip comment */
|
||||
while ((c = getc(fp)) != EOF)
|
||||
if (c == '\n') break;
|
||||
break;
|
||||
}
|
||||
*p++ = c;
|
||||
} while (c != ':' && (c = getc(fp)) != EOF && !isblank(c));
|
||||
*p++ = 0;
|
||||
return(buf);
|
||||
}
|
||||
|
||||
static number(p)
|
||||
char *p;
|
||||
{
|
||||
int n;
|
||||
|
||||
return sscanf(p, "%d", &n) == 1 ? n : -1;
|
||||
}
|
||||
|
||||
chkprot(chkfil, chkdefault, uid, gid)
|
||||
char *chkfil;
|
||||
char *chkdefault;
|
||||
{
|
||||
register userchk = 0, n;
|
||||
register FILE *fp;
|
||||
register char *p;
|
||||
register struct passwd *pw;
|
||||
register struct group *gr;
|
||||
extern FILE *fopen();
|
||||
extern struct passwd *getpwuid();
|
||||
extern struct group *getgrgid();
|
||||
|
||||
pw = getpwuid(uid);
|
||||
endpwent();
|
||||
gr = getgrgid(gid);
|
||||
endgrent();
|
||||
if ((fp = fopen(chkfil, "r")) == NULL && (fp = fopen(chkdefault, "r")) == NULL)
|
||||
return(-1);
|
||||
while ((p = gettok(fp)) != 0)
|
||||
if (strcmp(p, "group:") == 0)
|
||||
userchk = 0;
|
||||
else if (strcmp(p, "user:") == 0)
|
||||
userchk = 1;
|
||||
else if (userchk) {
|
||||
if (pw && strcmp(p, pw->pw_name) == 0 ||
|
||||
uid == number(p)) {
|
||||
fclose(fp);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (gr && strcmp(p, gr->gr_name) == 0 ||
|
||||
gid == number(p)) {
|
||||
fclose(fp);
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
76
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/rcp
Normal file
76
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/rcp
Normal file
@@ -0,0 +1,76 @@
|
||||
: Copy a file from any machine to any other machine.
|
||||
usage="Usage: $0 [machine!]from-file [machine!]to-file"
|
||||
PATH=/usr/local:/bin:/usr/bin
|
||||
CDPATH=
|
||||
case $# in
|
||||
2) :
|
||||
;;
|
||||
*) echo "$usage" 1>&2
|
||||
exit 1
|
||||
esac
|
||||
from=$1 to=$2
|
||||
case $from in
|
||||
*!*) IFS="!"
|
||||
set $from
|
||||
case $# in
|
||||
2) from_mach=$1 from_file=$2 IFS=" "
|
||||
;;
|
||||
*) echo "$usage" 1>&2
|
||||
exit 1
|
||||
esac
|
||||
;;
|
||||
*) from_file=$from
|
||||
esac
|
||||
case "$from_file" in
|
||||
"") echo "$usage" 1>&2
|
||||
exit 1
|
||||
esac
|
||||
case $to in
|
||||
*!*) IFS="!"
|
||||
set $to
|
||||
case $# in
|
||||
2) to_mach=$1 to_file=$2 IFS=" "
|
||||
;;
|
||||
*) echo "$usage" 1>&2
|
||||
exit 1
|
||||
esac
|
||||
;;
|
||||
*) to_file=$to
|
||||
esac
|
||||
case "$to_file" in
|
||||
"") echo "$usage" 1>&2
|
||||
exit 1
|
||||
esac
|
||||
case "$from_mach" in
|
||||
"$to_mach")
|
||||
: machines equal
|
||||
case "$to_mach" in
|
||||
"") : local
|
||||
cp "$from_file" "$to_file"
|
||||
;;
|
||||
*) : remote
|
||||
rsh "$to_mach" "cp $from_file $to_file"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*) : machines not equal
|
||||
case "$to_mach" in
|
||||
"") : to local
|
||||
if test -d "$to_file"
|
||||
then rsh -e "$from_mach" "cat $from_file" >"$to_file/`basename $from_file`"
|
||||
else rsh -e "$from_mach" "cat $from_file" >"$to_file"
|
||||
fi
|
||||
;;
|
||||
*) : to remote
|
||||
case "$from_mach" in
|
||||
"") : from local
|
||||
rsh -i "$to_mach" "if test -d $to_file; then cat >$to_file/`basename $from_file`; else cat >$to_file; fi" <"$from_file"
|
||||
;;
|
||||
*) : from remote
|
||||
rsh -e "$from_mach" "cat $from_file" | rsh -i "$to_mach" "if test -d $to_file; then cat >$to_file/`basename $from_file`; else cat >$to_file; fi"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
245
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/rsh.c
Normal file
245
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/rsh.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* rsh [-ei] machine command
|
||||
*
|
||||
* -b: run remote process in background
|
||||
* -e: separate error output
|
||||
* -i: send input
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include "amoeba.h"
|
||||
#include "sherver.h"
|
||||
|
||||
char *prog, *mach, buf[BUFFERSIZE];
|
||||
|
||||
usage(){
|
||||
fprintf(stderr, "Usage: %s [-bei] machine command ...\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
panic(s)
|
||||
char *s;
|
||||
{
|
||||
fprintf(stderr, "%s: %s\n", prog, s);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *collect(buf, vec, sep)
|
||||
char *buf, **vec, sep;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
while ((p = *vec++) != 0) {
|
||||
while (*p != 0) {
|
||||
*buf++ = *p++;
|
||||
if (buf == &buf[BUFFERSIZE])
|
||||
panic("environment too large\n");
|
||||
}
|
||||
*buf++ = *vec == 0 ? 0 : sep;
|
||||
}
|
||||
return(buf);
|
||||
}
|
||||
|
||||
char *setupbuf(argv, flags)
|
||||
char **argv;
|
||||
int *flags;
|
||||
{
|
||||
register char *p;
|
||||
extern char **environ, *getenv();
|
||||
|
||||
if (*argv == 0) {
|
||||
if ((p = getenv("SHELL")) == 0)
|
||||
p = "/bin/sh";
|
||||
if (strlen(p) > BUFFERSIZE - 10) /* 10 > strlen("exec -i") */
|
||||
panic("pathname of shell too large");
|
||||
sprintf(buf, "exec %s -i", p);
|
||||
p = &buf[strlen(buf) + 1];
|
||||
*flags |= IFLG;
|
||||
}
|
||||
else
|
||||
p = collect(buf, argv, ' ');
|
||||
return collect(p, environ, 0);
|
||||
}
|
||||
|
||||
execute(hdr, p, flags)
|
||||
header *hdr;
|
||||
char *p;
|
||||
{
|
||||
register unshort cnt;
|
||||
|
||||
timeout(50);
|
||||
strncpy(&hdr->h_port, mach, PORTSIZE);
|
||||
hdr->h_command = EXEC_COMMAND;
|
||||
hdr->h_size = p - buf;
|
||||
hdr->h_extra = flags;
|
||||
cnt = trans(hdr, buf, p - buf, hdr, buf, BUFFERSIZE);
|
||||
if ((short) cnt < 0) {
|
||||
fprintf(stderr, "%s: %s not available\n", prog, mach);
|
||||
return(0);
|
||||
}
|
||||
if (hdr->h_status != COMM_DONE) {
|
||||
if (cnt == 0)
|
||||
fprintf(stderr, "can't execute command\n");
|
||||
else
|
||||
fprintf(stderr, "%.*s\n", cnt, buf);
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
alrm(){
|
||||
fprintf(stderr, "rsh: getreq timed out\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
commandloop(hdr)
|
||||
header *hdr;
|
||||
{
|
||||
register unshort cnt;
|
||||
|
||||
for (;;) {
|
||||
alarm(12*60*60);
|
||||
cnt = getreq(hdr, buf, BUFFERSIZE);
|
||||
alarm(0);
|
||||
if ((short) cnt < 0) {
|
||||
fprintf(stderr, "getreq failed\n");
|
||||
return(-1);
|
||||
}
|
||||
switch (hdr->h_command) {
|
||||
case READ_FD:
|
||||
if (hdr->h_extra < NFD)
|
||||
cnt = read(hdr->h_extra, buf, hdr->h_size);
|
||||
else
|
||||
fprintf(stderr, "read: bad fd\n");
|
||||
hdr->h_size = (unshort) cnt;
|
||||
putrep(hdr, buf, cnt < 0 ? 0 : cnt);
|
||||
if (cnt == 0)
|
||||
return(0);
|
||||
break;
|
||||
case WRITE_FD:
|
||||
if (hdr->h_extra < NFD)
|
||||
if (cnt == 0)
|
||||
close(hdr->h_extra);
|
||||
else
|
||||
write(hdr->h_extra, buf, cnt);
|
||||
else
|
||||
fprintf(stderr, "write: bad fd\n");
|
||||
putrep(hdr, NILBUF, 0);
|
||||
break;
|
||||
case EXIT_STATUS:
|
||||
if (cnt != 0) {
|
||||
write(2, "Remote message: ", 16);
|
||||
write(2, buf, cnt);
|
||||
write(2, "\n", 1);
|
||||
}
|
||||
putrep(hdr, NILBUF, 0);
|
||||
return(hdr->h_extra >> 8);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown command\n");
|
||||
putrep(hdr, NILBUF, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupin(hdr)
|
||||
header *hdr;
|
||||
{
|
||||
register pid;
|
||||
|
||||
uniqport(&hdr->h_priv.prv_random);
|
||||
if ((pid = fork()) < 0) {
|
||||
perror(prog);
|
||||
exit(-1);
|
||||
}
|
||||
if (pid == 0) {
|
||||
hdr->h_port = hdr->h_priv.prv_random;
|
||||
_exit(commandloop(hdr)); /* get read commands from sherver */
|
||||
}
|
||||
return(pid);
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
char *p;
|
||||
header hdr;
|
||||
register pid, status;
|
||||
int flags;
|
||||
|
||||
#ifdef sun
|
||||
put_user_name_in_env();
|
||||
#endif
|
||||
prog = *argv++;
|
||||
if (argc == 1)
|
||||
usage();
|
||||
signal(SIGALRM, alrm);
|
||||
while (*argv != 0 && **argv == '-') {
|
||||
while (*++*argv)
|
||||
switch (**argv) {
|
||||
case 'b': flags |= BFLG; break;
|
||||
case 'e': flags |= EFLG; break;
|
||||
case 'i': flags |= IFLG; break;
|
||||
default: usage();
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
if ((mach = *argv++) == 0)
|
||||
usage();
|
||||
chkperm(mach);
|
||||
p = setupbuf(argv, &flags); /* get command and environment */
|
||||
if (flags & IFLG) /* set up input process */
|
||||
pid = setupin(&hdr);
|
||||
if (!execute(&hdr, p, flags)) { /* send command to sherver */
|
||||
if (flags & IFLG)
|
||||
kill(pid, SIGKILL);
|
||||
exit(1);
|
||||
}
|
||||
if (!(flags & BFLG)) /* get commands from sherver */
|
||||
status = commandloop(&hdr);
|
||||
if (flags & IFLG) { /* wait for input process */
|
||||
close(0); close(1); close(2);
|
||||
while (wait((int *) 0) != pid)
|
||||
;
|
||||
}
|
||||
exit(status);
|
||||
}
|
||||
|
||||
chkperm(svport)
|
||||
char *svport;
|
||||
{
|
||||
static char chkfil[] = "/etc/XXXXXXXXXXXXXX";
|
||||
extern char *strchr();
|
||||
|
||||
sprintf(strchr(chkfil, 'X'), "rsh:%.14s", svport);
|
||||
if (chkprot(chkfil, "/etc/rsh:default", geteuid(), getegid()) == 0)
|
||||
panic("permission denied");
|
||||
}
|
||||
|
||||
char *strchr(s, c)
|
||||
register char *s;
|
||||
{
|
||||
while (*s) {
|
||||
if (*s == c)
|
||||
return s;
|
||||
s++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef sun
|
||||
#include <pwd.h>
|
||||
|
||||
put_user_name_in_env()
|
||||
{
|
||||
extern struct passwd *getpwuid();
|
||||
register struct passwd *pw;
|
||||
static char buf[512];
|
||||
char host[10];
|
||||
|
||||
gethostname(host, sizeof host);
|
||||
pw = getpwuid(getuid());
|
||||
sprintf(buf, "UserName=%s@%s", pw ? pw->pw_name : "???", host);
|
||||
putenv(buf);
|
||||
}
|
||||
#endif sun
|
||||
420
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/sherver.c
Normal file
420
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/sherver.c
Normal file
@@ -0,0 +1,420 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include "amoeba.h"
|
||||
#include "sherver.h"
|
||||
|
||||
/* isn't minix wonderful */
|
||||
#undef BUFFERSIZE
|
||||
#define BUFFERSIZE 8192
|
||||
|
||||
#define COMPATIBLE /* with the new rsh */
|
||||
|
||||
#define MAXWAIT (4*60*60) /* maximum waiting time in seconds */
|
||||
#define Secs *10
|
||||
#define LOCATETIMER 30 Secs
|
||||
|
||||
#ifdef DEBUG
|
||||
char *
|
||||
portstr(p) port *p; {
|
||||
static char strbuf[80];
|
||||
|
||||
sprintf(strbuf,"%x:%x:%x:%x:%x:%x",
|
||||
p->_portbytes[0]&0xFF,
|
||||
p->_portbytes[1]&0xFF,
|
||||
p->_portbytes[2]&0xFF,
|
||||
p->_portbytes[3]&0xFF,
|
||||
p->_portbytes[4]&0xFF,
|
||||
p->_portbytes[5]&0xFF);
|
||||
return strbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
header hdr;
|
||||
char *prog, buf[BUFFERSIZE], *envvec[MAXENV], *errstr;
|
||||
int pidlist[NFD];
|
||||
extern errno;
|
||||
static char *sig[] = {
|
||||
"signal 0",
|
||||
"hangup",
|
||||
"interrupt",
|
||||
"quit",
|
||||
"illegal instruction",
|
||||
"trace/BPT trap",
|
||||
"IOT trap",
|
||||
"EMT trap",
|
||||
"floating exception",
|
||||
"kill",
|
||||
"bus error",
|
||||
"memory fault",
|
||||
"bad system call",
|
||||
"broken pipe",
|
||||
"alarm call",
|
||||
"terminate",
|
||||
"urgent socket",
|
||||
"stop (signal)",
|
||||
"stop",
|
||||
"continue",
|
||||
"child exited",
|
||||
"stop (tty input)",
|
||||
"stop (tty output)",
|
||||
"tty input interrupt",
|
||||
"cputime limit exceeded",
|
||||
"filesize limit exceeded",
|
||||
"virtual time alarm",
|
||||
"profiling timer alarm",
|
||||
};
|
||||
|
||||
panic(s, arg)
|
||||
char *s;
|
||||
{
|
||||
register FILE *f;
|
||||
FILE * fopen();
|
||||
|
||||
#ifdef DEBUG
|
||||
#define f stderr
|
||||
#else
|
||||
if (f = fopen("/dev/tty0", "w")) {
|
||||
#endif DEBUG
|
||||
fprintf(f, "%s: ", prog);
|
||||
fprintf(f, s, arg);
|
||||
fprintf(f, "\n");
|
||||
#ifdef DEBUG
|
||||
#undef f
|
||||
#else
|
||||
fclose(f);
|
||||
}
|
||||
#endif DEBUG
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
alrm(){ /* set alarm again to avoid races */
|
||||
signal(SIGALRM, alrm);
|
||||
alarm(MAXWAIT);
|
||||
}
|
||||
|
||||
killall(){ /* kill all the created processes */
|
||||
register n;
|
||||
|
||||
for (n = 0; n < NFD; n++)
|
||||
if (pidlist[n] != 0)
|
||||
kill(pidlist[n], SIGKILL);
|
||||
}
|
||||
|
||||
trap(){ /* got SIGAMOEBA */
|
||||
killall();
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
copyloop(pp, rfd, wfd)
|
||||
port *pp;
|
||||
{
|
||||
register unshort cnt;
|
||||
register n;
|
||||
|
||||
do {
|
||||
alarm(MAXWAIT);
|
||||
n = read(rfd, buf, BUFFERSIZE);
|
||||
alarm(0); alarm(0);
|
||||
if (n < 0) {
|
||||
strcpy(buf, errno==EINTR ? "waited too long for input"
|
||||
: "read error");
|
||||
killall();
|
||||
return(1);
|
||||
}
|
||||
hdr.h_port = *pp;
|
||||
hdr.h_command = WRITE_FD;
|
||||
hdr.h_size = n;
|
||||
hdr.h_extra = wfd;
|
||||
cnt = trans(&hdr, buf, (unshort) n, &hdr, NILBUF, 0);
|
||||
if (cnt != 0)
|
||||
panic("trans failed (%d iso 0)", (short) cnt);
|
||||
} while (n != 0);
|
||||
return(0);
|
||||
}
|
||||
|
||||
setupin(hdr)
|
||||
header *hdr;
|
||||
{
|
||||
int fd, p[2];
|
||||
register unshort cnt;
|
||||
port svport;
|
||||
|
||||
if (pipe(p) < 0)
|
||||
errstr = "can't pipe";
|
||||
else if (p[0] != 0)
|
||||
errstr = "pipe returned wrong fd";
|
||||
else if ((pidlist[0] = fork()) < 0)
|
||||
errstr = "can't fork";
|
||||
else if (pidlist[0] == 0) {
|
||||
close(p[0]);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#ifdef COMPATIBLE
|
||||
if (!NullPort(&hdr->h_signature))
|
||||
svport = hdr->h_signature;
|
||||
else
|
||||
#endif
|
||||
svport = hdr->h_priv.prv_random;
|
||||
for (;;) {
|
||||
hdr->h_port = svport;
|
||||
hdr->h_command = READ_FD;
|
||||
hdr->h_size = BUFFERSIZE;
|
||||
hdr->h_extra = 0;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"Using read port %s\n",portstr(&hdr->h_port));
|
||||
#endif
|
||||
cnt = trans(hdr, NILBUF, 0, hdr, buf, BUFFERSIZE);
|
||||
if ((short) cnt < 0)
|
||||
panic("read trans failed (%d)", (short) cnt);
|
||||
if (cnt == 0)
|
||||
_exit(0);
|
||||
if (write(p[1], buf, cnt) != cnt) {
|
||||
timeout(300);
|
||||
hdr->h_port = svport;
|
||||
hdr->h_command = EXIT_STATUS;
|
||||
hdr->h_extra = 0x100;
|
||||
if ((cnt = trans(hdr, NILBUF, 0, hdr, NILBUF, 0)) != 0)
|
||||
panic("trans failed (%d iso 0)", (short) cnt);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
close(p[1]);
|
||||
}
|
||||
|
||||
setuperr(){
|
||||
int errpipe[2];
|
||||
|
||||
if (pipe(errpipe) < 0) {
|
||||
errstr = "can't pipe";
|
||||
return(-1);
|
||||
}
|
||||
if ((pidlist[2] = fork()) < 0) {
|
||||
close(errpipe[0]);
|
||||
close(errpipe[1]);
|
||||
errstr = "can't fork";
|
||||
return(-1);
|
||||
}
|
||||
if (pidlist[2] == 0) {
|
||||
close(errpipe[1]);
|
||||
timeout(LOCATETIMER);
|
||||
_exit(copyloop(&hdr.h_port, errpipe[0], 2));
|
||||
}
|
||||
close(errpipe[0]);
|
||||
return(errpipe[1]);
|
||||
}
|
||||
|
||||
splitup(size){
|
||||
register char *p = buf, *top = &buf[size], **vec = envvec;
|
||||
|
||||
while (p != top) {
|
||||
if (vec == &envvec[MAXENV]) {
|
||||
errstr = "too much environment";
|
||||
return(0);
|
||||
}
|
||||
*vec++ = p;
|
||||
while (*p++ != 0)
|
||||
if (p == top) {
|
||||
errstr = "bad format";
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
*vec = 0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
runit(outpipe, errout)
|
||||
int outpipe[2];
|
||||
{
|
||||
register fd;
|
||||
register char *homedir;
|
||||
extern char **environ, *getenv();
|
||||
|
||||
close(1); close(2);
|
||||
if (hdr.h_extra & BFLG) {
|
||||
if ((fd = open("/dev/null", 1)) != 1)
|
||||
panic("open returned wrong fd (%d iso 1)", fd);
|
||||
else if ((fd = dup(1)) != 2)
|
||||
panic("dup returned wrong fd (%d iso 2)", fd);
|
||||
}
|
||||
else {
|
||||
close(outpipe[0]); /* outpipe[0] >= 1 */
|
||||
if ((fd = dup(outpipe[1])) != 1)
|
||||
panic("dup returned wrong fd (%d iso 1)", fd);
|
||||
if (hdr.h_extra & EFLG) {
|
||||
if ((fd = dup(errout)) != 2)
|
||||
panic("dup returned wrong fd (%d iso 2)", fd);
|
||||
else
|
||||
close(errout);
|
||||
}
|
||||
else if ((fd = dup(1)) != 2)
|
||||
panic("dup returned wrong fd (%d iso 2)", fd);
|
||||
}
|
||||
for (fd = 3; fd < 20; fd++)
|
||||
close(fd);
|
||||
#ifdef LOG
|
||||
{
|
||||
#include <fcntl.h>
|
||||
register int logfd;
|
||||
|
||||
logfd = open("/usr/tmp/rsh.log", O_WRONLY|O_APPEND|O_CREAT, 0244);
|
||||
if (logfd >= 0) {
|
||||
#include <time.h>
|
||||
register char *s;
|
||||
register struct tm *tm;
|
||||
long t;
|
||||
char buf[1024]; /* had better be large enough */
|
||||
static char *months[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
time(&t);
|
||||
tm = localtime(&t);
|
||||
environ = &envvec[1];
|
||||
s = getenv("UserName");
|
||||
if (s == 0)
|
||||
s = getenv("HOME");
|
||||
if (s == 0)
|
||||
s = getenv("LOGNAME");
|
||||
if (s == 0)
|
||||
s = getenv("USER");
|
||||
sprintf(buf, "%02d-%s-%02d %02d:%02d:%02d %s\t%s%s\n",
|
||||
tm->tm_mday, months[tm->tm_mon], tm->tm_year,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
||||
s?s:"???", envvec[0],
|
||||
hdr.h_extra & IFLG ? " (interactive)" : "");
|
||||
lseek(logfd, 0L, 2);
|
||||
write(logfd, buf, strlen(buf));
|
||||
close(logfd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
environ = &envvec[1];
|
||||
if ((homedir = getenv("HOME")) == 0 || chdir(homedir) < 0)
|
||||
chdir("/");
|
||||
execl("/bin/sh", "sh", "-c", envvec[0], (char *) 0);
|
||||
panic("can't execute shell", 0);
|
||||
}
|
||||
|
||||
execomm(size){
|
||||
int outpipe[2], errout;
|
||||
|
||||
if (!splitup(size))
|
||||
return(-1);
|
||||
if (!(hdr.h_extra & BFLG)) {
|
||||
if ((hdr.h_extra & EFLG) && (errout = setuperr()) < 0)
|
||||
return(-1);
|
||||
if (pipe(outpipe) < 0) {
|
||||
if (hdr.h_extra & EFLG)
|
||||
close(errout);
|
||||
errstr = "can't pipe";
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if ((pidlist[1] = fork()) < 0) {
|
||||
if (!(hdr.h_extra & BFLG)) {
|
||||
if (hdr.h_extra & EFLG)
|
||||
close(errout);
|
||||
close(outpipe[0]);
|
||||
close(outpipe[1]);
|
||||
}
|
||||
errstr = "can't fork";
|
||||
return(-1);
|
||||
}
|
||||
if (pidlist[1] == 0)
|
||||
runit(outpipe, errout);
|
||||
if (hdr.h_extra & BFLG)
|
||||
return(0);
|
||||
if (hdr.h_extra & EFLG)
|
||||
close(errout);
|
||||
close(outpipe[1]);
|
||||
return(outpipe[0]);
|
||||
}
|
||||
|
||||
awaitchild(hdr, status)
|
||||
header *hdr;
|
||||
{
|
||||
register pid, n;
|
||||
int wstat;
|
||||
|
||||
if (status == 0) {
|
||||
alarm(MAXWAIT);
|
||||
while ((pid = wait(&wstat)) > 0) {
|
||||
if (pid == pidlist[1]) {
|
||||
pidlist[1] = 0;
|
||||
hdr->h_extra = status;
|
||||
}
|
||||
status = wstat;
|
||||
}
|
||||
alarm(0); alarm(0);
|
||||
if (pidlist[1] != 0) {
|
||||
strcpy(buf, errno == EINTR ? "waited too long"
|
||||
: "wait error");
|
||||
killall();
|
||||
hdr->h_extra = 0x100;
|
||||
}
|
||||
else if (status & 0xFF)
|
||||
if ((status & 0x7F) < sizeof(sig) / sizeof(sig[0]))
|
||||
strcpy(buf, sig[status & 0x7F]);
|
||||
else
|
||||
sprintf(buf, "signal %d", status & 0x7F);
|
||||
else
|
||||
buf[0] = 0;
|
||||
if (status & 0x80)
|
||||
strcat(buf, " - core dumped");
|
||||
}
|
||||
else
|
||||
hdr->h_extra = status << 8;
|
||||
timeout(300);
|
||||
hdr->h_command = EXIT_STATUS;
|
||||
if ((n = trans(hdr, buf, strlen(buf), hdr, NILBUF, 0)) != 0)
|
||||
panic("trans failed (%d iso 0)", (short) n);
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
register unshort cnt;
|
||||
register fd;
|
||||
unshort getreq(), putrep();
|
||||
|
||||
prog = argv[0];
|
||||
if (argc != 2)
|
||||
panic("usage: sherver machine", 0);
|
||||
signal(SIGALRM, alrm);
|
||||
signal(SIGAMOEBA, trap);
|
||||
strncpy(&hdr.h_port, argv[1], PORTSIZE);
|
||||
/*cbo*/printf("before first getreq\n");
|
||||
cnt = getreq(&hdr, buf, BUFFERSIZE);
|
||||
/*cbo*/printf("after first getreq\n");
|
||||
if ((short) cnt < 0)
|
||||
panic("getreq failed (%d)", (short) cnt);
|
||||
if (hdr.h_size == cnt) {
|
||||
close(0);
|
||||
if (hdr.h_extra & IFLG)
|
||||
setupin(&hdr);
|
||||
else if (open("/dev/null", 0) != 0)
|
||||
errstr = "can't open /dev/null";
|
||||
if (errstr == 0) {
|
||||
uniqport(&hdr.h_port);
|
||||
fd = execomm(cnt);
|
||||
}
|
||||
}
|
||||
else
|
||||
errstr = hdr.h_size > BUFFERSIZE ? "request too large" :
|
||||
"bad format";
|
||||
if (errstr == 0) {
|
||||
hdr.h_status = COMM_DONE;
|
||||
putrep(&hdr, NILBUF, 0);
|
||||
if (!(hdr.h_extra & BFLG)) {
|
||||
timeout(LOCATETIMER);
|
||||
awaitchild(&hdr, copyloop(&hdr.h_port, fd, 1));
|
||||
}
|
||||
}
|
||||
else {
|
||||
hdr.h_status = COMM_ERROR;
|
||||
putrep(&hdr, errstr, strlen(errstr));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#define BUFFERSIZE 20480
|
||||
#define MAXENV 100
|
||||
#define NFD 3
|
||||
|
||||
/* initial command from rsh to sherver */
|
||||
#define EXEC_COMMAND 1
|
||||
|
||||
/* flags in h_extra for EXEC_COMMAND */
|
||||
#define BFLG 0x01
|
||||
#define EFLG 0x02
|
||||
#define IFLG 0x04
|
||||
|
||||
/* commands from sherver to rsh (parameter (fd or status) in h_extra) */
|
||||
#define READ_FD 1
|
||||
#define WRITE_FD 2
|
||||
#define EXIT_STATUS 4
|
||||
|
||||
/* replies */
|
||||
#define COMM_DONE 0
|
||||
#define COMM_ERROR -1
|
||||
50
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/to.c
Normal file
50
study/linux-travel/MINIX-1.5/1.5/Source/amoeba/util/to.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
#include "amoeba.h"
|
||||
|
||||
#define BUFSIZE 20480
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
header hdr;
|
||||
char *buf, *malloc();
|
||||
char *cmd = argv[0];
|
||||
unshort cnt, bufsize = BUFSIZE;
|
||||
unshort trans();
|
||||
|
||||
if (argc > 1 && strncmp(argv[1], "-t", 2) == 0) {
|
||||
timeout(atoi(&argv[1][2]), 0);
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
if (argc != 2 && argc != 3) {
|
||||
fprintf(stderr, "Usage: %s port\n", cmd);
|
||||
exit(-1);
|
||||
}
|
||||
if (argc == 3)
|
||||
bufsize = atoi(argv[2]);
|
||||
if ((buf = malloc(bufsize)) == NULL) {
|
||||
fprintf(stderr, "%s: out of memory\n", cmd);
|
||||
exit(-1);
|
||||
}
|
||||
strncpy(&hdr.h_port, argv[1], PORTSIZE);
|
||||
for (;;) {
|
||||
cnt = read(0, buf, bufsize);
|
||||
if ((short) cnt < 0) {
|
||||
perror("read");
|
||||
exit(-3);
|
||||
}
|
||||
if (trans(&hdr, buf, cnt, &hdr, NILBUF, 0) != 0) {
|
||||
fprintf(stderr, "%s: trans failed\n", cmd);
|
||||
exit(-4);
|
||||
}
|
||||
if (hdr.h_status) {
|
||||
fprintf(stderr, "%s: write failed in from\n", cmd);
|
||||
exit(-5);
|
||||
}
|
||||
if (cnt == 0)
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user