[comp.os.minix] New Bootstrapper Part 2 of 3

ncoverby@ndsuvax.UUCP (Glen Overby) (05/11/89)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	b2b/loader.c
#	kernel/makefile
#	kernel/memory.c.diff
#	kernel/mpx88.s
#	kernel/system.c.diff
#	fs/glo.h.diff
#	fs/inode.c.diff
#	fs/makefile
# This archive created: Tue May  9 12:01:19 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'b2b/loader.c'" '(26336 characters)'
if test -f 'b2b/loader.c'
then
    echo shar: will not over-write existing file "'b2b/loader.c'"
else
sed 's/^X//' << \SHAR_EOF > 'b2b/loader.c'
X/*
X			Minix Second Stage Boot Loader
X
XIn this program, all the elements of the Minix system are loaded into memory
Xfrom binary files on a filesystem.  All parts of the system are loaded
Xlike any other Minix process, with Text, Data and Stack areas and command
Xoptions on a "command line" (which is actually in a binary format).
X
XThe routines in this file turn a raw disk into a filesystem.  The primary
Xroutines are:
X	inode = open_file(filename)
X	a.out = load_file(inode, starting segment)
X	count = read_file(inode, buffer)
X
X12/2/88 Glen/B
X	Construct this from the reminants of the old (CS548/CS497) boot
X	program.
X*/
X
X/* include files to get inode, super block structs*/
X#include <minix/const.h>
X#include <minix/type.h>
X#include <fs/const.h>
X#include <fs/type.h>
X#include <fs/inode.h>
X#include <fs/super.h>
X#include <stdio.h>
X#include <errno.h>
X#include <a.out.h>
X#include "type.h"
X#include "partition.h"
X#include "hdparam.h"
X
X/*#undef printf		/* defined in fs/const.h as 'printk' */
X#undef getchar		/* don't want the macros */
X#undef putchar
X#undef putc
X#undef getc
X
Xextern	int	errno;
X	int	def_dev;			/* default (boot) device */
X	char	glb_block[BLOCK_SIZE];		/* misc block buffer */
X	int	cylsiz, tracksiz;		/* for low diskio.. */
X	int	sizes[10];			/* kernel, mm, fs, init size */
X	int	kds, ksp;			/* kernel data seg, sp */
X
X/*#define TRACE*/
X/*#define DEBUG*/
X/*#define DEBUG1*/
X
X/* Function Types */
Xint ll_Block_Read(/* int device, block; char *buffer */);
Xint read_block(/* struct super_block *super; int block; char *buffer; */);
Xstruct super_block *read_super(/* int device; */);
Xstruct part_entry *Read_Part(/* int device; */);
Xstruct param *read_rom(/* int device; */);
Xstruct inode *read_inode(/*struct super_block *sb; int inum;*/);
Xint read_file(/*struct inode *inode; char *buffer;*/);
Xint lload_blocks(/*struct super_block *super; char *buffer;
X		int *list, nlist;*/);
Xstruct inode *open_file(/*char *filename;*/);
Xchar *device_map(/*char *filename; int *device;*/);
Xstruct inode *follow_path(/*struct super_block *super; char *name*/);
Xnext_name(/*char *from, *name;*/);
Xint search_dir(/*struct inode *inode; char *name;*/);
X
X#define	READ	0
X#define	WRITE	1
X
X/*
X * Filesystem parameters which are not supplied in FS' header files
X */
X#define NR_DIRECT_ZONES	NR_ZONE_NUMS-2	/* number of DIRECT zones */
X#define IND_ZONE_NUM	7	/* i_zone offset of indirect zone */
X#define DIND_ZONE_NUM	8	/* i_zone offset of double indirect block */
X#define SECTOR_SIZE	512	/* sector size (bytes) */
X#define HEAD_SIZE	32	/* a.out header size (stripped) */
X
X/*
X * Hardware Parameters
X */
X#define WINI_DISK	0x40	/* first device number of wini */
X#define PART_PER_DRIVE	5	/* how many partitions per wini drive */
X
X#define NSUPERCACHE	10	/* size of super block "cache" */
X#define NINODECACHE	20	/* size of inode "cache" */
X#define NEXECCACHE	10	/* size of a.out header "cache" */ 
X
X/*
X	Intra-Segment Copy
X
Xcopy(destination, source, length)
X*/
Xcopy(d,s,l)
Xchar *d, *s;
Xint l;
X{
X	while(l--)	*d++ = *s++;
X}
X
X/*
X	Inter-Segment Copy
X
Xlcopy(destination segment, offset, source segment, offset, length)
X*/
X/*lcopy(dseg, doff, sseg, soff, length)
Xint dseg, doff, sseg, soff, length;
X{	long from, to;
X
X	from = (long) sseg * (long) 16 + (long) soff;
X	to   = (long) dseg * (long) 16 + (long) doff;
X	phys_copy(from, to, (long) length);
X}*/
X
X/*
X	Zero Memory	(for clearing the bss segment)
X
Xzero_mem(segment, offset, length)
X*/
Xzero_mem(segment, offset, length)
Xunsigned int segment, offset, length;
X{
X	static char zero[1024];	/* this will get put in BSS, which is zeroed */
X	int count;
X
X#ifdef DEBUG
X	printf("zero_mem: 0x%x:0x%x 0x%x\n", segment, offset, length);
X#endif
X	count = length / 1024 + 1; /* caveat! trashes to an even 1K boundary */
X				/* (no prob for sequential process loading */
X	while(count--) {
X#ifdef DEBUG
X	printf("zero_mem: 0x%x:0x%x #%d\n", segment, offset, count);
X#endif
X		lcopy(segment, offset, ds(), zero, 1024);
X		segment += 64;
X	}
X}
X/*
X	Clicks
X
Xcalculate the number of clicks from bytes (a click is 16 bytes).  Compensate
Xfor partial clicks by rounding UP.
X*/
Xclicks(bytes)
Xlong bytes;
X{
X	return((bytes%16) ? (bytes>>CLICK_SHIFT)+1 : (bytes>>CLICK_SHIFT));
X}
X
X/*
X	Low-Level Block Read
X
X	procedure low_level_block_read
X		in device, block number, buffer address
X		returns Error_Status
X
XPerforms the lowest level data read by calling the disk I/O services
Xsupplied by the Operating System or ROM Support Routines.  No knowledge
Xof hard-disk partitions is exhibited.
X
X*/
Xint ll_Block_Read(device, block, buffer)
Xint device; unsigned int block; char *buffer;
X{
X	int status;
X#ifdef DEBUG1
X	printf("ll_Block_Read: device=0x%x block=0x%x buffer=0x%x\n", device, block, buffer);
X#endif
X#ifdef DEBUG
X	fgetc();
X#endif
X	status = diskio(READ, block*2, buffer, 1, device);
X	if(status > 255) {
X		errno = EIO;
X		printf("Disk Error reading sector 1 of block %d\n",block);
X		return(ERROR);
X	}
X	status = diskio(READ, block*2+1, buffer+SECTOR_SIZE, 1, device);
X	if(status > 255) {
X		errno = EIO;
X		printf("Disk Error reading sector 2 of block %d\n",block);
X		return(ERROR);
X	}
X	return(OK);
X}
X
X/*
X	Intermediate-Level Block Read
X
X	procedure read_block
X		in Super_Block, block number, buffer address
X		returns Error_Status
X
XReads a block from a disk by calling the Low-Level Block Read.  If
Xthe disk is paritioned, the partition information (stored in the super block)
Xis consulted to determine the offset into the disk of the partition.
X
X*/
X
Xint read_block(super, block, buffer)
XSUPERBLOCK super;
Xint block;
Xchar *buffer;
X{	int device;
X	unsigned int real_block;
X#ifdef DEBUG
X	printf("Block_Read..%u %ld\n", block, super->s_time);
X#endif
X	device = (super->s_dev < WINI_DISK) ? super->s_dev : 
X			0x80 + ((super->s_dev - WINI_DISK) / PART_PER_DRIVE);
X	real_block = block + (unsigned int) (super->s_time & 0xFFFF);
X	return(ll_Block_Read(device, real_block, buffer));
X}
X
X/*
X	Read Super-Block
X
X	procedure read_super_-_block
X		in device
X		returns Super_Block_Ptr
X
XRead the super-block off of the specified device, if this has not yet
Xbeen done.  A pointer to a super-block for the requested device is
Xreturned.  This structure will NOT be overwritten by subsequent
Xrequests for super-blocks on different devices.  NULL is returned if an
Xerror occurs, and the error code will be stored in the variable
X"errno".
X
XIf the disk being read from is a partition of a larger physical drive,
Xit's partition table is read and information about where the partition
Xlies on the physical device is stored in the super block.
X
XAllocation of Super-Blocks is made out of a pool of pre-allocated
Xblocks.  A count of how many blocks have been allocated is kept
Xso that new blocks can be painlessly allocated; since no de-allocation
Xis allowed, this is sufficent.  Prior to allocating a new blocks,
Xall allocated blocks are searched for the wanted block.  If it is not
Xfound, then a new one is allocated and loaded.
X
X*/
X
X/*
Xsearch sb list for this defive
Xif ! found
X	have to load it!...
X	allocate SB
X	if partitioned disk (wini)
X		read partition table
X		build partial super-block
X	else
X		set non-partitioned parameters in SB
X	read SB from disk
Xreturn sb
X
X*/
X
XSUPERBLOCK read_super(device)
Xint device;
X{
X	static struct super_block s_cache[NSUPERCACHE],
X				*last_super = s_cache;
X	SUPERBLOCK sb, last;
X	struct part_entry *partition;
X	long lowsec;		/* low sector of partition */
X
X	Set_Param(device);
X#ifdef TRACE
X	printf("read_super: device=%d...", device);
X#endif
X	/* Search the cache for a possibly already loaded super-block
X	 */
X	for(sb = s_cache;
X	    sb < last_super && sb->s_dev != device;
X	    sb++) ;
X
X	if (sb >= last_super) { /* load it */
X#ifdef TRACE
X		printf("loading super block\n");
X#endif
X		/* The Super-Block is not loaded.  Allocate a new one
X		 * and load it.
X		 */
X		sb = last_super++;	/* allocate new SB */
X		sb->s_dirt++;
X		sb->s_dev = device;
X
X		/* fix up device number and block number for partitioned
X		 * disks (winchesters)
X		 */
X		if (device >= WINI_DISK) { /* partitioned WINI device */
X			partition = Read_Part(device);
X			sb->s_time = partition->lowsec/2;
X			lowsec = partition->lowsec/2;
X		} else {
X			sb->s_time = 0;
X			lowsec = 0;
X		}
X
X		if(read_block(sb, SUPER_BLOCK, glb_block) == OK) {
X			copy(sb, glb_block, SUPER_SIZE);
X			sb->s_dev = device;
X			sb->s_time = lowsec;
X			sb->s_dirt = 1;
X#ifdef DEBUG
X			dump_super(sb);
X#endif
X		} else {
X			sb = NULL;
X		}
X	} else {
X#ifdef TRACE
X		printf("super block already loaded\n");
X#endif
X	}
X	return(sb);
X}
X
X/*
X	Set Parameters
X
X	procedure Set_Param
X		in device
X		return Ptr to parameter structure
X
XRead and set the disk track and cylinder size parameters appropriately.
XIf the device is a hard disk, read the hard disk parameters from their
XROM tables.
X*/
X
XSet_Param(device)
Xint device;
X{
X	struct param *param;
X
X	if(device < WINI_DISK) {
X		tracksiz = 9;
X		cylsiz = 18;
X	} else {
X/*		param = read_rom((device - WINI_DISK) / PART_PER_DRIVE);*/
X		tracksiz = 0x11;			/* not in my rom */
X/*		cylsiz = tracksiz * param->nr_heads;*/
X		cylsiz = tracksiz * 6;
X	}
X}
X
X/*
X	Read Rom
X
X	procecure read_rom
X		in device
X		out ptr to param structure
X
XRead the table for either wini 0 or wini 1 from ROM.
X
XMassive sections of code copied from kernel/xt_wini.c
X*/
Xstruct param *read_rom(device)
Xint device;
X{
X	int i, offset, segment, drtype;
X	long source, destination;
X	static struct param param;
X
X#define WIN_SELECT     0x322	/* winchester disk controller select port */
X
X	/*phys_copy( (long) source, (long) destination, (long) bytecount)*/
X
X	/* Read the switches from the controller */
X	port_in(WIN_SELECT, &i);
X
X	/* Calculate the drive type */
X	if(device == 0)
X		drtype = i & 3;
X	else
X		drtype = (i >> 2) & 3;
X
X	/* Copy the parameter vector from low memory */
X	source = ((long) 0 ) + 0x41 * 4;
X	destination = (((long) ds()) <<4) + glb_block;
X#ifdef DEBUG
X	printf("Read_Rom: src=%lx dest=%lx ds=0x%x\n", source, destination,ds());
X#endif
X/*	phys_copy(destination, source, 4L);*/
X/* !!!! switch to "lcopy" !!!! */
X
X	offset = *(int *) glb_block;		/* vec_table[2 * 0x41]; */
X	segment = *(int *) (glb_block+2);	/* vec_table[2 * 0x41 + 1]; */
X
X	/* Calculate the address off the parameters and copy them to buf */
X	source = ((long)segment << 4) + offset;
X/*	phys_copy(destination, source, 64L);*/
X/* !!!! switch to "lcopy" !!!! */
X
X#ifdef DEBUG
X	printf("Read_Rom: src=%lx dest=%lx offset=0x%x seg=0x%x\n", source, destination, offset, segment);
X#endif
X	/* Copy the parameters to the structure */
X	copy_param(&glb_block[drtype * 16], &param);
X#ifdef DEBUG
X	dump_param(&param);
X#endif
X	return(&param);
X}
X
X/*==========================================================================*
X *				copy_params				    *
X *==========================================================================*/
XPRIVATE copy_params(src, dest)
Xregister unsigned char *src;
Xregister struct param *dest;
X{
X/* This routine copies the parameters from src to dest
X * and sets the parameters for partition 0 and DEV_PER_DRIVE
X */
X
X  dest->nr_cyl = *(int *)src;
X  dest->nr_heads = (int)src[2];
X  dest->reduced_wr = *(int *)&src[3];
X  dest->wr_precomp = *(int *)&src[5];
X  dest->max_ecc = (int)src[7];
X  dest->ctrl_byte = (int)src[8];
X  dest->sectors = (int)src[14];		/* gpo */
X}
X
X/*
X	Read Partition Table
X
X	procedure Read_Part
X		in device
X		return Ptr to partition entry
X
XRead the partition table in sector 1 of a hard disk and return a pointer
Xto the partition entry for the device we're using.
X
X*/
Xstruct part_entry *Read_Part(device)
Xint device;
X{
X	int real_dev, partition;
X
X	if(device >= WINI_DISK) {
X		real_dev = 0x80 + ((device - WINI_DISK) / PART_PER_DRIVE);
X		partition = ((device - WINI_DISK) % PART_PER_DRIVE) -1;
X	} else {
X		real_dev = device;
X		partition = 0;
X	}
X
X#ifdef TRACE
X	printf("Read_Part: device=0x%x partition=0x%x\n", real_dev, partition);
X#endif
X	ll_Block_Read(real_dev, 0, glb_block);
X#ifdef DEBUG
X	dump_prt(glb_block + (partition * sizeof(struct part_entry)) + TABLEOFFSET);
X#endif
X	return(glb_block + (partition * sizeof(struct part_entry)) + TABLEOFFSET);
X}
X
X/*
X	Read i-node
X
X	procedure read_i_-_node
X		in super-block, i-node number
X		returns Inode_Ptr
X
XRead one i-node from the specified device.  If the inode has already
Xbeen read into the internal cache, it is not reread.  A pointer to an
Xinternal i-node is returned (this holds more information than an
Xordinary disk inode does).  NULL is returned if an error occurs, and
Xthe error code will be stored in the variable "errno".
X
X*/
X
XINODE read_inode(sb, inum)
XSUPERBLOCK sb;
Xint inum;
X{
X	static struct inode i_cache[NINODECACHE],
X				*last_inode = i_cache;
X	INODE i, last;
X
X	int blk_off, i_off;
X
X#ifdef TRACE
X	printf("read_inode: inum=%d...",inum);
X#endif
X	/* Search the cache for a possibly already loaded i-node
X	 */
X	for(i = i_cache;
X	    i < last_inode && (i->i_num != inum || i->i_dev != sb->s_dev);
X	    i++) ;
X
X	if(i >= last_inode ) {
X#ifdef TRACE
X		printf("loading inode\n");
X#endif
X		/* The i-node is not loaded.  Allocate a new one and load it
X		 */
X		i = last_inode++;	/* error check allocating too many */
X		i->i_dirt++;
X		i->i_count = 1;
X		i->i_num = inum;
X		i->i_dev = sb->s_dev;
X	
X		/* calculate the block and where in the block the inode is */
X		blk_off = (sb->s_imap_blocks + sb->s_zmap_blocks +2) + 
X			  (inum - 1)/INODES_PER_BLOCK;	/* fs/inode.c:8558 */
X#ifdef DEBUG
X		printf("iblock: i=0x%x 0x%x z=0x%x 0x%x\n", sb->s_imap_blocks, sb->s_zmap_blocks, (inum -1)/INODES_PER_BLOCK, INODES_PER_BLOCK);
X#endif
X
X		i_off = ((inum - 1) % INODES_PER_BLOCK);
X
X#ifdef DEBUG
X		printf("Reading Inode i=%d blk=%u off=0x%x\n",inum, blk_off, i_off);
X#endif
X		if(read_block(sb, blk_off, glb_block) == OK) {
X#ifdef DEBUG
X			printf("copy: 0x%x 0x%x 0x%x 0x%x\n",i, glb_block + i_off * INODE_SIZE, INODE_SIZE, i_off * INODE_SIZE);
X#endif
X			copy(i, glb_block + i_off * INODE_SIZE, INODE_SIZE);
X		} else {
X			i = NULL;
X		}
X	}
X#ifdef TRACE
X	else printf("inode already loaded\n");
X#endif
X	return(i);
X}
X
X/*
X	Read File
X
X	procedure read_file
X		in Inode_Ptr, buffer address
X		returns bytes read
X
XReads a disk file into the current data segment.  If the returned byte count
Xis zero, an error has occured and an error code is in the global variable 
X"errno".
X
X*/
X
Xint read_file(inode, buffer)
XINODE inode;
Xchar *buffer;
X{
X	int count, blocks;
X	SUPERBLOCK super;
X	static int indirect[BLOCK_SIZE/2];	/* buffer for indirect block */
X
X#ifdef TRACE
X	printf("Read_File: inum=%d\n", inode->i_num);
X#endif
X	blocks = 0;
X	super = read_super(inode->i_dev);
X	count = lload_blocks(super, buffer, inode->i_zone, NR_DZONE_NUM);
X	buffer += count*BLOCK_SIZE;
X	blocks += count;
X	if(inode->i_zone[NR_DZONE_NUM] != 0) {
X		read_block(super, inode->i_zone[NR_DZONE_NUM], indirect);
X		count = lload_blocks(super, buffer, indirect, BLOCK_SIZE/2);
X		blocks += count;
X	}
X	return(blocks);
X}
X
X/*
X	Local Load Blocks
X
X	procedure Local_Load_Blocks
X		in Super-Block_Ptr, buffer address, list address, list length
X		returns blocks read
X
XLoads disk blocks listed in the "list" into the current data segment.
XA count of blocks read is returned; if this count is zero, an error has
Xoccured and an error code is in the global variable "errno".
X*/
X
Xint lload_blocks(super, buffer, list, nlist)
XSUPERBLOCK super;
Xchar *buffer;
Xunsigned int *list;
Xint nlist;
X{
X	int count = 0;
X#ifdef DEBUG
X	printf("Loading file's data blocks\n");
X#endif
X	while(nlist > 0 && *list != 0) {
X		if(read_block(super, *list, buffer) != OK) {
X			count = 0;	/* Indicate error */
X			break;		/* get outa here! */
X		}
X		buffer += BLOCK_SIZE;
X		list++;
X		nlist--;
X		count++;
X	}
X	return(count);
X}
X
X/*
X	Load File
X
X	procedure  load_file
X		in Inode_Ptr, buffer address (segment)
X		returns a.out header
X
XLoad a Minix format binary object file into any location in memory (the
Xsegment being given in the buffer address).  An "a.out" header
Xstructure is returned.  This contains information on the text, data,
Xbss and stack sizes.  The text and data segments will have been loaded,
Xand the bss and stack segments zeroed at this point, so only writing
Xthe program's arguments to the stack segment remains to be done.  If an
Xerror occurs, NULL is returned and an error code is in the global
Xvariable "errno".
X
X*/
XAOUT load_file(inode, buffer)
XINODE inode;
Xchar *buffer;
X{
X	static struct exec e_cache[NEXECCACHE],
X				*last_exec = e_cache,
X				*e;
X
X	int count;
X	SUPERBLOCK super;
X	static int indirect[BLOCK_SIZE/2];	/* buffer for indirect block */
X
X#ifdef TRACE
X	printf("Load_File: inum=%d\n", inode->i_num);
X#endif
X	super = read_super(inode->i_dev);
X
X	/* first block requires special pampering because it has the
X	   a.out header in it */
X	read_block(super, inode->i_zone[0], glb_block);
X	e = last_exec++;	/* allocate a.out structure */
X	copy(e, glb_block, A_MINHDR);	/* the file *must* be stripped */
X	lcopy(buffer, 0, ds(), glb_block+A_MINHDR, BLOCK_SIZE - A_MINHDR);
X	buffer += (BLOCK_SIZE / 16) - (A_MINHDR / 16);
X
X	count = fload_blocks(super, buffer, inode->i_zone+1, NR_DZONE_NUM - 1);
X	buffer += count * BLOCK_SIZE / 16;
X
X	if(inode->i_zone[NR_DZONE_NUM] != 0) {
X		read_block(super, inode->i_zone[NR_DZONE_NUM], indirect);
X		count = fload_blocks(super, buffer, indirect, BLOCK_SIZE/2);
X	}
X	return(e);
X}
X
X/*
X	Far Load Blocks
X
X	procedure Far_Load_Blocks
X		in Super-Block_Ptr, buffer address, list address, list length
X		returns blocks read
X
XLoads disk blocks listed in the "list" into memory starting at the
Xsegment specified in "buffer address".  A count of blocks read is
Xreturned; if this count is zero, an error has occured and an error code
Xis in the global variable "errno".
X
X*/
Xint fload_blocks(super, buffer, list, nlist)
XSUPERBLOCK super;
Xchar *buffer;
Xunsigned int *list;
Xint nlist;
X{
X	int count = 0;
X#ifdef DEBUG
X	printf("Loading file's data blocks: glb_block= 0x%x:0x%x\n", ds(), glb_block);
X#endif
X	while(nlist > 0 && *list != 0) {
X		if(read_block(super, *list, glb_block) != OK) {
X			count = 0;	/* Indicate error */
X			break;		/* get outa here! */
X		}
X#ifdef DEBUG
X		printf("copy block %u to 0x%x:0x%x\n", *list, buffer, 0);
X#endif
X		lcopy(buffer, 0, ds(), glb_block, BLOCK_SIZE);
X		buffer += BLOCK_SIZE / 16;
X		list++;
X		nlist--;
X		count++;
X	}
X	return(count);
X}
X
X/*
X	Open File
X
X	procecure open_file
X		in filename
X		returns Inode_Ptr
X
XAttempt to open a file with a name of the format "device:path".  The device,
Xif given, specifies which physical drive and partition to load the file
Xfrom.  If an error occurs durring processing, a NULL Inode pointer is returned
Xand an error codes is put in the global variable "errno".
X
XNotes:
X1)	///usr//ast == /usr/ast
X2)	the last element is ALWAYS a file, so the case:
X		/usr/ast/
X	cannot occur.
X*/
XINODE open_file(filename)
Xchar *filename;
X{
X	int device;
X	char *path;
X	struct super_block *super;
X	struct inode *inode;
X
X#ifdef TRACE
X	printf("Open File %s\n",filename);
X#endif
X	path = device_map(filename,&device);
X			/* how to error check? */
X	if((super = read_super(device)) == NULL) {
X		errno = ENODEV;
X		return(NULL);
X	}
X
X	/* follow the pathname down the directory tree */
X	inode = follow_path(super, path);
X
X	/* We now have a proposed file to open.  Make sure it's a
X	 * "regular" file (as opposed to directory or device).
X	 */
X	if(inode != NULL && (inode->i_mode & I_TYPE) != I_REGULAR) {
X		errno = EISDIR;
X		return(NULL);
X	} else {
X		return(inode);
X	}
X}
X
X/*
X	Device Calculation
X
X	procedure device_map
X		in filename
X		out device number
X		returns path
X
XChecks the filename for a device:path form, and if there is a device
Xit is looked up in a table of device names and the given device number 
Xis returned, along with the part of the string that contains only the
Xpath.  If no device name exists, the default device (the one booted from)
Xis returned as the device, and the entire filename (which is just the path)
Xis returned.
X
XIf a invalid device name is given, a device number of -1 is returned, and
Xthe pathname is set as if the device was OK.  This is a feature.
X
X*/
X
Xchar *device_map(filename, device)
Xchar *filename;
Xint *device;
X{
X	char devicename[80];
X	char *s, *d;
X	static struct {
X		char *name;
X		int dev;
X	} map[] = {		/* list of existing devices */
X		"fd0", 0,	"fd1", 1,	"fd2", 2,	"fd3", 3,
X		"hd0.0", 0x40,	"hd0.1", 0x41,	"hd0.2", 0x42,
X				"hd0.3", 0x43,	"hd0.4", 0x44,
X		"hd1.0", 0x45,	"hd1.1", 0x46,	"hd1.2", 0x47,
X				"hd1.3", 0x48,	"hd1.4", 0x49,
X		"", -1
X	}, *mp;
X
X
X	for(s=filename, d=devicename; *s != '\0' && *s != ':'; ) {
X		*d++ = *s++;
X	}
X	if(*s == ':') s++;
X	*d = '\0';
X
X	if(*s == '\0') {
X		/* no ":" found, so there's no device name here */
X		*device = def_dev;
X		return(filename);
X	} else {
X		for(mp = map; mp->dev != -1 && strcmp(mp->name, devicename);
X		    mp++) ;
X		*device = mp->dev;
X		return(s);
X	}
X}
X
X
X/*
X	Follow Path
X
X	procedure follow_path
X		in Pathname, Super_Block
X		returns Inode_Ptr
X
XThe file given in _pathname_ is searched for on the device which the
Xsuper-block is on.  If it exists, an i-node for it is returned; otherwise
XNULL is returned and an error code is placed in the global variable "errno".
X
X*/
XINODE follow_path(super, path)
XSUPERBLOCK super;
Xchar *path;
X{
X	INODE inode;
X	char name[80];
X	int i_num;
X
X	i_num = ROOT_INODE;
X
X	while((path = next_name(path, name)) != NULL) {
X		/* there are more directories to descend.  First make sure
X		 * that our current directory is in fact a directory before
X		 * loading and searching it.
X		 */
X#ifdef DEBUG
X		printf("follow_path: looking for %s in %d\n", name, i_num);
X#endif
X		inode = read_inode(super, i_num);
X			/* obvious problem if an error occurs and read_inode
X			   returns NULL */
X		if((inode->i_mode & I_TYPE) != I_DIRECTORY) {
X			errno = ENOTDIR;
X			printf("ENOTDIR in follow_path\n");
X			return((struct inode *)NULL);
X		}
X
X		/* so far, so good.  Search this directory for the next
X		 * path element.
X		 */ /* inum=zero is an error situation; zero is root */
X		if((i_num = search_dir(inode, name)) == 0) {
X			errno = EINVAL;
X			printf("can't find %s!\n", name);
X			return((struct inode *)NULL);
X		}
X	}
X	inode = read_inode(super, i_num);
X		/* no real problem here if an error occurs and read_inode
X		   returns NULL... it will be detected 1 level up */
X	return(inode);
X}
X
X/*
X	Next Pathname Element
X
X	procedure next_name
X		in pathname
X		out next path element
X		returns remaining path after the current element
X
XMoves down the pathname for the next file name, and returns that and
Xthe remaining path after the next file name.  NULL is returned when
Xthe path is exhausted.
X
X*/
X
Xnext_name(path, name)
Xchar *path, *name;
X{	char *from, *to;
X
X	for(from = path; *from == '/'; from++) ;	/* skip all '/' */
X
X	for(to = name; *from != '/' && *from != '\0';) {
X		*to++ = *from++;
X	}
X	
X	*to = '\0';
X	if(to == name)
X		return(NULL);
X	else
X		return(from);
X}
X
X/*
X	Search Directory
X
X	procedure search_dir
X		in inode, name to search for
X		returns new inode number
X
XSearch the directory described by _inode_ for the file name in _name_.
XIf found, return the inode number of the found file; otherwise return 0.
X
XA static array is used as the destination for the directory load.  An
Xunchecked error condition exists if the directory is larger than this!
X
X*/
X
Xint search_dir(inode, name)
XINODE inode;
Xchar *name;
X{
X	dir_struct *dir, *lastdir;
X	static dir_struct directory[NR_DIR_ENTRIES * 8];
X		/* directory buffer 8 blocks long */
X	int count;	/* directory length in blocks */
X
X#ifdef DEBUG
X	printf("search_dir: inum=%d, name=%s.\n", inode->i_num, name);
X#endif
X	count = read_file(inode, directory);
X	lastdir = directory + NR_DIR_ENTRIES * count + 1;
X#ifdef DEBUG
X	printf("search_dir: count=%d dir=0x%x lastdir=0x%x\n", count, directory, lastdir);
X#endif
X	for(dir = directory; 
X	    dir <= lastdir && strcmp(dir->d_name, name) != 0;
X	    dir++)
X#ifdef DEBUG
X		printf("search_dir: checking %s\n",dir->d_name);
X#endif
X		;
X#ifdef DEBUG
X		printf("search_dir: found %s\n",dir->d_name);
X#endif
X	return(dir > lastdir ? NULL : dir->d_inum);
X}
X
X#ifdef DEBUG
X/* Dump Super-Block contents
X*/
Xdump_super(super)
XSUPBERBLOCK super;
X{
X	printf("\nSuper-Block Contents\n");
X	printf(" s_ninodes=%u      ", super->s_ninodes);
X	printf(" s_nzones=%u       ", super->s_nzones);		fputc('\n');
X	printf(" s_imap_blocks=%u  ", super->s_imap_blocks);
X	printf(" s_zmap_blocks=%u  ", super->s_zmap_blocks);
X	printf(" s_firstdatazone=%u", super->s_firstdatazone);	fputc('\n');
X	printf(" s_log_zone_size=%u", super->s_log_zone_size);
X	printf(" s_max_size=%u     ", super->s_max_size);
X	printf(" s_magic=%u        ", super->s_magic);		fputc('\n');
X
X	printf(" s_dev=%u          ", super->s_dev);
X	printf(" s_time=%ld        ", super->s_time);		fputc('\n');
X	fputc('\n');
X}
X/* dump partition table contents
X*/
Xdump_prt(part)
Xstruct part_entry *part;
X{
X	printf("\nPartition Table Contents\n");
X	printf(" at 0x%x       ", part);			fputc('\n');
X	printf(" bootind=0x%x  ", part->bootind);
X	printf(" start_head=%d ", part->start_head);		fputc('\n');
X	printf(" start_sec=%d  ", part->start_sec);
X	printf(" start_cyl=%d  ", part->start_cyl);		fputc('\n');
X	printf(" sysind=0x%x   ", part->sysind);
X	printf(" last_head=%d  ", part->last_head);		fputc('\n');
X	printf(" last_sec=%d   ", part->last_sec);
X	printf(" last_cyl=%d   ", part->last_cyl);		fputc('\n');
X	printf(" lowsec=%ld    ", part->lowsec);
X	printf(" size=%ld      ", part->size);			fputc('\n');
X	fputc('\n');
X}
X
X/* dump Fixed Disk parameter table
X */
Xdump_param(dest)
Xstruct param *dest;
X{
X	printf("\nParameter Table Contents\n");
X	printf(" nr_cyl=0x%x     ",  dest->nr_cyl);
X	printf(" nr_heads=0x%x   ", dest->nr_heads);		fputc('\n');
X	printf(" reduced_wr=0x%x ", dest->reduced_wr);
X	printf(" wr_precomp=0x%x ", dest->wr_precomp);		fputc('\n');
X	printf(" max_ecc=0x%x    ", dest->max_ecc);
X	printf(" ctrl_byte=0x%x  ", dest->ctrl_byte);		fputc('\n');
X	printf(" sectors=0x%x    ", dest->sectors);
X	fputc('\n');
X}
X#endif
X
X/* dump EXEC structure
X */
Xdump_exec(exec)
XAOUT exec;
X{
X	printf("\nEXEC Structure Contents\n");
X	printf(" magic= 0x%x, 0x%x", exec->a_magic[0], exec->a_magic[1]);
X	printf(" flags= 0x%x    ", exec->a_flags);		fputc('\n');
X	printf(" cpu= 0x%x      ", exec->a_cpu);
X	printf(" hdrlen= 0x%x   ", exec->a_hdrlen);
X	printf(" version= 0x%x  ", exec->a_version);		fputc('\n');
X	printf(" text size= %ld ", exec->a_text);
X	printf(" data size= %ld ", exec->a_data);
X	printf(" bss size= %ld  ", exec->a_bss);
X	printf(" total size= %ld", exec->a_total);		fputc('\n');
X	printf(" syms size= %ld ", exec->a_syms);
X	printf(" entry point= %ld", exec->a_no_entry);		fputc('\n');
X	fputc('\n');
X}
SHAR_EOF
if test 26336 -ne "`wc -c < 'b2b/loader.c'`"
then
    echo shar: error transmitting "'b2b/loader.c'" '(should have been 26336 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'kernel/makefile'" '(4125 characters)'
if test -f 'kernel/makefile'
then
    echo shar: will not over-write existing file "'kernel/makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'kernel/makefile'
X# The kernel dir contains xt_wini.c and at_wini.c.  Before running make
X# you must copy one of these to wini.c, depending on which controller you
X# have.  If you do not have a hard disk, you MUST choose one of them at random.
X# On a PC, cpp and cem are in /lib and will be removed to make space while
X# linking the kernel.  On an AT, they are in /usr/lib are are not removed.
X# This is because they have to be in /lib on a PC; the diskette is too small
X# for them to be in /usr/lib.  You can change this by editing commands/cc.c.
X#
X# This makefile has been modified for separate-directory compilation
X# ("newboot" project).
X#
X# The CFLAGS values are:
X#  -Di8088	- required on an 8088/80286/80386 CPU; forbidden on a 68000
X#  -F		- run cpp and cem sequentially (used when memory is tight)
X#  -T.		- put temporaries in working directory (when RAM disk is small)
X#
XCFLAGS	= -Di8088 -T. -I. -I../../kernel
XH	= ../../h
Xh	= ../h
XK	= ../../kernel
Xl	= /usr/lib
X
Xobj =	mpx88.s main.s tty.s floppy.s wini.s system.s proc.s \
X	clock.s memory.s console.s rs232.s printer.s table.s \
X	klib88.s dmp.s msgtrace.s
X#	rdmp.s rprintk.s rputc.s
X
Xcobjs =	main.s tty.s floppy.s wini.s system.s proc.s clock.s memory.s \
X	console.s rs232.s printer.s table.s dmp.s msgtrace.s
X#	rdmp.s rprintk.
X
Xkernel:	makefile $(obj) $l/libc.a
X	@echo "Start linking Kernel."
X	@asld -s -o kernel -i -T. $(obj) $l/libc.a $l/end.s >kernel.sym
X	@chmem =2048 kernel
X	@echo "Kernel done.  "
X
Xclean:
X	rm -f $(cobjs)
X
Xclock.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xclock.s:	$H/callnr.h
Xclock.s:	$H/com.h
Xclock.s:	$H/error.h
Xclock.s:	$H/signal.h
Xclock.s:	$K/glo.h
Xclock.s:	$K/proc.h
Xclock.s:	$K/clock.c
X	$(CC) $(CFLAGS) -c $K/clock.c
X
Xconsole.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xconsole.s:	$H/callnr.h
Xconsole.s:	$H/com.h
Xconsole.s:	$H/error.h
Xconsole.s:	$H/sgtty.h
Xconsole.s:	$H/signal.h
Xconsole.s:	$K/glo.h
Xconsole.s:	$K/proc.h
Xconsole.s:	$K/tty.h
Xconsole.s:	$K/ttymaps.h
X	$(CC) $(CFLAGS) -c $K/console.c
X
Xfloppy.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xfloppy.s:	$H/callnr.h
Xfloppy.s:	$H/com.h
Xfloppy.s:	$H/error.h
Xfloppy.s:	$K/glo.h
Xfloppy.s:	$K/proc.h
X	$(CC) $(CFLAGS) -c $K/floppy.c
X
Xdmp.s:		$K/const.h $K/type.h $H/const.h $H/type.h
Xdmp.s:		$H/callnr.h
Xdmp.s:		$H/com.h
Xdmp.s:		$H/error.h
Xdmp.s:		$K/glo.h
Xdmp.s:		$K/proc.h
X	$(CC) $(CFLAGS) -c $K/dmp.c
X
Xmain.s:		$K/const.h $K/type.h $H/const.h $H/type.h
Xmain.s:		$H/callnr.h
Xmain.s:		$h/com.h
Xmain.s:		$H/error.h
Xmain.s:		$K/glo.h
Xmain.s:		$K/proc.h
Xmain.s:		main.c
X	$(CC) $(CFLAGS) -c main.c
X
Xmemory.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xmemory.s:	$H/callnr.h
Xmemory.s:	$H/com.h
Xmemory.s:	$H/error.h
Xmemory.s:	$K/proc.h
Xmemory.s:	memory.c
X	$(CC) $(CFLAGS) -c memory.c
X
Xprinter.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xprinter.s:	$H/callnr.h
Xprinter.s:	$H/com.h
Xprinter.s:	$H/error.h
Xprinter.s:	$K/proc.h
Xprinter.s:	$K/glo.h
X	$(CC) $(CFLAGS) -c $K/printer.c
X
Xproc.s:		$K/const.h $K/type.h $H/const.h $H/type.h
Xproc.s:		$H/callnr.h
Xproc.s:		$H/com.h
Xproc.s:		$H/error.h
Xproc.s:		$K/glo.h
Xproc.s:		$K/proc.h
X	$(CC) $(CFLAGS) -c $K/proc.c
X
Xsystem.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xsystem.s:	$H/callnr.h
Xsystem.s:	$h/com.h
Xsystem.s:	$H/error.h
Xsystem.s:	$H/signal.h
Xsystem.s:	$K/glo.h
Xsystem.s:	$K/proc.h
Xsystem.s:	system.c
X	$(CC) $(CFLAGS) -c system.c
X
Xtable.s:	$K/const.h $K/type.h $H/const.h $H/type.h $H/com.h
Xtable.s:	$K/glo.h
Xtable.s:	$K/proc.h
Xtable.s:	$K/tty.h
X	$(CC) $(CFLAGS) -c $K/table.c
X
Xtty.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xtty.s:	$H/callnr.h
Xtty.s:	$H/com.h
Xtty.s:	$H/error.h
Xtty.s:	$H/sgtty.h
Xtty.s:	$H/signal.h
Xtty.s:	$K/glo.h
Xtty.s:	$K/proc.h
Xtty.s:	$K/tty.h
Xtty.s:	$K/ttymaps.h
X	$(CC) $(CFLAGS) -c $K/tty.c
X
Xrs232.s: $K/const.h $K/type.h $K/glo.h $K/proc.h $K/tty.h
Xrs232.s: $H/const.h
Xrs232.s: $H/type.h
Xrs232.s: $H/callnr.h
Xrs232.s: $H/com.h
Xrs232.s: $H/error.h
Xrs232.s: $H/sgtty.h
Xrs232.s: $H/signal.h
X	$(CC) $(CFLAGS) -c $K/rs232.c
X
Xwini.s:	$K/const.h $K/type.h $H/const.h $H/type.h
Xwini.s:	$H/callnr.h
Xwini.s:	$H/com.h
Xwini.s:	$H/error.h
Xwini.s:	$K/proc.h
X	$(CC) $(CFLAGS) -c $K/wini.c
X
Xmsgtrace.s:	$K/const.h
X	$(CC) $(CFLAGS) -c $K/msgtrace.c
SHAR_EOF
if test 4125 -ne "`wc -c < 'kernel/makefile'`"
then
    echo shar: error transmitting "'kernel/makefile'" '(should have been 4125 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'kernel/memory.c.diff'" '(1096 characters)'
if test -f 'kernel/memory.c.diff'
then
    echo shar: will not over-write existing file "'kernel/memory.c.diff'"
else
sed 's/^X//' << \SHAR_EOF > 'kernel/memory.c.diff'
X*** /usr/src/minix/kernel/memory.c	Wed Nov 30 16:40:14 1988
X--- memory.c	Mon Apr 17 11:24:18 1989
X***************
X*** 45,57 ****
X  /* Main program of the disk driver task. */
X  
X    int r, caller, proc_nr;
X-   extern unsigned sizes[8];
X    extern phys_bytes umap();
X  
X    /* Initialize this task. */
X    ram_origin[KMEM_DEV] = umap(proc_addr(SYSTASK), D, (vir_bytes) 0,
X                                (vir_bytes) 1);
X!   ram_limit[KMEM_DEV] = (phys_bytes) (sizes[0] + sizes[1]) << CLICK_SHIFT;
X    ram_limit[MEM_DEV] = MEM_BYTES;
X  
X    /* Here is the main loop of the memory task.  It waits for a message, carries
X--- 45,56 ----
X  /* Main program of the disk driver task. */
X  
X    int r, caller, proc_nr;
X    extern phys_bytes umap();
X  
X    /* Initialize this task. */
X    ram_origin[KMEM_DEV] = umap(proc_addr(SYSTASK), D, (vir_bytes) 0,
X                                (vir_bytes) 1);
X!   ram_limit[KMEM_DEV] = (phys_bytes) proc[NR_TASKS + HARDWARE].p_map[S].mem_vir;
X    ram_limit[MEM_DEV] = MEM_BYTES;
X  
X    /* Here is the main loop of the memory task.  It waits for a message, carries
SHAR_EOF
if test 1096 -ne "`wc -c < 'kernel/memory.c.diff'`"
then
    echo shar: error transmitting "'kernel/memory.c.diff'" '(should have been 1096 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'kernel/mpx88.s'" '(14359 characters)'
if test -f 'kernel/mpx88.s'
then
    echo shar: will not over-write existing file "'kernel/mpx88.s'"
else
sed 's/^X//' << \SHAR_EOF > 'kernel/mpx88.s'
X|
X| newboot/kernel/mpx88.s  1/5/88 Glen Overby
X|
X
X| This file is part of the lowest layer of the MINIX kernel.  All processing
X| switching and message handling is done here and in file "proc.c".  This file
X| is entered on every transition to the kernel, both for sending/receiving
X| messages and for all interrupts.  In all cases, the trap or interrupt
X| routine first calls save() to store the machine state in the proc table.
X| Then the stack is switched to k_stack.  Finally, the real trap or interrupt
X| handler (in C) is called.  When it returns, the interrupt routine jumps to
X| restart, to run the process or task whose number is in 'cur_proc'.
X|
X| The external entry points into this file are:
X|   s_call:	process or task wants to send or receive a message
X|   tty_int:	interrupt routine for each key depression and release
X|   rs232_int:	interrupt routine for each rs232 interrupt on port 1
X|   secondary:	interrupt routine for each rs232 interrupt on port 2
X|   lpr_int:	interrupt routine for each line printer interrupt
X|   disk_int:	disk interrupt routine
X|   wini_int:	winchester interrupt routine
X|   clock_int:	clock interrupt routine (HZ times per second)
X|   eth_int:	ethernet interrupt routine
X|   int00-int15:handlers for unused interrupt vectors < 16
X|   trp:	all traps with vector >= 16 are vectored here
X|   restart:	start running a task or process
X
X| These symbols MUST agree with the values in ../h/com.h to avoid disaster.
XK_STACK_BYTES	=  256
XWINI		=   -6
XFLOPPY		=   -5
XCLOCK		=   -3
XIDLE		= -999
XDISKINT		=    1
XCLOCK_TICK	=    2
X
X| The following procedures are defined in this file and called from outside it.
X.globl _tty_int, _rs232_int, _lpr_int, _clock_int, _disk_int, _wini_int
X.globl _eth_int, _s_call, _trp, _restart, _secondary_int
X.globl _int00, _int01, _int02, _int03, _int04, _int05, _int06, _int07
X.globl _int08, _int09, _int10, _int11, _int12, _int13, _int14, _int15
X
X| The following external procedures are called in this file.
X.globl _main, _sys_call, _interrupt, _keyboard, _panic, _unexpected_int, _trap
X.globl _pr_char, _rs232
X
X| Variables, data structures and miscellaneous.
X.globl _cur_proc, _proc_ptr, _scan_code, _int_mess, _k_stack, splimit
X.globl begtext, begdata, begbss
X
X| The following constants are offsets into the proc table.
Xesreg = 14
Xdsreg = 16
Xcsreg = 18
Xssreg = 20
XSP    = 22
XPC    = 24
XPSW   = 28
XSPLIM = 50
XOFF   = 18
XROFF  = 12
X
X.text
Xbegtext:
X|*===========================================================================*
X|*				MINIX					     *
X|*===========================================================================*
X				|Register Usage (entry):
X				|bx	scan code
X				||es:bp	sizes[] 
X				|cs	code segment
X				|ds	data segment
X				|sp	stack
X				|
X				|Register Use durring startup:
X				|dx	save DS...
XMINIX:				| this is the entry point for the MINIX kernel.
X	jmp M.0			| skip over the next few bytes
X	.word 0,0		| build puts DS at kernel text address 4
XM.0:	cli                     | disable interrupts
X				| set up segment registers
X	mov dx,ds
X	mov ss,dx		| ss now contains proper value
X	mov es,dx		| es now contains proper value [sizes wng]
X	mov _scan_code,bx	| save scan code from bootstrap
X
X| Debug Hack: Initialize the printer in hopes of being able to use it
X|	mov ax,#0
X|	int 0x17
X
X	seg cs
X	mov 4,dx
X
X| This is the C run-time start-off routine, taken from /usr/lib/crtso.s.
X| It's job is to take the arguments as put on the stack by boot stage 2,
X| which uses the same format as EXEC, and to parse them and set them up the
X| way _main expects them.
X	| Stack Set-Up:
X	|	environment
X	|	arguments
X	|	environment pointers
X	|	argument pointers
X	|	number of arguments
X	mov	bx,sp
X	mov	cx,(bx)
X	add	bx,*2
X	mov	ax,cx
X	inc	ax
X	shl	ax,#1
X	add	ax,bx
X	push	ax	| push environ
X	push	bx	| push argv
X	push	cx	| push argc
X
X	call _main		| start the main program of MINIX
XM.1:	jmp M.1			| this should never be executed
X
X
X|*===========================================================================*
X|*				s_call					     *
X|*===========================================================================*
X_s_call:			| System calls are vectored here.
X	call save		| save the machine state
X	mov bp,_proc_ptr	| use bp to access sys call parameters
X	push 2(bp)		| push(pointer to user message) (was bx)
X	push (bp)		| push(src/dest) (was ax)
X	push _cur_proc		| push caller
X	push 4(bp)		| push(SEND/RECEIVE/BOTH) (was cx)
X	call _sys_call		| sys_call(function, caller, src_dest, m_ptr)
X	jmp _restart		| jump to code to restart proc/task running
X
X
X|*===========================================================================*
X|*				tty_int					     *
X|*===========================================================================*
X_tty_int:			| Interrupt routine for terminal input.
X	call save		| save the machine state
X	call _keyboard		| process a keyboard interrupt
X	jmp _restart		| continue execution
X
X
X|*============================================================================
X|*				rs232_int				     *
X|*============================================================================
X_rs232_int:			| Interrupt routine for rs232 I/O.
X	call save		| save the machine state
X	mov ax,#1		| which unit caused the interrupt
X	push ax			| pass it as a parameter
X	call _rs232		| process a rs232 interrupt
X	jmp _restart		| continue execution
X
X
X|*============================================================================
X|*				secondary_int				     *
X|*============================================================================
X_secondary_int:			| Interrupt routine for rs232 port 2
X	call save		| save the machine state
X	mov ax,#2		| which unit caused the interrupt
X	push ax			| pass it as a parameter
X	call _rs232		| process a rs232 interrupt
X	jmp _restart		| continue execution
X
X
X|*===========================================================================*
X|*				lpr_int					     *
X|*===========================================================================*
X_lpr_int:			| Interrupt routine for terminal input.
X	call save		| save the machine state
X	call _pr_char		| process a line printer interrupt
X	jmp _restart		| continue execution
X
X
X|*===========================================================================*
X|*				disk_int				     *
X|*===========================================================================*
X_disk_int:			| Interrupt routine for the floppy disk.
X	call save		| save the machine state
X	mov _int_mess+2,*DISKINT| build message for disk task
X	mov ax,#_int_mess	| prepare to call interrupt(FLOPPY, &intmess)
X	push ax			| push second parameter
X	mov ax,*FLOPPY		| prepare to push first parameter
X	push ax			| push first parameter
X	call _interrupt		| this is the call
X	jmp _restart		| continue execution
X
X
X|*===========================================================================*
X|*				wini_int				     *
X|*===========================================================================*
X_wini_int:			| Interrupt routine for the winchester disk.
X	call save		| save the machine state
X	mov _int_mess+2,*DISKINT| build message for winchester task
X	mov ax,#_int_mess	| prepare to call interrupt(WINI, &intmess)
X	push ax			| push second parameter
X	mov ax,*WINI		| prepare to push first parameter
X	push ax			| push first parameter
X	call _interrupt		| this is the call
X	jmp _restart		| continue execution
X
X
X|*===========================================================================*
X|*				clock_int				     *
X|*===========================================================================*
X_clock_int:			| Interrupt routine for the clock.
X	call save		| save the machine state
X	mov _int_mess+2,*CLOCK_TICK	| build message for clock task
X	mov ax,#_int_mess	| prepare to call interrupt(CLOCK, &intmess)
X	push ax			| push second parameter
X	mov ax,*CLOCK		| prepare to push first parameter
X	push ax			| push first parameter
X	call _interrupt		| this is the call
X	jmp _restart		| continue execution
X
X
X|*===========================================================================*
X|*				eth_int					     *
X|*===========================================================================*
X_eth_int:			| Interrupt routine for ethernet input
X	call save		| save the machine state
X	call _dp8390_int	| call the handler
X	jmp _restart		| continue execution
X
X
X|*===========================================================================*
X|*				int00-15				     *
X|*===========================================================================*
X_int00:	call save		| interrupt through vector 0
X	mov ax,#0		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int01:	call save		| interrupt through vector 1
X	mov ax,#1		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int02:	call save		| interrupt through vector 1
X	mov ax,#2		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int03:	call save		| interrupt through vector 3
X	mov ax,#3		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int04:	call save		| interrupt through vector 4
X	mov ax,#4		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int05:	call save		| interrupt through vector 5
X	mov ax,#5		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int06:	call save		| interrupt through vector 6
X	mov ax,#6		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int07:	call save		| interrupt through vector 7
X	mov ax,#7		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int08:	call save		| interrupt through vector 8
X	mov ax,#8		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int09:	call save		| interrupt through vector 9
X	mov ax,#9		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int10:	call save		| interrupt through vector 10
X	mov ax,#10		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int11:	call save		| interrupt through vector 11
X	mov ax,#11		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int12:	call save		| interrupt through vector 12
X	mov ax,#12		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int13:	call save		| interrupt through vector 13
X	mov ax,#13		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int14:	call save		| interrupt through vector 14
X	mov ax,#14		| save vector number in ax
X	jmp vec_mess		| print message
X	
X_int15:	call save		| interrupt through vector 15
X	mov ax,#15		| save vector number in ax
X	jmp vec_mess		| print message
X	
Xvec_mess:			| this is where unexpected interrupts come.
X	push ax			| push the vector number
X	call _unexpected_int	| go panic
X	jmp _restart		| never executed
X
X
X|*===========================================================================*
X|*				trp					     *
X|*===========================================================================*
X_trp:				| this is where unexpected traps come.
X	call save		| save the machine state
X	call _trap		| print a message
X	jmp _restart		| this error is not fatal
X
X
X|*===========================================================================*
X|*				save					     *
X|*===========================================================================*
Xsave:				| save the machine state in the proc table.  
X	cld			| set direction flag to a known value
X	push ds			| stack: psw/cs/pc/ret addr/ds
X	push cs			| prepare to restore ds
X	pop ds			| ds has now been set to cs
X	mov ds,4		| word 4 in kernel text space contains ds value
X	pop ds_save		| stack: psw/cs/pc/ret addr
X	pop ret_save		| stack: psw/cs/pc
X	mov bx_save,bx		| save bx for later ; we need a free register
X	mov bx,_proc_ptr	| start save set up; make bx point to save area
X	add bx,*OFF		| bx points to place to store cs
X	pop PC-OFF(bx)		| store pc in proc table 
X	pop csreg-OFF(bx)	| store cs in proc table
X	pop PSW-OFF(bx)		| store psw 
X	mov ssreg-OFF(bx),ss	| store ss
X	mov SP-OFF(bx),sp	| sp as it was prior to interrupt
X	mov sp,bx		| now use sp to point into proc table/task save
X	mov bx,ds		| about to set ss
X	mov ss,bx		| set ss
X	push ds_save		| start saving all the registers, sp first
X	push es			| save es between sp and bp
X	mov es,bx		| es now references kernel memory too
X	push bp			| save bp
X	push di			| save di
X	push si			| save si
X	push dx			| save dx
X	push cx			| save cx
X	push bx_save		| save original bx
X	push ax			| all registers now saved
X	mov sp,#_k_stack	| temporary stack for interrupts
X	add sp,#K_STACK_BYTES	| set sp to top of temporary stack
X	mov splimit,#_k_stack	| limit for temporary stack
X	add splimit,#8		| splimit checks for stack overflow
X	cld
X	mov ax,ret_save		| ax = address to return to
X	jmp (ax)		| return to caller; Note: sp points to saved ax
X
X
X|*===========================================================================*
X|*				restart					     *
X|*===========================================================================*
X_restart:			| This routine sets up and runs a proc or task.
X	cmp _cur_proc,#IDLE	| restart user; if cur_proc = IDLE, go idle
X	je idle			| no user is runnable, jump to idle routine
X	cli			| disable interrupts
X	mov sp,_proc_ptr	| return to user, fetch regs from proc table
X	pop ax			| start restoring registers
X	pop bx			| restore bx
X	pop cx			| restore cx
X	pop dx			| restore dx
X	pop si			| restore si
X	pop di			| restore di
X	mov lds_low,bx		| lds_low contains bx
X	mov bx,sp		| bx points to saved bp register
X	mov bp,SPLIM-ROFF(bx)	| splimit = p_splimit
X	mov splimit,bp		| ditto
X	mov bp,dsreg-ROFF(bx)	| bp = ds
X	mov lds_low+2,bp	| lds_low+2 contains ds
X	pop bp			| restore bp
X	pop es			| restore es
X	mov sp,SP-ROFF(bx)	| restore sp
X	mov ss,ssreg-ROFF(bx)	| restore ss using the value of ds
X	push PSW-ROFF(bx)	| push psw
X	push csreg-ROFF(bx)	| push cs
X	push PC-ROFF(bx)	| push pc
X	lds bx,lds_low		| restore ds and bx in one fell swoop
X	iret			| return to user or task
X
X
X|*===========================================================================*
X|*				idle					     *
X|*===========================================================================*
Xidle:				| executed when there is no work 
X	sti			| enable interrupts
XL3:  	wait			| just idle while waiting for interrupt
X	jmp L3			| loop until interrupt
X
X
X
X|*===========================================================================*
X|*				data					     *
X|*===========================================================================*
X.data
Xbegdata:
Xbx_save: .word 0		| storage for bx
Xds_save: .word 0		| storage for ds
Xret_save:.word 0		| storage for return address
Xlds_low: .word 0,0		| storage used for restoring bx
X.bss
Xbegbss:
SHAR_EOF
if test 14359 -ne "`wc -c < 'kernel/mpx88.s'`"
then
    echo shar: error transmitting "'kernel/mpx88.s'" '(should have been 14359 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'kernel/system.c.diff'" '(3222 characters)'
if test -f 'kernel/system.c.diff'
then
    echo shar: will not over-write existing file "'kernel/system.c.diff'"
else
sed 's/^X//' << \SHAR_EOF > 'kernel/system.c.diff'
X*** /usr/src/minix/kernel/system.c	Tue Oct 11 00:46:46 1988
X--- system.c	Fri Jan 27 23:57:35 1989
X***************
X*** 15,20 ****
X--- 15,21 ----
X   *   SYS_SIG	 send a signal to a process
X   *   SYS_KILL	 cause a signal to be sent via MM
X   *   SYS_COPY	 requests a block of data to be copied between processes
X+  *   SYS_GETMAP  allow MM to retrieve a process' memory map
X   *
X   * Message type m1 is used for all except SYS_SIG and SYS_COPY, both of
X   * which need special parameter types.
X***************
X*** 25,30 ****
X--- 26,33 ----
X   * |------------+---------+---------+---------+---------|
X   * | SYS_NEWMAP | proc nr |         |         | map ptr |
X   * |------------+---------+---------+---------+---------|
X+  * | SYS_GETMAP | proc nr |         |         | map ptr |
X+  * |------------+---------+---------+---------+---------|
X   * | SYS_EXEC   | proc nr |         | new sp  |         |
X   * |------------+---------+---------+---------+---------|
X   * | SYS_XIT    | parent  | exitee  |         |         |
X***************
X*** 98,103 ****
X--- 101,107 ----
X  	    case SYS_SIG:	r = do_sig(&m);		break;
X  	    case SYS_KILL:	r = do_kill(&m);	break;
X  	    case SYS_COPY:	r = do_copy(&m);	break;
X+  	    case SYS_GETMAP:	r = do_getmap(&m);	break;
X  	    default:		r = E_BAD_FCN;
X  	}
X  
X***************
X*** 453,458 ****
X--- 457,463 ----
X  
X    register struct proc *rp, *mmp;
X  
X+   msg_trace(HARDWARE, proc_nr, 0);
X    rp = proc_addr(proc_nr);
X    if ((rp->p_flags & PENDING) == 0)
X  	sig_procs++;		/* incr if a new proc is now pending */
X***************
X*** 536,538 ****
X--- 541,580 ----
X    pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
X    return(seg_base + pa);
X  }
X+ 
X+ /*===========================================================================*
X+  *				do_getmap				     * 
X+  *===========================================================================*/
X+ PRIVATE int do_getmap(m_ptr)
X+ message *m_ptr;			/* pointer to request message */
X+ {
X+ /* Handle sys_getmap().  Send the memory map to MM. */
X+ 
X+   register struct proc *rp, *rsrc;
X+   phys_bytes src_phys, dst_phys, pn;
X+   vir_bytes vmm, vsys, vn;
X+   int caller;			/* whose space has the new map (usually MM) */
X+   int k;			/* process whose map is to be loaded */
X+   int old_flags;		/* value of flags before modification */
X+   struct mem_map *map_ptr;	/* virtual address of map inside caller (MM) */
X+ 
X+   /* Extract message parameters and copy new memory map from MM. */
X+   caller = m_ptr->m_source;
X+   k = m_ptr->PROC1;
X+   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
X+   if (k < -NR_TASKS || k >= NR_PROCS) return(E_BAD_PROC);
X+   rp = proc_addr(k);		/* ptr to entry of user getting new map */
X+   rsrc = proc_addr(caller);	/* ptr to MM's proc entry */
X+   vn = NR_SEGS * sizeof(struct mem_map);
X+   pn = vn;
X+   vmm = (vir_bytes) map_ptr;	/* careful about sign extension */
X+   vsys = (vir_bytes) rp->p_map;	/* again, careful about sign extension */
X+   if ( (dst_phys = umap(rsrc, D, vmm, vn)) == 0)
X+ 	panic("bad call to sys_newmap (src)", NO_NUM);
X+   if ( (src_phys = umap(proc_addr(SYSTASK), D, vsys, vn)) == 0)
X+ 	panic("bad call to sys_newmap (dst)", NO_NUM);
X+   phys_copy(src_phys, dst_phys, pn);
X+ 
X+   return(OK);
X+ }
X+ 
SHAR_EOF
if test 3222 -ne "`wc -c < 'kernel/system.c.diff'`"
then
    echo shar: error transmitting "'kernel/system.c.diff'" '(should have been 3222 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'fs/glo.h.diff'" '(502 characters)'
if test -f 'fs/glo.h.diff'
then
    echo shar: will not over-write existing file "'fs/glo.h.diff'"
else
sed 's/^X//' << \SHAR_EOF > 'fs/glo.h.diff'
X*** /usr/src/minix/fs/glo.h	Sat Aug 13 14:20:38 1988
X--- glo.h	Tue Apr 18 11:30:36 1989
X***************
X*** 6,11 ****
X--- 6,12 ----
X  EXTERN int reviving;		/* number of pipe processes to be revived */
X  EXTERN file_pos rdahedpos;	/* position to read ahead */
X  EXTERN struct inode *rdahed_inode;	/* pointer to inode to read ahead */
X+ EXTERN dev_nr root_dev;		/* Device that ROOT is mounted on */
X  
X  /* The parameters of the call are kept here. */
X  EXTERN message m;		/* the input message itself */
SHAR_EOF
if test 502 -ne "`wc -c < 'fs/glo.h.diff'`"
then
    echo shar: error transmitting "'fs/glo.h.diff'" '(should have been 502 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'fs/inode.c.diff'" '(686 characters)'
if test -f 'fs/inode.c.diff'
then
    echo shar: will not over-write existing file "'fs/inode.c.diff'"
else
sed 's/^X//' << \SHAR_EOF > 'fs/inode.c.diff'
X*** /usr/src/minix/fs/inode.c	Mon Oct 10 19:18:15 1988
X--- inode.c	Tue Apr 18 11:31:38 1989
X***************
X*** 116,122 ****
X  	err_code = ENFILE;
X  	major = (int) (sp->s_dev >> MAJOR) & BYTE;
X  	minor = (int) (sp->s_dev >> MINOR) & BYTE;
X! 	if (sp->s_dev == ROOT_DEV)
X  		printf("Out of i-nodes on root device (RAM disk)\n");
X  	else
X  		printf("Out of i-nodes on device %d/%d\n", major, minor);
X--- 116,122 ----
X  	err_code = ENFILE;
X  	major = (int) (sp->s_dev >> MAJOR) & BYTE;
X  	minor = (int) (sp->s_dev >> MINOR) & BYTE;
X! 	if (sp->s_dev == root_dev)
X  		printf("Out of i-nodes on root device (RAM disk)\n");
X  	else
X  		printf("Out of i-nodes on device %d/%d\n", major, minor);
SHAR_EOF
if test 686 -ne "`wc -c < 'fs/inode.c.diff'`"
then
    echo shar: error transmitting "'fs/inode.c.diff'" '(should have been 686 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'fs/makefile'" '(5603 characters)'
if test -f 'fs/makefile'
then
    echo shar: will not over-write existing file "'fs/makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'fs/makefile'
X# On a PC, cpp and cem are in /lib and will be removed to make space while
X# linking the kernel.  On an AT, they are in /usr/lib are are not removed.
X# This is because they have to be in /lib on a PC; the diskette is too small
X# for them to be in /usr/lib.
X#
X# This makefile has been modified for separate-directory compilation
X# ("newboot" project).
X#
XCFLAGS	= -Di8088 -T. -I. -I../../fs
XH	= ../../h
X# h	= h/const.h
Xh	= ../../h
XF	= ../../fs
Xf	= ../../fs
XL=/usr/lib
X
Xobj =	main.s open.s read.s write.s pipe.s device.s \
X	path.s mount.s link.s super.s inode.s cache.s filedes.s \
X	stadir.s protect.s time.s misc.s utility.s table.s putc.s
X
Xfs:	makefile   $L/head.s $(obj) $L/libc.a $L/end.s
X	@echo "Start linking FS.  "
X	@cc -i -o fs -T. $(obj) ../lib/syslib.s
X#	@asld  -o fs -T. $L/head.s $(obj) ../lib/syslib.s $L/libc.a $L/end.s
X	@chmem =2000 fs
X	@echo "FS done.  "
X
Xclean:
X	rm -f $(obj)
X
Xcache.s:	$F/const.h $F/type.h $h/const.h $H/type.h
Xcache.s:	$H/error.h
Xcache.s:	$F/buf.h
Xcache.s:	$F/file.h
Xcache.s:	$F/fproc.h
Xcache.s:	$F/glo.h
Xcache.s:	$F/inode.h
Xcache.s:	$F/super.h
Xcache.s:	cache.c
X	$(CC) $(CFLAGS) -c cache.c
X
Xdevice.s:	$F/const.h $F/type.h $h/const.h $H/type.h
Xdevice.s:	$H/com.h
Xdevice.s:	$H/error.h
Xdevice.s:	$F/dev.h
Xdevice.s:	$F/file.h
Xdevice.s:	$F/fproc.h
Xdevice.s:	$F/glo.h
Xdevice.s:	$F/inode.h
Xdevice.s:	$F/param.h
X	$(CC) $(CFLAGS) -c $f/device.c
X
Xfiledes.s:	$F/const.h $F/type.h $H/const.h $H/type.h
Xfiledes.s:	$H/error.h
Xfiledes.s:	$F/file.h
Xfiledes.s:	$F/fproc.h
Xfiledes.s:	$F/glo.h
Xfiledes.s:	$F/inode.h
X	$(CC) $(CFLAGS) -c $f/filedes.c
X
Xinode.s:	$F/const.h $F/type.h $h/const.h $H/type.h
Xinode.s:	$H/error.h
Xinode.s:	$F/buf.h
Xinode.s:	$F/file.h
Xinode.s:	$F/fproc.h
Xinode.s:	$F/glo.h
Xinode.s:	$F/inode.h
Xinode.s:	$F/super.h
Xinode.s:	inode.c
X	$(CC) $(CFLAGS) -c inode.c
X
Xlink.s:		$F/const.h $F/type.h $H/const.h $H/type.h
Xlink.s:		$H/error.h
Xlink.s:		$F/buf.h
Xlink.s:		$F/file.h
Xlink.s:		$F/fproc.h
Xlink.s:		$F/glo.h
Xlink.s:		$F/inode.h
Xlink.s:		$F/param.h
X	$(CC) $(CFLAGS) -c $f/link.c
X
Xmain.s:		$F/const.h $F/type.h $h/const.h $H/type.h
Xmain.s:		$H/callnr.h
Xmain.s:		$h/com.h
Xmain.s:		$H/error.h
Xmain.s:		$F/buf.h
Xmain.s:		$F/file.h
Xmain.s:		$F/fproc.h
Xmain.s:		$F/glo.h
Xmain.s:		$F/inode.h
Xmain.s:		$F/param.h
Xmain.s:		$F/super.h
Xmain.s:		main.c
X	$(CC) $(CFLAGS) -c main.c
X
Xmisc.s:		$F/const.h $F/type.h $h/const.h $H/type.h
Xmisc.s:		$H/callnr.h
Xmisc.s:		$H/com.h
Xmisc.s:		$H/error.h
Xmisc.s:		$F/buf.h
Xmisc.s:		$F/file.h
Xmisc.s:		$F/fproc.h
Xmisc.s:		$F/glo.h
Xmisc.s:		$F/inode.h
Xmisc.s:		$F/param.h
Xmisc.s:		$F/super.h
Xmisc.s:		misc.c
X	$(CC) $(CFLAGS) -c misc.c
X
Xmount.s:	$F/const.h $F/type.h $h/const.h $H/type.h
Xmount.s:	$H/error.h
Xmount.s:	$F/buf.h
Xmount.s:	$F/file.h
Xmount.s:	$F/fproc.h
Xmount.s:	$F/glo.h
Xmount.s:	$F/inode.h
Xmount.s:	$F/param.h
Xmount.s:	$F/super.h
X	$(CC) $(CFLAGS) -c $f/mount.c
X
Xopen.s:		$F/const.h $F/type.h $H/const.h $H/type.h
Xopen.s:		$H/callnr.h
Xopen.s:		$H/error.h
Xopen.s:		$F/buf.h
Xopen.s:		$F/file.h
Xopen.s:		$F/fproc.h
Xopen.s:		$F/glo.h
Xopen.s:		$F/inode.h
Xopen.s:		$F/param.h
X	$(CC) $(CFLAGS) -c $f/open.c
X
Xpath.s:		$F/const.h $F/type.h $H/const.h $H/type.h
Xpath.s:		$H/error.h
Xpath.s:		$F/buf.h
Xpath.s:		$F/file.h
Xpath.s:		$F/fproc.h
Xpath.s:		$F/glo.h
Xpath.s:		$F/inode.h
Xpath.s:		$F/super.h
X	$(CC) $(CFLAGS) -c $f/path.c
X
Xpipe.s:		$F/const.h $F/type.h $H/const.h $H/type.h
Xpipe.s:		$H/callnr.h
Xpipe.s:		$H/com.h
Xpipe.s:		$H/error.h
Xpipe.s:		$H/signal.h
Xpipe.s:		$F/file.h
Xpipe.s:		$F/fproc.h
Xpipe.s:		$F/glo.h
Xpipe.s:		$F/inode.h
Xpipe.s:		$F/param.h
X	$(CC) $(CFLAGS) -c $f/pipe.c
X
Xprotect.s:	$F/const.h $F/type.h $H/const.h $H/type.h
Xprotect.s:	$H/error.h
Xprotect.s:	$F/buf.h
Xprotect.s:	$F/file.h
Xprotect.s:	$F/fproc.h
Xprotect.s:	$F/glo.h
Xprotect.s:	$F/inode.h
Xprotect.s:	$F/param.h
Xprotect.s:	$F/super.h
X	$(CC) $(CFLAGS) -c $f/protect.c
X
Xputc.s:		$F/const.h $F/type.h $H/const.h $H/type.h
Xputc.s:		$H/com.h
X	$(CC) $(CFLAGS) -c $f/putc.c
X
Xread.s:		$F/const.h $F/type.h $h/const.h $H/type.h
Xread.s:		$H/com.h
Xread.s:		$H/error.h
Xread.s:		$F/buf.h
Xread.s:		$F/file.h
Xread.s:		$F/fproc.h
Xread.s:		$F/glo.h
Xread.s:		$F/inode.h
Xread.s:		$F/param.h
Xread.s:		$F/super.h
X	$(CC) $(CFLAGS) -c $f/read.c
X
Xstadir.s:	$F/const.h $F/type.h $H/const.h $H/type.h
Xstadir.s:	$H/error.h
Xstadir.s:	$H/stat.h
Xstadir.s:	$F/file.h
Xstadir.s:	$F/fproc.h
Xstadir.s:	$F/glo.h
Xstadir.s:	$F/inode.h
Xstadir.s:	$F/param.h
X	$(CC) $(CFLAGS) -c $f/stadir.c
X
Xsuper.s:	$F/const.h $F/type.h $h/const.h $H/type.h
Xsuper.s:	$H/error.h
Xsuper.s:	$F/buf.h
Xsuper.s:	$F/inode.h
Xsuper.s:	$F/super.h
Xsuper.s:	super.c
X	$(CC) $(CFLAGS) -c super.c
X
Xtable.s:	$F/const.h $F/type.h $H/const.h $H/type.h
Xtable.s:	$H/com.h
Xtable.s:	$H/callnr.h
Xtable.s:	$H/error.h
Xtable.s:	$H/stat.h
Xtable.s:	$F/buf.h
Xtable.s:	$F/dev.h
Xtable.s:	$F/file.h
Xtable.s:	$F/fproc.h
Xtable.s:	$F/glo.h
Xtable.s:	$F/inode.h
Xtable.s:	$F/super.h
X	$(CC) $(CFLAGS) -c $f/table.c
X
Xtime.s:		$F/const.h $F/type.h $H/const.h $H/type.h
Xtime.s:		$H/callnr.h
Xtime.s:		$H/com.h
Xtime.s:		$H/error.h
Xtime.s:		$F/file.h
Xtime.s:		$F/fproc.h
Xtime.s:		$F/glo.h
Xtime.s:		$F/inode.h
Xtime.s:		$F/param.h
X	$(CC) $(CFLAGS) -c $f/time.c
X
Xutility.s:	$F/const.h $F/type.h $h/const.h $H/type.h
Xutility.s:	$H/com.h
Xutility.s:	$H/error.h
Xutility.s:	$F/buf.h
Xutility.s:	$F/file.h
Xutility.s:	$F/fproc.h
Xutility.s:	$F/glo.h
Xutility.s:	$F/inode.h
Xutility.s:	$F/param.h
Xutility.s:	$F/super.h
Xutility.s:	utility.c
X	$(CC) $(CFLAGS) -c utility.c
X
Xwrite.s:	$F/const.h $F/type.h $H/const.h $H/type.h
Xwrite.s:	$H/error.h
Xwrite.s:	$F/buf.h
Xwrite.s:	$F/file.h
Xwrite.s:	$F/fproc.h
Xwrite.s:	$F/glo.h
Xwrite.s:	$F/inode.h
Xwrite.s:	$F/super.h
X	$(CC) $(CFLAGS) -c $f/write.c
SHAR_EOF
if test 5603 -ne "`wc -c < 'fs/makefile'`"
then
    echo shar: error transmitting "'fs/makefile'" '(should have been 5603 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0