#undef EXTERN /* <minix/const.h> defined this */
#define EXTERN /* so we get proc & mproc */
+#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../kernel/const.h"
#include "../../kernel/type.h"
#include "../../kernel/proc.h"
#include <time.h>
#include <errno.h>
#include <signal.h>
-#include <ibm/portio.h>
+#include <minix/portio.h>
#include <ibm/cmos.h>
#include <sys/svrctl.h>
#undef EXTERN
#define EXTERN
+#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../servers/pm/const.h"
#include "../../servers/pm/type.h"
#include "../../servers/pm/mproc.h"
#include <pm/type.h>
#include <pm/mproc.h>
+#include <kernel/arch/i386/include/archtypes.h>
#include <kernel/const.h>
#include <kernel/type.h>
#include <kernel/proc.h>
#include <sys/ptrace.h>
#include "proto.h"
+#include <kernel/arch/i386/include/archtypes.h>
#include <kernel/const.h>
#include <kernel/type.h>
#include <kernel/proc.h>
#include <setjmp.h>
#include "proto.h"
+#include "../../kernel/arch/i386/include/archtypes.h"
#include <kernel/const.h>
#include <kernel/type.h>
#include <kernel/proc.h>
#include <stdio.h>
#include <ttyent.h>
+#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../kernel/const.h"
#include "../../kernel/type.h"
#include "../../kernel/proc.h"
#include <string.h>
#include <stdlib.h>
+#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../kernel/const.h"
#include "../../kernel/type.h"
#include "../../kernel/config.h"
#include <minix/type.h>
#include <minix/const.h>
+#include "../../kernel/arch/i386/include/archtypes.h"
#include "../../servers/pm/mproc.h"
#include "../../kernel/const.h"
#include "../../kernel/proc.h"
u8_t steps; /* steps per cylinder (2 = double step) */
u8_t test; /* sector to try for density test */
u8_t rate; /* data rate (2=250, 1=300, 0=500 kbps) */
- u8_t start; /* motor start (clock ticks) */
+ clock_t start; /* motor start (clock ticks) */
u8_t gap; /* gap size */
u8_t spec1; /* first specify byte (SRT/HUT) */
} fdensity[NT] = {
if (OK != (s=sys_getmachine(&machine))) {
panic("MEM","Couldn't get machine information.",s);
}
- if (! machine.prot) {
- m_geom[MEM_DEV].dv_size = cvul64(0x100000); /* 1M for 8086 systems */
- } else {
-#if _WORD_SIZE == 2
- m_geom[MEM_DEV].dv_size = cvul64(0x1000000); /* 16M for 286 systems */
-#else
- m_geom[MEM_DEV].dv_size = cvul64(0xFFFFFFFF); /* 4G-1 for 386 systems */
-#endif
- }
-#else /* !(CHIP == INTEL) */
-#if (CHIP == M68000)
- m_geom[MEM_DEV].dv_size = cvul64(MEM_BYTES);
-#else /* !(CHIP == M68000) */
-#error /* memory limit not set up */
-#endif /* !(CHIP == M68000) */
+ m_geom[MEM_DEV].dv_size = cvul64(0xFFFFFFFF); /* 4G-1 for 386 systems */
#endif /* !(CHIP == INTEL) */
}
+++ /dev/null
-# Makefile for rescue driver
-DRIVER = rescue
-
-# directories
-u = /usr
-i = $u/include
-s = $i/sys
-m = $i/minix
-b = $i/ibm
-d = ..
-
-# programs, flags, etc.
-MAKE = exec make
-CC = exec cc
-CFLAGS = -I$i $(CPROFILE)
-LDFLAGS = -i
-LIBS = -lsys -lsysutil
-
-OBJ = rescue.o
-LIBDRIVER = $d/libdriver/driver.o
-
-
-# build local binary
-all build: $(DRIVER)
-$(DRIVER): $(OBJ) $(LIBDRIVER)
- $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBDRIVER) $(LIBS)
- install -S 8k $(DRIVER)
-
-$(LIBDRIVER):
- cd $d/libdriver && $(MAKE)
-
-
-# install with other drivers
-install: /sbin/$(DRIVER)
-/sbin/$(DRIVER): $(DRIVER)
- install -o root -cs $? $@
-
-# clean up local files
-clean:
- rm -f $(DRIVER) *.o *.bak
-
-
-depend:
- /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c ../libdriver/*.c > .depend
-
-# Include generated dependencies.
-include .depend
-
+++ /dev/null
-/* This file contains the rescue device driver (/dev/rescue)
- *
- * Changes:
- * Oct 21, 1992 created (Jorrit N. Herder)
- */
-
-#include "../drivers.h"
-#include "../libdriver/driver.h"
-#include "../../kernel/const.h"
-#include "../../kernel/config.h"
-#include "../../kernel/type.h"
-
-#define VERBOSE 0 /* enable/ disable messages */
-#define NR_DEVS 1 /* number of rescue devices */
-#define RESCUE_KBYTES 128 /* default size in kilobytes */
-
-PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */
-PRIVATE int m_seg[NR_DEVS]; /* segment index of each device */
-PRIVATE int m_device; /* current device */
-
-extern int errno; /* error number for PM calls */
-
-FORWARD _PROTOTYPE( void m_init, (int argc, char **argv) );
-FORWARD _PROTOTYPE( char *m_name, (void) );
-FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
-FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position,
- iovec_t *iov, unsigned nr_req, int safe));
-FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) );
-FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
-
-/* Entry points to this driver. */
-PRIVATE struct driver m_dtab = {
- m_name, /* current device's name */
- m_do_open, /* open or mount */
- do_nop, /* nothing on a close */
- do_diocntl, /* standard I/O controls */
- m_prepare, /* prepare for I/O on a given minor device */
- m_transfer, /* do the I/O */
- nop_cleanup, /* no need to clean up */
- m_geometry, /* memory device "geometry" */
- nop_signal, /* system signals */
- nop_alarm,
- nop_cancel,
- nop_select,
- NULL,
- NULL
-};
-
-
-/*===========================================================================*
- * main *
- *===========================================================================*/
-PUBLIC int main(int argc, char **argv)
-{
-/* Main program. Initialize the rescue driver and start the main loop. */
- m_init(argc, argv);
- driver_task(&m_dtab);
- return(OK);
-}
-
-/*===========================================================================*
- * m_name *
- *===========================================================================*/
-PRIVATE char *m_name()
-{
-/* Return a name for the current device. */
- static char name[] = "rescue";
- return name;
-}
-
-/*===========================================================================*
- * m_prepare *
- *===========================================================================*/
-PRIVATE struct device *m_prepare(device)
-int device;
-{
-/* Prepare for I/O on a device: check if the minor device number is ok. */
- if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
- m_device = device;
-
- return(&m_geom[device]);
-}
-
-/*===========================================================================*
- * m_transfer *
- *===========================================================================*/
-PRIVATE int m_transfer(proc_nr, opcode, position, iov, nr_req, safe)
-int proc_nr; /* process doing the request */
-int opcode; /* DEV_GATHER or DEV_SCATTER */
-off_t position; /* offset on device to read or write */
-iovec_t *iov; /* pointer to read or write request vector */
-unsigned nr_req; /* length of request vector */
-int safe; /* safe copies? */
-{
-/* Read or write one the driver's minor devices. */
- int seg;
- unsigned count, left, chunk;
- vir_bytes user_vir, vir_offset = 0;
- struct device *dv;
- unsigned long dv_size;
- int s;
-
- /* Get and check minor device number. */
- if ((unsigned) m_device > NR_DEVS - 1) return(ENXIO);
- dv = &m_geom[m_device];
- dv_size = cv64ul(dv->dv_size);
-
- while (nr_req > 0) {
-
- /* How much to transfer and where to / from. */
- count = iov->iov_size;
- user_vir = iov->iov_addr;
-
- /* Virtual copying. For rescue device. */
- if (position >= dv_size) {
- return(OK); /* check for EOF */
- }
- if (position + count > dv_size) count = dv_size - position;
- seg = m_seg[m_device];
-
- if (opcode == DEV_GATHER) { /* copy actual data */
- int r;
- if(safe) {
- if((r=sys_safecopyto(proc_nr, user_vir, vir_offset,
- position, count, seg)) != OK) {
- printf("rescue: safecopy failed to user (proc %d, grant %d), error %d\n",
- proc_nr, user_vir, r);
- return EIO;
- }
- } else {
- sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count);
- }
- } else {
- if(safe) {
- if(sys_safecopyfrom(proc_nr, user_vir, vir_offset,
- position, count, seg) != OK) {
- return EIO;
- }
- } else {
- sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count);
- }
- }
-
- /* Book the number of bytes transferred. */
- if(safe) {
- vir_offset += count;
- } else {
- iov->iov_addr += count;
- }
- if ((iov->iov_size -= count) == 0) {
- iov++;
- nr_req--;
- vir_offset = 0;
- }
- position += count;
- }
- return(OK);
-}
-
-/*===========================================================================*
- * m_do_open *
- *===========================================================================*/
-PRIVATE int m_do_open(dp, m_ptr)
-struct driver *dp;
-message *m_ptr;
-{
-/* Check device number on open. */
- if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
- return(OK);
-}
-
-/*===========================================================================*
- * m_init *
- *===========================================================================*/
-PRIVATE void m_init(argc,argv)
-int argc;
-char **argv;
-{
- /* Initialize this task. All minor devices are initialized one by one. */
- phys_bytes rescue_size;
- phys_bytes rescue_base;
- message m;
- int i, s;
-
- /* Initialize all rescue devices in a loop. */
- for (i=0; i< NR_DEVS; i++) {
-
- /* Determine size and base of rescue disks. See if rescue disk details
- * exist in the data store. If no memory for the rescue disk was claimed
- * yet, do it below.
- */
- m.DS_KEY = (RESCUE_MAJOR << 8) + i;
- if (OK == (s = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m))) {
- rescue_size = m.DS_VAL_L1;
- rescue_base = m.DS_VAL_L2;
- }
- else { /* no details known */
- if (argc>i+1) rescue_size = atoi(argv[i+1]) * 1024;
- else rescue_size = RESCUE_KBYTES * 1024;
-
- if (allocmem(rescue_size, &rescue_base) < 0) {
- report("RESCUE", "warning, allocmem failed", errno);
- rescue_size = 0;
- }
- }
-
- /* Now that we have the base and size of the rescue disk, set up all
- * data structures if the rescue has a positive (nonzero) size.
- */
- if (rescue_size > 0) {
-
- /* Create a new remote segment to make virtual copies. */
- if (OK != (s=sys_segctl(&m_seg[i], (u16_t *) &s,
- (vir_bytes *) &s, rescue_base, rescue_size))) {
- panic("RESCUE","Couldn't install remote segment.",s);
- }
-
- /* Set the device geometry for the outside world. */
- m_geom[i].dv_base = cvul64(rescue_base);
- m_geom[i].dv_size = cvul64(rescue_size);
-
- /* Store the values in the data store for future retrieval. */
- m.DS_KEY = (RESCUE_MAJOR << 8) + i;
- m.DS_VAL_L1 = rescue_size;
- m.DS_VAL_L2 = rescue_base;
- if (OK != (s = _taskcall(DS_PROC_NR, DS_PUBLISH, &m))) {
- panic("RESCUE","Couldn't store rescue disk details at DS.",s);
- }
-
-#if VERBOSE
- printf("RESCUE disk %d (size %u/base %u) initialized\n",
- i, rescue_size, rescue_base);
-#endif
- }
- }
-}
-
-/*===========================================================================*
- * m_geometry *
- *===========================================================================*/
-PRIVATE void m_geometry(entry)
-struct partition *entry;
-{
- /* Memory devices don't have a geometry, but the outside world insists. */
- entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
- entry->heads = 64;
- entry->sectors = 32;
-}
-
#include <minix/type.h>
#include <minix/sysutil.h>
#include <timers.h>
-#include <ibm/portio.h>
#include <net/hton.h>
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
# Makefile for terminal driver (TTY)
DRIVER = tty
+include /etc/make.conf
+
# directories
u = /usr
i = $u/include
# programs, flags, etc.
MAKE = exec make
CC = exec cc
-CFLAGS = -I$i
+CPPFLAGS = -I$i -I../../kernel/arch/$(ARCH)/include
+CFLAGS = $(CPPFLAGS)
LDFLAGS = -i
LIBS = -lsysutil -lsys -ltimers
#include <termios.h>
#include <signal.h>
#include <unistd.h>
+#include <archtypes.h>
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/keymap.h>
ETC=/etc/
USRETC=/usr/etc/
-FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile protocols rc services termcap ttytab utmp rc.cd binary_sizes binary_sizes.big binary_sizes.xxl rc.rescue syslog.conf rc.daemons.dist rs.single
+FILES1=fstab group hostname.file inet.conf motd.install mtab passwd profile protocols rc services termcap ttytab utmp rc.cd binary_sizes binary_sizes.big binary_sizes.xxl rc.rescue syslog.conf rc.daemons.dist rs.single make.conf
FILES2=shadow
FILES3=daily dhcptags.conf rc
p=`pwd` && cd /dev && sh $$p/../commands/scripts/MAKEDEV.sh null
p=`pwd` && cd /dev && sh $$p/../commands/scripts/MAKEDEV.sh std 2>/dev/null
@echo "Making user homedirs.."
- for u in /usr/ast ~root; do (cd ast && tar cf - .[a-z]* ) | (cd $$u && tar xf - ); done
+ for u in /usr/ast ~root; do cp ast/.* $$u ; done
postinstall:
binsizes normal
#define FASTLOAD _FASTLOAD
/* Enable or disable system profiling. */
-#define SPROFILE 0 /* statistical profiling */
+#define SPROFILE 1 /* statistical profiling */
#define CPROFILE 0 /* call profiling */
#endif /* _CONFIG_H */
/*
-ibm/portio.h
+minix/portio.h
Created: Jan 15, 1992 by Philip Homburg
*/
#endif
/* Kernel debug checks */
-#define DEBUG_LOCK_CHECK 0 /* Interrupt Lock/unlock sanity checking. */
+#define DEBUG_LOCK_CHECK 1 /* Interrupt Lock/unlock sanity checking. */
#endif /* _MINIX_SYS_CONFIG_H */
int pc_at;
int ps_mca;
int processor;
- int prot;
+ int padding; /* used to be protected */
int vdu_ega;
int vdu_vga;
};
# Makefile for kernel
+include /etc/make.conf
+
# Directories
u = /usr
i = $u/include
l = $u/lib
s = system
+a = arch/$(ARCH)
# Programs, flags, etc.
CC = exec cc
CPP = $l/cpp
LD = $(CC) -.o
-CFLAGS = -I$i $(CPROFILE)
-LDFLAGS = -i
+CPPFLAGS=-I$i -I$a/include
+CFLAGS=$(CPROFILE) $(CPPFLAGS)
+LDFLAGS=-i
+
+# first-stage, arch-dependent startup code
+HEAD = head.o
+FULLHEAD = $a/$(HEAD)
-HEAD = mpx.o
-OBJS = start.o protect.o klib.o table.o kprintf.o main.o proc.o \
- i8259.o exception.o system.o clock.o utility.o debug.o profile.o
+OBJS = start.o table.o main.o proc.o \
+ system.o clock.o utility.o debug.o profile.o interrupt.o
SYSTEM = system.a
+ARCHLIB = $a/$(ARCH).a
LIBS = -ltimers -lsysutil
-
# What to make.
all: build
kernel build install: $(HEAD) $(OBJS)
- cd system && $(MAKE) -$(MAKEFLAGS) $@
- $(LD) $(CFLAGS) $(LDFLAGS) -o kernel \
- $(HEAD) $(OBJS) \
- $(SYSTEM) $(LIBS)
+ cd system && $(MAKE) $@
+ cd $a && $(MAKE) $@
+ $(LD) $(CFLAGS) $(LDFLAGS) -o kernel $(FULLHEAD) $(OBJS) \
+ $(SYSTEM) $(ARCHLIB) $(LIBS)
install -S 0 kernel
clean:
cd system && $(MAKE) -$(MAKEFLAGS) $@
+ cd $a && $(MAKE) -$(MAKEFLAGS) $@
rm -f *.a *.o *~ *.bak kernel
depend:
cd system && $(MAKE) -$(MAKEFLAGS) $@
- /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c *.s > .depend
+ cd $a && $(MAKE) $@
+ /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
# How to build it
-.s.o:
- $(CC) $(CFLAGS) -c -o $@ $<
-
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
+$(HEAD):
+ cd $a && make HEAD=$(HEAD) $(HEAD)
+
# Include generated dependencies.
-klib.o: klib386.s klib88.s
-mpx.o: mpx386.s mpx88.s
include .depend
-
--- /dev/null
+# Makefile for kernel
+
+include /etc/make.conf
+
+ARCHAR=$(ARCH).a
+
+# objects, excluding first-stage code, which is $(HEAD).
+# the HEAD variable is passed as an argument to this Makefile
+# by an upper level Makefile.
+
+OBJS=$(ARCHAR)(exception.o) \
+ $(ARCHAR)(i8259.o) \
+ $(ARCHAR)(memory.o) \
+ $(ARCHAR)(protect.o) \
+ $(ARCHAR)(system.o) \
+ $(ARCHAR)(clock.o) \
+ $(ARCHAR)(klib386.o) \
+ $(ARCHAR)(do_readbios.o) \
+ $(ARCHAR)(do_int86.o) \
+ $(ARCHAR)(do_sdevio.o) \
+ $(ARCHAR)(do_iopenable.o)
+
+CPPFLAGS=-Iinclude
+CFLAGS=$(CPPFLAGS) -Wall
+
+build: $(HEAD) $(ARCHAR)
+
+$(ARCHAR): $(OBJS)
+ aal cr $@ *.o
+
+depend:
+ /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c *.s > .depend
+
+clean:
+ rm -f *.a *.o *~
+
+# How to build it
+$(ARCHAR)(exception.o): exception.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(i8259.o): i8259.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(memory.o): memory.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(protect.o): protect.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(system.o): system.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(do_int86.o): do_int86.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(do_iopenable.o): do_iopenable.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(do_readbios.o): do_readbios.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(do_sdevio.o): do_sdevio.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(clock.o): clock.c
+ $(CC) $(CFLAGS) -c $<
+
+$(ARCHAR)(klib386.o): klib386.s
+ $(CC) $(CFLAGS) -c $<
+
+.s.o:
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+.c.o:
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(HEAD): mpx386.o
+ cp $< $@
+
+# Include generated dependencies.
+include .depend
--- /dev/null
+
+/* i386-specific clock functions. */
+
+#include <ibm/ports.h>
+#include <minix/portio.h>
+
+#include "../../kernel.h"
+
+#define CLOCK_ACK_BIT 0x80 /* PS/2 clock interrupt acknowledge bit */
+
+/* Clock parameters. */
+#define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */
+#define LATCH_COUNT 0x00 /* cc00xxxx, c = channel, x = any */
+#define SQUARE_WAVE 0x36 /* ccaammmb, a = access, m = mode, b = BCD */
+ /* 11x11, 11 = LSB then MSB, x11 = sq wave */
+#define TIMER_FREQ 1193182 /* clock frequency for timer in PC and AT */
+#define TIMER_COUNT (TIMER_FREQ/HZ) /* initial value for counter*/
+
+/*===========================================================================*
+ * arch_init_clock *
+ *===========================================================================*/
+PUBLIC int arch_init_clock(void)
+{
+ /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz,
+ * and register the CLOCK task's interrupt handler to be run
+ * on every clock tick.
+ */
+ outb(TIMER_MODE, SQUARE_WAVE); /* run continuously */
+ outb(TIMER0, (TIMER_COUNT & 0xff)); /* timer low byte */
+ outb(TIMER0, TIMER_COUNT >> 8); /* timer high byte */
+
+ return OK;
+}
+
+/*===========================================================================*
+ * clock_stop *
+ *===========================================================================*/
+PUBLIC void clock_stop(void)
+{
+ /* Reset the clock to the BIOS rate. (For rebooting.) */
+ outb(TIMER_MODE, 0x36);
+ outb(TIMER0, 0);
+ outb(TIMER0, 0);
+}
+
+/*===========================================================================*
+ * read_clock *
+ *===========================================================================*/
+PUBLIC clock_t read_clock(void)
+{
+ /* Read the counter of channel 0 of the 8253A timer. This counter
+ * counts down at a rate of TIMER_FREQ and restarts at
+ * TIMER_COUNT-1 when it reaches zero. A hardware interrupt
+ * (clock tick) occurs when the counter gets to zero and restarts
+ * its cycle.
+ */
+ u32_t count;
+
+ outb(TIMER_MODE, LATCH_COUNT);
+ count = inb(TIMER0);
+ count |= (inb(TIMER0) << 8);
+
+ return count;
+}
+
* m1_p1: INT86_REG86
*/
-#include "../system.h"
+#include "../../system.h"
#include <minix/type.h>
#include <minix/endpoint.h>
+#include <minix/portio.h>
#include <ibm/int86.h>
+#include "proto.h"
+
struct reg86u reg86;
/*===========================================================================*
* Jorrit N. Herder <jnherder@cs.vu.nl>
*/
-#include "../system.h"
-#include "../kernel.h"
+#include "../../system.h"
+#include "../../kernel.h"
+
+#include "proto.h"
/*===========================================================================*
* do_iopenable *
* m2_p1: RDB_BUF buffer address in requesting process
*/
-#include "../system.h"
+#include "../../system.h"
#include <minix/type.h>
/*===========================================================================*
* m2_i2: DIO_VEC_PROC (process where buffer is)
*/
-#include "../system.h"
+#include "../../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
+#include "proto.h"
+
#if USE_SDEVIO
/*===========================================================================*
* a panic.
*/
-#include "kernel.h"
+#include "../../kernel.h"
#include <signal.h>
-#include "proc.h"
+#include "../../proc.h"
/*===========================================================================*
* exception *
*===========================================================================*/
-PUBLIC void exception(vec_nr)
-unsigned vec_nr;
+PUBLIC void exception(unsigned vec_nr)
{
/* An exception or unexpected interrupt has occurred. */
/*===========================================================================*
* stacktrace *
*===========================================================================*/
-PUBLIC void stacktrace(proc)
-struct proc *proc;
+PUBLIC void stacktrace(struct proc *proc)
{
reg_t bp, v_bp, v_pc, v_hbp;
--- /dev/null
+/* This file contains routines for initializing the 8259 interrupt controller:
+ * put_irq_handler: register an interrupt handler
+ * rm_irq_handler: deregister an interrupt handler
+ * intr_handle: handle a hardware interrupt
+ * intr_init: initialize the interrupt controller(s)
+ */
+
+#include "../../kernel.h"
+#include "../../proc.h"
+#include "proto.h"
+#include <minix/com.h>
+#include <minix/portio.h>
+#include <ibm/cpu.h>
+
+#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
+#define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */
+#define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */
+#define ICW4_AT_SLAVE 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
+#define ICW4_AT_MASTER 0x05 /* not SFNM, not buffered, normal EOI, 8086 */
+#define ICW4_PC_SLAVE 0x09 /* not SFNM, buffered, normal EOI, 8086 */
+#define ICW4_PC_MASTER 0x0D /* not SFNM, buffered, normal EOI, 8086 */
+
+#define set_vec(nr, addr) ((void)0)
+
+/*===========================================================================*
+ * intr_init *
+ *===========================================================================*/
+PUBLIC int intr_init(mine)
+int mine;
+{
+/* Initialize the 8259s, finishing with all interrupts disabled. This is
+ * only done in protected mode, in real mode we don't touch the 8259s, but
+ * use the BIOS locations instead. The flag "mine" is set if the 8259s are
+ * to be programmed for MINIX, or to be reset to what the BIOS expects.
+ */
+ int i;
+
+ intr_disable();
+
+ /* The AT and newer PS/2 have two interrupt controllers, one master,
+ * one slaved at IRQ 2. (We don't have to deal with the PC that
+ * has just one controller, because it must run in real mode.)
+ */
+ outb( INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
+ outb( INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
+ /* ICW2 for master */
+ outb( INT_CTLMASK, (1 << CASCADE_IRQ));
+ /* ICW3 tells slaves */
+ outb( INT_CTLMASK, ICW4_AT_MASTER);
+ outb( INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
+ outb( INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
+ outb( INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
+ /* ICW2 for slave */
+ outb( INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
+ outb( INT2_CTLMASK, ICW4_AT_SLAVE);
+ outb( INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
+
+ /* Copy the BIOS vectors from the BIOS to the Minix location, so we
+ * can still make BIOS calls without reprogramming the i8259s.
+ */
+#if IRQ0_VECTOR != BIOS_IRQ0_VEC
+ phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
+#endif
+#if IRQ8_VECTOR != BIOS_IRQ8_VEC
+ phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L);
+#endif
+
+ return OK;
+}
+
+/*===========================================================================*
+ * intr_disabled *
+ *===========================================================================*/
+PUBLIC int intr_disabled(void)
+{
+ if(!(read_cpu_flags() & X86_FLAG_I))
+ return 1;
+ return 0;
+}
--- /dev/null
+
+#ifndef _I386_ACONST_H
+#define _I386_ACONST_H 1
+
+#include <ibm/interrupt.h>
+#include <ibm/memory.h>
+
+#define NR_REMOTE_SEGS 3 /* # remote memory regions (variable) */
+
+/* Constants for protected mode. */
+
+/* Table sizes. */
+#define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS)
+ /* spec. and LDT's */
+#define IDT_SIZE (IRQ8_VECTOR + 8) /* only up to the highest vector */
+
+/* Fixed global descriptors. 1 to 7 are prescribed by the BIOS. */
+#define GDT_INDEX 1 /* GDT descriptor */
+#define IDT_INDEX 2 /* IDT descriptor */
+#define DS_INDEX 3 /* kernel DS */
+#define ES_INDEX 4 /* kernel ES (386: flag 4 Gb at startup) */
+#define SS_INDEX 5 /* kernel SS (386: monitor SS at startup) */
+#define CS_INDEX 6 /* kernel CS */
+#define MON_CS_INDEX 7 /* temp for BIOS (386: monitor CS at startup) */
+#define TSS_INDEX 8 /* kernel TSS */
+#define DS_286_INDEX 9 /* scratch 16-bit source segment */
+#define ES_286_INDEX 10 /* scratch 16-bit destination segment */
+#define A_INDEX 11 /* 64K memory segment at A0000 */
+#define B_INDEX 12 /* 64K memory segment at B0000 */
+#define C_INDEX 13 /* 64K memory segment at C0000 */
+#define D_INDEX 14 /* 64K memory segment at D0000 */
+#define FIRST_LDT_INDEX 15 /* rest of descriptors are LDT's */
+
+#define GDT_SELECTOR 0x08 /* (GDT_INDEX * DESC_SIZE) bad for asld */
+#define IDT_SELECTOR 0x10 /* (IDT_INDEX * DESC_SIZE) */
+#define DS_SELECTOR 0x18 /* (DS_INDEX * DESC_SIZE) */
+#define ES_SELECTOR 0x20 /* (ES_INDEX * DESC_SIZE) */
+#define FLAT_DS_SELECTOR 0x21 /* less privileged ES */
+#define SS_SELECTOR 0x28 /* (SS_INDEX * DESC_SIZE) */
+#define CS_SELECTOR 0x30 /* (CS_INDEX * DESC_SIZE) */
+#define MON_CS_SELECTOR 0x38 /* (MON_CS_INDEX * DESC_SIZE) */
+#define TSS_SELECTOR 0x40 /* (TSS_INDEX * DESC_SIZE) */
+#define DS_286_SELECTOR 0x49 /* (DS_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */
+#define ES_286_SELECTOR 0x51 /* (ES_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */
+
+/* Privileges. */
+#define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */
+#define TASK_PRIVILEGE 1 /* kernel tasks */
+#define USER_PRIVILEGE 3 /* servers and user processes */
+
+/* 286 hardware constants. */
+
+/* Exception vector numbers. */
+#define BOUNDS_VECTOR 5 /* bounds check failed */
+#define INVAL_OP_VECTOR 6 /* invalid opcode */
+#define COPROC_NOT_VECTOR 7 /* coprocessor not available */
+#define DOUBLE_FAULT_VECTOR 8
+#define COPROC_SEG_VECTOR 9 /* coprocessor segment overrun */
+#define INVAL_TSS_VECTOR 10 /* invalid TSS */
+#define SEG_NOT_VECTOR 11 /* segment not present */
+#define STACK_FAULT_VECTOR 12 /* stack exception */
+#define PROTECTION_VECTOR 13 /* general protection */
+
+/* Selector bits. */
+#define TI 0x04 /* table indicator */
+#define RPL 0x03 /* requester privilege level */
+
+/* Descriptor structure offsets. */
+#define DESC_BASE 2 /* to base_low */
+#define DESC_BASE_MIDDLE 4 /* to base_middle */
+#define DESC_ACCESS 5 /* to access byte */
+#define DESC_SIZE 8 /* sizeof (struct segdesc_s) */
+
+/* Base and limit sizes and shifts. */
+#define BASE_MIDDLE_SHIFT 16 /* shift for base --> base_middle */
+
+/* Access-byte and type-byte bits. */
+#define PRESENT 0x80 /* set for descriptor present */
+#define DPL 0x60 /* descriptor privilege level mask */
+#define DPL_SHIFT 5
+#define SEGMENT 0x10 /* set for segment-type descriptors */
+
+/* Access-byte bits. */
+#define EXECUTABLE 0x08 /* set for executable segment */
+#define CONFORMING 0x04 /* set for conforming segment if executable */
+#define EXPAND_DOWN 0x04 /* set for expand-down segment if !executable*/
+#define READABLE 0x02 /* set for readable segment if executable */
+#define WRITEABLE 0x02 /* set for writeable segment if !executable */
+#define TSS_BUSY 0x02 /* set if TSS descriptor is busy */
+#define ACCESSED 0x01 /* set if segment accessed */
+
+/* Special descriptor types. */
+#define AVL_286_TSS 1 /* available 286 TSS */
+#define LDT 2 /* local descriptor table */
+#define BUSY_286_TSS 3 /* set transparently to the software */
+#define CALL_286_GATE 4 /* not used */
+#define TASK_GATE 5 /* only used by debugger */
+#define INT_286_GATE 6 /* interrupt gate, used for all vectors */
+#define TRAP_286_GATE 7 /* not used */
+
+/* Extra 386 hardware constants. */
+
+/* Exception vector numbers. */
+#define PAGE_FAULT_VECTOR 14
+#define COPROC_ERR_VECTOR 16 /* coprocessor error */
+
+/* Descriptor structure offsets. */
+#define DESC_GRANULARITY 6 /* to granularity byte */
+#define DESC_BASE_HIGH 7 /* to base_high */
+
+/* Type-byte bits. */
+#define DESC_386_BIT 0x08 /* 386 types are obtained by ORing with this */
+ /* LDT's and TASK_GATE's don't need it */
+
+/* Base and limit sizes and shifts. */
+#define BASE_HIGH_SHIFT 24 /* shift for base --> base_high */
+#define BYTE_GRAN_MAX 0xFFFFFL /* maximum size for byte granular segment */
+#define GRANULARITY_SHIFT 16 /* shift for limit --> granularity */
+#define OFFSET_HIGH_SHIFT 16 /* shift for (gate) offset --> offset_high */
+#define PAGE_GRAN_SHIFT 12 /* extra shift for page granular limits */
+
+/* Granularity byte. */
+#define GRANULAR 0x80 /* set for 4K granularilty */
+#define DEFAULT 0x40 /* set for 32-bit defaults (executable seg) */
+#define BIG 0x40 /* set for "BIG" (expand-down seg) */
+#define AVL 0x10 /* 0 for available */
+#define LIMIT_HIGH 0x0F /* mask for high bits of limit */
+
+/* Program stack words and masks. */
+#define INIT_PSW 0x0200 /* initial psw */
+#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
+#define TRACEBIT 0x0100 /* OR this with psw in proc[] for tracing */
+#define SETPSW(rp, new) /* permits only certain bits to be set */ \
+ ((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
+#define IF_MASK 0x00000200
+#define IOPL_MASK 0x003000
+
+/* Sizes of memory tables. The boot monitor distinguishes three memory areas,
+ * namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
+ * for DOS MINIX.
+ */
+#define NR_MEMS 8
+
+#define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir))
+
+#endif /* _I386_ACONST_H */
--- /dev/null
+
+#ifndef _I386_TYPES_H
+#define _I386_TYPES_H
+
+#include <minix/sys_config.h>
+#include "archconst.h"
+
+typedef unsigned reg_t; /* machine register */
+typedef reg_t segdesc_t;
+
+/* The stack frame layout is determined by the software, but for efficiency
+ * it is laid out so the assembly code to use it is as simple as possible.
+ * 80286 protected mode and all real modes use the same frame, built with
+ * 16-bit registers. Real mode lacks an automatic stack switch, so little
+ * is lost by using the 286 frame for it. The 386 frame differs only in
+ * having 32-bit registers and more segment registers. The same names are
+ * used for the larger registers to avoid differences in the code.
+ */
+struct stackframe_s { /* proc_ptr points here */
+ u16_t gs; /* last item pushed by save */
+ u16_t fs; /* ^ */
+ u16_t es; /* | */
+ u16_t ds; /* | */
+ reg_t di; /* di through cx are not accessed in C */
+ reg_t si; /* order is to match pusha/popa */
+ reg_t fp; /* bp */
+ reg_t st; /* hole for another copy of sp */
+ reg_t bx; /* | */
+ reg_t dx; /* | */
+ reg_t cx; /* | */
+ reg_t retreg; /* ax and above are all pushed by save */
+ reg_t retadr; /* return address for assembly code save() */
+ reg_t pc; /* ^ last item pushed by interrupt */
+ reg_t cs; /* | */
+ reg_t psw; /* | */
+ reg_t sp; /* | */
+ reg_t ss; /* these are pushed by CPU during interrupt */
+};
+
+struct segdesc_s { /* segment descriptor for protected mode */
+ u16_t limit_low;
+ u16_t base_low;
+ u8_t base_middle;
+ u8_t access; /* |P|DL|1|X|E|R|A| */
+ u8_t granularity; /* |G|X|0|A|LIMT| */
+ u8_t base_high;
+};
+
+#define LDT_SIZE (2 + NR_REMOTE_SEGS) /* CS, DS and remote segments */
+
+/* Fixed local descriptors. */
+#define CS_LDT_INDEX 0 /* process CS */
+#define DS_LDT_INDEX 1 /* process DS=ES=FS=GS=SS */
+#define EXTRA_LDT_INDEX 2 /* first of the extra LDT entries */
+
+typedef struct segframe {
+ reg_t p_ldt_sel; /* selector in gdt with ldt base and limit */
+ struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote */
+} segframe_t;
+
+#endif /* #ifndef _I386_TYPES_H */
+
#include <minix/config.h>
#include <minix/const.h>
-#include "const.h"
+#include <ibm/interrupt.h>
+#include <archconst.h>
+#include "../../const.h"
#include "sconst.h"
-#include "protect.h"
! This file contains a number of assembly code utility routines needed by the
! kernel. They are:
.define _phys_insb ! likewise byte by byte
.define _phys_outsw ! transfer data from memory to (disk controller) port
.define _phys_outsb ! likewise byte by byte
-.define _enable_irq ! enable an irq at the 8259 controller
-.define _disable_irq ! disable an irq
+.define _intr_unmask ! enable an irq at the 8259 controller
+.define _intr_mask ! disable an irq
.define _phys_copy ! copy data from anywhere to anywhere in memory
.define _phys_memset ! write pattern anywhere in memory
.define _mem_rdw ! copy one word from [segment:offset]
!*==========================================================================*
-!* enable_irq *
+!* intr_unmask *
!*==========================================================================*/
-! PUBLIC void enable_irq(irq_hook_t *hook)
+! PUBLIC void intr_unmask(irq_hook_t *hook)
! Enable an interrupt request line by clearing an 8259 bit.
! Equivalent C code for hook->irq < 8:
! if ((irq_actids[hook->irq] &= ~hook->id) == 0)
! outb(INT_CTLMASK, inb(INT_CTLMASK) & ~(1 << irq));
.align 16
-_enable_irq:
+_intr_unmask:
push ebp
mov ebp, esp
pushf
!*==========================================================================*
-!* disable_irq *
+!* intr_mask *
!*==========================================================================*/
-! PUBLIC int disable_irq(irq_hook_t *hook)
+! PUBLIC int intr_mask(irq_hook_t *hook)
! Disable an interrupt request line by setting an 8259 bit.
! Equivalent C code for irq < 8:
! irq_actids[hook->irq] |= hook->id;
! Returns true iff the interrupt was not already disabled.
.align 16
-_disable_irq:
+_intr_mask:
push ebp
mov ebp, esp
pushf
--- /dev/null
+
+#include "../../kernel.h"
+#include "../../proc.h"
+
+#include <minix/type.h>
+#include <string.h>
+
+#include <sys/vm.h>
+
+#include <minix/portio.h>
+
+#include "proto.h"
+
+/* VM functions and data. */
+
+PRIVATE int vm_needs_init= 1;
+PRIVATE u32_t vm_cr3;
+
+FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
+FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
+FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
+FORWARD _PROTOTYPE( void set_cr3, (void) );
+FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
+
+/* *** Internal VM Functions *** */
+
+PUBLIC void vm_init(void)
+{
+ int o;
+ phys_bytes p, pt_size;
+ phys_bytes vm_dir_base, vm_pt_base, phys_mem;
+ u32_t entry;
+ unsigned pages;
+
+ if (!vm_size)
+ panic("i386_vm_init: no space for page tables", NO_NUM);
+
+ /* Align page directory */
+ o= (vm_base % PAGE_SIZE);
+ if (o != 0)
+ o= PAGE_SIZE-o;
+ vm_dir_base= vm_base+o;
+
+ /* Page tables start after the page directory */
+ vm_pt_base= vm_dir_base+PAGE_SIZE;
+
+ pt_size= (vm_base+vm_size)-vm_pt_base;
+ pt_size -= (pt_size % PAGE_SIZE);
+
+ /* Compute the number of pages based on vm_mem_high */
+ pages= (vm_mem_high-1)/PAGE_SIZE + 1;
+
+ if (pages * I386_VM_PT_ENT_SIZE > pt_size)
+ panic("i386_vm_init: page table too small", NO_NUM);
+
+ for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
+ {
+ phys_mem= p*PAGE_SIZE;
+ entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
+ I386_VM_PRESENT;
+ if (phys_mem >= vm_mem_high)
+ entry= 0;
+ phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
+ }
+
+ for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
+ {
+ phys_mem= vm_pt_base + p*PAGE_SIZE;
+ entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
+ I386_VM_PRESENT;
+ if (phys_mem >= vm_pt_base + pt_size)
+ entry= 0;
+ phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
+ }
+ vm_set_cr3(vm_dir_base);
+ level0(vm_enable_paging);
+}
+
+PRIVATE void phys_put32(addr, value)
+phys_bytes addr;
+u32_t value;
+{
+ phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
+}
+
+PRIVATE u32_t phys_get32(addr)
+phys_bytes addr;
+{
+ u32_t value;
+
+ phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
+
+ return value;
+}
+
+PRIVATE void vm_set_cr3(value)
+u32_t value;
+{
+ vm_cr3= value;
+ level0(set_cr3);
+}
+
+PRIVATE void set_cr3()
+{
+ write_cr3(vm_cr3);
+}
+
+PRIVATE void vm_enable_paging(void)
+{
+ u32_t cr0;
+
+ cr0= read_cr0();
+ write_cr0(cr0 | I386_CR0_PG);
+}
+
+PUBLIC void vm_map_range(base, size, offset)
+u32_t base;
+u32_t size;
+u32_t offset;
+{
+ u32_t curr_pt, curr_pt_addr, entry;
+ int dir_ent, pt_ent;
+
+ if (base % PAGE_SIZE != 0)
+ panic("map_range: bad base", base);
+ if (size % PAGE_SIZE != 0)
+ panic("map_range: bad size", size);
+ if (offset % PAGE_SIZE != 0)
+ panic("map_range: bad offset", offset);
+
+ curr_pt= -1;
+ curr_pt_addr= 0;
+ while (size != 0)
+ {
+ dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
+ pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
+ if (dir_ent != curr_pt)
+ {
+ /* Get address of page table */
+ curr_pt= dir_ent;
+ curr_pt_addr= phys_get32(vm_cr3 +
+ dir_ent * I386_VM_PT_ENT_SIZE);
+ curr_pt_addr &= I386_VM_ADDR_MASK;
+ }
+ entry= offset | I386_VM_USER | I386_VM_WRITE |
+ I386_VM_PRESENT;
+#if 0 /* Do we need this for memory mapped I/O? */
+ entry |= I386_VM_PCD | I386_VM_PWT;
+#endif
+ phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
+ offset += PAGE_SIZE;
+ base += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ /* reload root of page table. */
+ vm_set_cr3(vm_cr3);
+}
+
+PUBLIC vir_bytes alloc_remote_segment(u32_t *selector,
+ segframe_t *segments, int index, phys_bytes phys, vir_bytes size,
+ int priv)
+{
+ phys_bytes offset = 0;
+ /* Check if the segment size can be recorded in bytes, that is, check
+ * if descriptor's limit field can delimited the allowed memory region
+ * precisely. This works up to 1MB. If the size is larger, 4K pages
+ * instead of bytes are used.
+ */
+ if (size < BYTE_GRAN_MAX) {
+ init_dataseg(&segments->p_ldt[EXTRA_LDT_INDEX+index],
+ phys, size, priv);
+ *selector = ((EXTRA_LDT_INDEX+index)*0x08) | (1*0x04) | priv;
+ offset = 0;
+ } else {
+ init_dataseg(&segments->p_ldt[EXTRA_LDT_INDEX+index],
+ phys & ~0xFFFF, 0, priv);
+ *selector = ((EXTRA_LDT_INDEX+index)*0x08) | (1*0x04) | priv;
+ offset = phys & 0xFFFF;
+ }
+
+ return offset;
+}
+
+PUBLIC phys_bytes umap_remote(struct proc* rp, int seg,
+ vir_bytes vir_addr, vir_bytes bytes)
+{
+/* Calculate the physical memory address for a given virtual address. */
+ struct far_mem *fm;
+
+ if (bytes <= 0) return( (phys_bytes) 0);
+ if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
+
+ fm = &rp->p_priv->s_farmem[seg];
+ if (! fm->in_use) return( (phys_bytes) 0);
+ if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0);
+
+ return(fm->mem_phys + (phys_bytes) vir_addr);
+}
+
+/*===========================================================================*
+ * umap_local *
+ *===========================================================================*/
+PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes)
+register struct proc *rp; /* pointer to proc table entry for process */
+int seg; /* T, D, or S segment */
+vir_bytes vir_addr; /* virtual address in bytes within the seg */
+vir_bytes bytes; /* # of bytes to be copied */
+{
+/* Calculate the physical memory address for a given virtual address. */
+ vir_clicks vc; /* the virtual address in clicks */
+ phys_bytes pa; /* intermediate variables as phys_bytes */
+ phys_bytes seg_base;
+
+ if (bytes <= 0) return( (phys_bytes) 0);
+ if (vir_addr + bytes <= vir_addr) return 0; /* overflow */
+ vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
+
+ if (seg != T)
+ seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S);
+
+ if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir +
+ rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
+
+ if (vc >= rp->p_memmap[seg].mem_vir +
+ rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
+
+ seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys;
+ seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
+ pa = (phys_bytes) vir_addr;
+ pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
+ return(seg_base + pa);
+}
+
#include <minix/const.h>
#include <minix/com.h>
#include <ibm/interrupt.h>
-#include "const.h"
-#include "protect.h"
+#include <archconst.h>
+#include "../../const.h"
#include "sconst.h"
/* Selected 386 tss offsets. */
* for local descriptors in the process table.
*/
-#include "kernel.h"
-#include "proc.h"
-#include "protect.h"
+#include "../../kernel.h"
+#include "../../proc.h"
+#include <archconst.h>
+
+#include "proto.h"
-#if _WORD_SIZE == 4
#define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
#define TSS_TYPE (AVL_286_TSS | DESC_386_BIT)
-#else
-#define INT_GATE_TYPE INT_286_GATE
-#define TSS_TYPE AVL_286_TSS
-#endif
struct desctableptr_s {
char limit[sizeof(u16_t)];
reg_t ss1;
reg_t sp2;
reg_t ss2;
-#if _WORD_SIZE == 4
reg_t cr3;
-#endif
reg_t ip;
reg_t flags;
reg_t ax;
reg_t cs;
reg_t ss;
reg_t ds;
-#if _WORD_SIZE == 4
reg_t fs;
reg_t gs;
-#endif
reg_t ldt;
-#if _WORD_SIZE == 4
u16_t trap;
u16_t iobase;
/* u8_t iomap[0]; */
-#endif
};
PUBLIC struct segdesc_s gdt[GDT_SIZE]; /* used in klib.s and mpx.s */
FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
vir_bytes size) );
+/*===========================================================================*
+ * enable_iop *
+ *===========================================================================*/
+PUBLIC void enable_iop(struct proc *pp)
+{
+/* Allow a user process to use I/O instructions. Change the I/O Permission
+ * Level bits in the psw. These specify least-privileged Current Permission
+ * Level allowed to execute I/O instructions. Users and servers have CPL 3.
+ * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
+ */
+ pp->p_reg.psw |= 0x3000;
+}
+
+/*===========================================================================*
+ * seg2phys *
+ *===========================================================================*/
+PUBLIC phys_bytes seg2phys(U16_t seg)
+{
+/* Return the base address of a segment, with seg being a
+ * register, or a 286/386 segment selector.
+ */
+ phys_bytes base;
+ struct segdesc_s *segdp;
+
+ segdp = &gdt[seg >> 3];
+ base = ((u32_t) segdp->base_low << 0)
+ | ((u32_t) segdp->base_middle << 16)
+ | ((u32_t) segdp->base_high << 24);
+ return base;
+}
+
+/*===========================================================================*
+ * phys2seg *
+ *===========================================================================*/
+PUBLIC void phys2seg(u16_t *seg, vir_bytes *off, phys_bytes phys)
+{
+/* Return a segment selector and offset that can be used to reach a physical
+ * address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
+ */
+ *seg = FLAT_DS_SELECTOR;
+ *off = phys;
+}
+
+/*===========================================================================*
+ * init_dataseg *
+ *===========================================================================*/
+PUBLIC void init_dataseg(register struct segdesc_s *segdp,
+ phys_bytes base, vir_bytes size, int privilege)
+{
+ /* Build descriptor for a data segment. */
+ sdesc(segdp, base, size);
+ segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT |
+ WRITEABLE);
+ /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
+}
+
+/*===========================================================================*
+ * init_codeseg *
+ *===========================================================================*/
+PUBLIC void init_codeseg(register struct segdesc_s *segdp, phys_bytes base,
+ vir_bytes size, int privilege)
+{
+ /* Build descriptor for a code segment. */
+ sdesc(segdp, base, size);
+ segdp->access = (privilege << DPL_SHIFT)
+ | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
+ /* CONFORMING = 0, ACCESSED = 0 */
+}
+
/*===========================================================================*
* prot_init *
*===========================================================================*/
-PUBLIC void prot_init()
+PUBLIC void prot_init(void)
{
/* Set up tables for protected mode.
* All GDT slots are allocated at compile time.
{ segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE },
{ stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE },
{ general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE },
-#if _WORD_SIZE == 4
{ page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE },
{ copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE },
-#endif
{ hwint00, VECTOR( 0), INTR_PRIVILEGE },
{ hwint01, VECTOR( 1), INTR_PRIVILEGE },
{ hwint02, VECTOR( 2), INTR_PRIVILEGE },
{ hwint13, VECTOR(13), INTR_PRIVILEGE },
{ hwint14, VECTOR(14), INTR_PRIVILEGE },
{ hwint15, VECTOR(15), INTR_PRIVILEGE },
-#if _WORD_SIZE == 2
- { p_s_call, SYS_VECTOR, USER_PRIVILEGE }, /* 286 system call */
-#else
{ s_call, SYS386_VECTOR, USER_PRIVILEGE }, /* 386 system call */
-#endif
{ level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE },
};
*/
for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX;
rp < END_PROC_ADDR; ++rp, ldt_index++) {
- init_dataseg(&gdt[ldt_index], vir2phys(rp->p_ldt),
- sizeof(rp->p_ldt), INTR_PRIVILEGE);
+ init_dataseg(&gdt[ldt_index], vir2phys(rp->p_seg.p_ldt),
+ sizeof(rp->p_seg.p_ldt), INTR_PRIVILEGE);
gdt[ldt_index].access = PRESENT | LDT;
- rp->p_ldt_sel = ldt_index * DESC_SIZE;
+ rp->p_seg.p_ldt_sel = ldt_index * DESC_SIZE;
}
/* Build main TSS.
PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
}
-#if _WORD_SIZE == 4
/* Complete building of main TSS. */
tss.iobase = sizeof tss; /* empty i/o permissions map */
-#endif
}
-/*===========================================================================*
- * init_codeseg *
- *===========================================================================*/
-PUBLIC void init_codeseg(segdp, base, size, privilege)
-register struct segdesc_s *segdp;
-phys_bytes base;
-vir_bytes size;
-int privilege;
-{
-/* Build descriptor for a code segment. */
- sdesc(segdp, base, size);
- segdp->access = (privilege << DPL_SHIFT)
- | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
- /* CONFORMING = 0, ACCESSED = 0 */
-}
-/*===========================================================================*
- * init_dataseg *
- *===========================================================================*/
-PUBLIC void init_dataseg(segdp, base, size, privilege)
-register struct segdesc_s *segdp;
-phys_bytes base;
-vir_bytes size;
-int privilege;
-{
-/* Build descriptor for a data segment. */
- sdesc(segdp, base, size);
- segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
- /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
-}
/*===========================================================================*
* sdesc *
segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
segdp->base_high = base >> BASE_HIGH_SHIFT;
-#if _WORD_SIZE == 4
--size; /* convert to a limit, 0 size means 4G */
if (size > BYTE_GRAN_MAX) {
segdp->limit_low = size >> PAGE_GRAN_SHIFT;
segdp->granularity = size >> GRANULARITY_SHIFT;
}
segdp->granularity |= DEFAULT; /* means BIG for data seg */
-#else
- segdp->limit_low = size - 1;
-#endif
-}
-
-/*===========================================================================*
- * seg2phys *
- *===========================================================================*/
-PUBLIC phys_bytes seg2phys(seg)
-U16_t seg;
-{
-/* Return the base address of a segment, with seg being either a 8086 segment
- * register, or a 286/386 segment selector.
- */
- phys_bytes base;
- struct segdesc_s *segdp;
-
- if (! machine.prot) {
- base = hclick_to_physb(seg);
- } else {
- segdp = &gdt[seg >> 3];
- base = ((u32_t) segdp->base_low << 0)
- | ((u32_t) segdp->base_middle << 16)
- | ((u32_t) segdp->base_high << 24);
- }
- return base;
-}
-
-/*===========================================================================*
- * phys2seg *
- *===========================================================================*/
-PUBLIC void phys2seg(seg, off, phys)
-u16_t *seg;
-vir_bytes *off;
-phys_bytes phys;
-{
-/* Return a segment selector and offset that can be used to reach a physical
- * address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
- */
-#if _WORD_SIZE == 2
- if (! machine.prot) {
- *seg = phys / HCLICK_SIZE;
- *off = phys % HCLICK_SIZE;
- } else {
- unsigned bank = phys >> 16;
- unsigned index = bank - 0xA + A_INDEX;
- init_dataseg(&gdt[index], (phys_bytes) bank << 16, 0, TASK_PRIVILEGE);
- *seg = (index * 0x08) | TASK_PRIVILEGE;
- *off = phys & 0xFFFF;
- }
-#else
- *seg = FLAT_DS_SELECTOR;
- *off = phys;
-#endif
}
/*===========================================================================*
idp->offset_low = offset;
idp->selector = CS_SELECTOR;
idp->p_dpl_type = dpl_type;
-#if _WORD_SIZE == 4
idp->offset_high = offset >> OFFSET_HIGH_SHIFT;
-#endif
-}
-
-/*===========================================================================*
- * enable_iop *
- *===========================================================================*/
-PUBLIC void enable_iop(pp)
-struct proc *pp;
-{
-/* Allow a user process to use I/O instructions. Change the I/O Permission
- * Level bits in the psw. These specify least-privileged Current Permission
- * Level allowed to execute I/O instructions. Users and servers have CPL 3.
- * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
- */
- pp->p_reg.psw |= 0x3000;
}
/*===========================================================================*
* alloc_segments *
*===========================================================================*/
-PUBLIC void alloc_segments(rp)
-register struct proc *rp;
+PUBLIC void alloc_segments(register struct proc *rp)
{
/* This is called at system initialization from main() and by do_newmap().
* The code has a separate function because of all hardware-dependencies.
phys_bytes data_bytes;
int privilege;
- if (machine.prot) {
data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir +
rp->p_memmap[S].mem_len) << CLICK_SHIFT;
if (rp->p_memmap[T].mem_len == 0)
else
code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
privilege = (iskernelp(rp)) ? TASK_PRIVILEGE : USER_PRIVILEGE;
- init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
+ init_codeseg(&rp->p_seg.p_ldt[CS_LDT_INDEX],
(phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT,
code_bytes, privilege);
- init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
+ init_dataseg(&rp->p_seg.p_ldt[DS_LDT_INDEX],
(phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT,
data_bytes, privilege);
rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
-#if _WORD_SIZE == 4
rp->p_reg.gs =
rp->p_reg.fs =
-#endif
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
- } else {
- rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys);
- rp->p_reg.ss =
- rp->p_reg.es =
- rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys);
- }
}
--- /dev/null
+
+#ifndef _I386_PROTO_H
+#define _I386_PROTO_H
+
+/* Hardware interrupt handlers. */
+_PROTOTYPE( void hwint00, (void) );
+_PROTOTYPE( void hwint01, (void) );
+_PROTOTYPE( void hwint02, (void) );
+_PROTOTYPE( void hwint03, (void) );
+_PROTOTYPE( void hwint04, (void) );
+_PROTOTYPE( void hwint05, (void) );
+_PROTOTYPE( void hwint06, (void) );
+_PROTOTYPE( void hwint07, (void) );
+_PROTOTYPE( void hwint08, (void) );
+_PROTOTYPE( void hwint09, (void) );
+_PROTOTYPE( void hwint10, (void) );
+_PROTOTYPE( void hwint11, (void) );
+_PROTOTYPE( void hwint12, (void) );
+_PROTOTYPE( void hwint13, (void) );
+_PROTOTYPE( void hwint14, (void) );
+_PROTOTYPE( void hwint15, (void) );
+
+
+/* Exception handlers (real or protected mode), in numerical order. */
+void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) );
+void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
+void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) );
+void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
+void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) );
+void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) );
+void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
+void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
+void _PROTOTYPE( double_fault, (void) );
+void _PROTOTYPE( copr_seg_overrun, (void) );
+void _PROTOTYPE( inval_tss, (void) );
+void _PROTOTYPE( segment_not_present, (void) );
+void _PROTOTYPE( stack_exception, (void) );
+void _PROTOTYPE( general_protection, (void) );
+void _PROTOTYPE( page_fault, (void) );
+void _PROTOTYPE( copr_error, (void) );
+
+/* Software interrupt handlers, in numerical order. */
+_PROTOTYPE( void trp, (void) );
+_PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
+_PROTOTYPE( void level0_call, (void) );
+
+/* klib386.s */
+_PROTOTYPE( void level0, (void (*func)(void)) );
+_PROTOTYPE( void monitor, (void) );
+_PROTOTYPE( void reset, (void) );
+_PROTOTYPE( void int86, (void) );
+_PROTOTYPE( unsigned long read_cr0, (void) );
+_PROTOTYPE( void write_cr0, (unsigned long value) );
+_PROTOTYPE( void write_cr3, (unsigned long value) );
+_PROTOTYPE( unsigned long read_cpu_flags, (void) );
+_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
+_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
+_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
+_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
+
+/* protect.c */
+_PROTOTYPE( void prot_init, (void) );
+_PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
+ vir_bytes size, int privilege) );
+_PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
+ vir_bytes size, int privilege) );
+_PROTOTYPE( void enable_iop, (struct proc *pp) );
+
+/* functions defined in architecture-independent kernel source. */
+#include "../../proto.h"
+
+#endif
! Offsets in struct proc. They MUST match proc.h.
P_STACKBASE = 0
-#if _WORD_SIZE == 2
-ESREG = P_STACKBASE
-#else
GSREG = P_STACKBASE
FSREG = GSREG + 2 ! 386 introduces FS and GS segments
ESREG = FSREG + 2
-#endif
DSREG = ESREG + 2
DIREG = DSREG + 2
SIREG = DIREG + W
P_STACKTOP = SSREG + W
P_LDT_SEL = P_STACKTOP
P_LDT = P_LDT_SEL + W
-
-#if _WORD_SIZE == 2
-Msize = 12 ! size of a message in 16-bit words
-#else
Msize = 9 ! size of a message in 32-bit words
-#endif
--- /dev/null
+/* system dependent functions for use inside the whole kernel. */
+
+#include "../../kernel.h"
+
+#include <unistd.h>
+#include <ibm/cmos.h>
+#include <ibm/bios.h>
+#include <minix/portio.h>
+
+#include "proto.h"
+
+PUBLIC void arch_shutdown(int how)
+{
+ /* Mask all interrupts, including the clock. */
+ outb( INT_CTLMASK, ~0);
+
+ if(how != RBT_RESET) {
+ /* return to boot monitor */
+
+ outb( INT_CTLMASK, 0);
+ outb( INT2_CTLMASK, 0);
+
+ /* Return to the boot monitor. Set
+ * the program if not already done.
+ */
+ if (how != RBT_MONITOR)
+ phys_copy(vir2phys(""), kinfo.params_base, 1);
+ level0(monitor);
+ } else {
+ /* Reset the system by forcing a processor shutdown. First stop
+ * the BIOS memory test by setting a soft reset flag.
+ */
+ u16_t magic = STOP_MEM_CHECK;
+ phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR,
+ SOFT_RESET_FLAG_SIZE);
+ level0(reset);
+ }
+}
+
+PUBLIC void system_init(void)
+{
+ prot_init();
+}
+
+#define COM1_BASE 0x3F8
+#define COM1_THR (COM1_BASE + 0)
+#define LSR_THRE 0x20
+#define COM1_LSR (COM1_BASE + 5)
+
+PUBLIC void ser_putc(char c)
+{
+ int i;
+ int lsr, thr;
+
+ lsr= COM1_LSR;
+ thr= COM1_THR;
+ for (i= 0; i<100000; i++)
+ {
+ if (inb( lsr) & LSR_THRE)
+ break;
+ }
+ outb( thr, c);
+}
+
+#if SPROFILE
+
+PUBLIC int arch_init_profile_clock(u32_t freq)
+{
+ int r;
+ /* Set CMOS timer frequency. */
+ outb(RTC_INDEX, RTC_REG_A);
+ outb(RTC_IO, RTC_A_DV_OK | freq);
+ /* Enable CMOS timer interrupts. */
+ outb(RTC_INDEX, RTC_REG_B);
+ r = inb(RTC_IO);
+ outb(RTC_INDEX, RTC_REG_B);
+ outb(RTC_IO, r | RTC_B_PIE);
+ /* Mandatory read of CMOS register to enable timer interrupts. */
+ outb(RTC_INDEX, RTC_REG_C);
+ inb(RTC_IO);
+
+ return CMOS_CLOCK_IRQ;
+}
+
+PUBLIC void arch_stop_profile_clock(void)
+{
+ int r;
+ /* Disable CMOS timer interrupts. */
+ outb(RTC_INDEX, RTC_REG_B);
+ r = inb(RTC_IO);
+ outb(RTC_INDEX, RTC_REG_B);
+ outb(RTC_IO, r & !RTC_B_PIE);
+}
+
+PUBLIC void arch_ack_profile_clock(void)
+{
+ /* Mandatory read of CMOS register to re-enable timer interrupts. */
+ outb(RTC_INDEX, RTC_REG_C);
+ inb(RTC_IO);
+}
+
+#endif
* CLOCK task thus is hidden from the outside world.
*
* Changes:
+ * Aug 18, 2006 removed direct hardware access etc, MinixPPC (Ingmar Alting)
* Oct 08, 2005 reordering and comment editing (A. S. Woodhull)
* Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
#include <signal.h>
#include <minix/com.h>
-/* Function prototype for PRIVATE functions. */
+/* Function prototype for PRIVATE functions.
+ */
FORWARD _PROTOTYPE( void init_clock, (void) );
FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
FORWARD _PROTOTYPE( void load_update, (void));
-/* Clock parameters. */
-#define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */
-#define LATCH_COUNT 0x00 /* cc00xxxx, c = channel, x = any */
-#define SQUARE_WAVE 0x36 /* ccaammmb, a = access, m = mode, b = BCD */
- /* 11x11, 11 = LSB then MSB, x11 = sq wave */
-#define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/
-#define TIMER_FREQ 1193182L /* clock frequency for timer in PC and AT */
-
-#define CLOCK_ACK_BIT 0x80 /* PS/2 clock interrupt acknowledge bit */
-
/* The CLOCK's timers queue. The functions in <timers.h> operate on this.
* Each system process possesses a single synchronous alarm timer. If other
* kernel parts want to use additional timers, they must declare their own
* via (re)set_timer().
* When a timer expires its watchdog function is run by the CLOCK task.
*/
-PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */
-PRIVATE clock_t next_timeout; /* realtime that next timer expires */
+PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */
+PRIVATE clock_t next_timeout; /* realtime that next timer expires */
-/* The time is incremented by the interrupt handler on each clock tick. */
-PRIVATE clock_t realtime; /* real time clock */
+/* The time is incremented by the interrupt handler on each clock tick.
+ */
+PRIVATE clock_t realtime = 0; /* real time clock */
PRIVATE irq_hook_t clock_hook; /* interrupt handler hook */
/*===========================================================================*
{
/* Main program of clock task. If the call is not HARD_INT it is an error.
*/
- message m; /* message buffer for both input and output */
- int result; /* result returned by the handler */
-
- init_clock(); /* initialize clock task */
+ message m; /* message buffer for both input and output */
+ int result; /* result returned by the handler */
+ init_clock(); /* initialize clock task */
+
/* Main loop of the clock task. Get work, process it. Never reply. */
- while (TRUE) {
-
- /* Go get a message. */
- receive(ANY, &m);
-
- /* Handle the request. Only clock ticks are expected. */
- switch (m.m_type) {
- case HARD_INT:
- result = do_clocktick(&m); /* handle clock tick */
- break;
- default: /* illegal request type */
- kprintf("CLOCK: illegal request %d from %d.\n", m.m_type,m.m_source);
- }
+ while(TRUE) {
+ /* Go get a message. */
+ result = receive(ANY, &m);
+
+ /* Handle the request. Only clock ticks are expected. */
+ switch (m.m_type) {
+ case HARD_INT:
+ result = do_clocktick(&m); /* handle clock tick */
+ break;
+ default: /* illegal request type */
+ kprintf("CLOCK: illegal request %d from %d.\n",
+ m.m_type, m.m_source);
+ }
}
}
/* Despite its name, this routine is not called on every clock tick. It
* is called on those clock ticks when a lot of work needs to be done.
*/
-
+
/* A process used up a full quantum. The interrupt handler stored this
* process in 'prev_ptr'. First make sure that the process is not on the
* scheduling queues. Then announce the process ready again. Since it has
* place in the queues. As a side-effect a new process will be scheduled.
*/
if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) {
- lock_dequeue(prev_ptr); /* take it off the queues */
+ if(prev_ptr->p_rts_flags == 0) /* if it was runnable .. */
+ lock_dequeue(prev_ptr); /* take it off the queues */
lock_enqueue(prev_ptr); /* and reinsert it again */
}
/* Check if a clock timer expired and run its watchdog function. */
- if (next_timeout <= realtime) {
- tmrs_exptimers(&clock_timers, realtime, NULL);
- next_timeout = clock_timers == NULL ?
- TMR_NEVER : clock_timers->tmr_exp_time;
+ if (next_timeout <= realtime) {
+ tmrs_exptimers(&clock_timers, realtime, NULL);
+ next_timeout = (clock_timers == NULL) ?
+ TMR_NEVER : clock_timers->tmr_exp_time;
}
/* Inhibit sending a reply. */
*===========================================================================*/
PRIVATE void init_clock()
{
+ /* First of all init the clock system.
+ *
+ * Here the (a) clock is set to produce a interrupt at
+ * every 1/60 second (ea. 60Hz).
+ *
+ * Running right away.
+ */
+ arch_init_clock(); /* architecture-dependent initialization. */
+
/* Initialize the CLOCK's interrupt hook. */
clock_hook.proc_nr_e = CLOCK;
-
- /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz, and register
- * the CLOCK task's interrupt handler to be run on every clock tick.
- */
- outb(TIMER_MODE, SQUARE_WAVE); /* set timer to run continuously */
- outb(TIMER0, TIMER_COUNT); /* load timer low byte */
- outb(TIMER0, TIMER_COUNT >> 8); /* load timer high byte */
+
put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);
enable_irq(&clock_hook); /* ready for clock interrupts */
-
+
/* Set a watchdog timer to periodically balance the scheduling queues. */
balance_queues(NULL); /* side-effect sets new timer */
}
-/*===========================================================================*
- * clock_stop *
- *===========================================================================*/
-PUBLIC void clock_stop()
-{
-/* Reset the clock to the BIOS rate. (For rebooting.) */
- outb(TIMER_MODE, 0x36);
- outb(TIMER0, 0);
- outb(TIMER0, 0);
-}
-
/*===========================================================================*
* clock_handler *
*===========================================================================*/
*/
register unsigned ticks;
- /* Acknowledge the PS/2 clock interrupt. */
- if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
-
/* Get number of ticks and update realtime. */
ticks = lost_ticks + 1;
lost_ticks = 0;
* process is running, charge the billable process for system time as well.
* Thus the unbillable process' user time is the billable user's system time.
*/
+
proc_ptr->p_user_time += ticks;
if (priv(proc_ptr)->s_flags & PREEMPTIBLE) {
proc_ptr->p_ticks_left -= ticks;
/* Update load average. */
load_update();
-
+
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
* Some processes, such as the kernel tasks, cannot be preempted.
*/
/*===========================================================================*
* get_uptime *
*===========================================================================*/
-PUBLIC clock_t get_uptime()
+PUBLIC clock_t get_uptime(void)
{
-/* Get and return the current clock uptime in ticks. */
+ /* Get and return the current clock uptime in ticks. */
return(realtime);
}
TMR_NEVER : clock_timers->tmr_exp_time;
}
-/*===========================================================================*
- * read_clock *
- *===========================================================================*/
-PUBLIC unsigned long read_clock()
-{
-/* Read the counter of channel 0 of the 8253A timer. This counter counts
- * down at a rate of TIMER_FREQ and restarts at TIMER_COUNT-1 when it
- * reaches zero. A hardware interrupt (clock tick) occurs when the counter
- * gets to zero and restarts its cycle.
- */
- unsigned count;
-
- outb(TIMER_MODE, LATCH_COUNT);
- count = inb(TIMER0);
- count |= (inb(TIMER0) << 8);
-
- return count;
-}
-
/*===========================================================================*
* load_update *
*===========================================================================*/
kloadinfo.last_clock = realtime;
}
+
+
/* How many bytes for the kernel stack. Space allocated in mpx.s. */
#define K_STACK_BYTES 1024
+#define K_PARAM_SIZE 512
+
/* This section allows to enable kernel debugging and timing functionality.
* For normal operation all options should be disabled.
*/
#ifndef CONST_H
#define CONST_H
-#include <ibm/interrupt.h> /* interrupt numbers and hardware vectors */
-#include <ibm/ports.h> /* port addresses and magic numbers */
-#include <ibm/bios.h> /* BIOS addresses, sizes and magic numbers */
-#include <ibm/cpu.h> /* BIOS addresses, sizes and magic numbers */
#include <minix/config.h>
#include <minix/bitmap.h>
#include "config.h"
-/* To translate an address in kernel space to a physical address. This is
- * the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly.
- */
-#define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir))
-
/* Map a process number to a privilege structure id. */
#define s_nr_to_id(n) (NR_TASKS + (n) + 1)
( MAP_CHUNK(map.chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) )
#define NR_SYS_CHUNKS BITMAP_CHUNKS(NR_SYS_PROCS)
-#if (CHIP == INTEL)
-
-/* Program stack words and masks. */
-#define INIT_PSW 0x0200 /* initial psw */
-#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
-#define TRACEBIT 0x0100 /* OR this with psw in proc[] for tracing */
-#define SETPSW(rp, new) /* permits only certain bits to be set */ \
- ((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
-#define IF_MASK 0x00000200
-#define IOPL_MASK 0x003000
-
#if DEBUG_LOCK_CHECK
-#define reallock(c, v) { if (!(read_cpu_flags() & X86_FLAG_I)) { kinfo.relocking++; } else { intr_disable(); } }
+#define reallock(c, v) { if(intr_disabled()) { kinfo.relocking++; } else { intr_disable(); } }
#else
-#define reallock(c, v) intr_disable()
+#define reallock(c, v) intr_disable()
#endif
-#define realunlock(c) intr_enable()
+#define realunlock(c) intr_enable()
+#if DEBUG_TIME_LOCKS
+#define lock(c, v) do { reallock(c, v); locktimestart(c, v); } while(0)
+#define unlock(c) do { locktimeend(c); realunlock(c); } while(0)
+#else
/* Disable/ enable hardware interrupts. The parameters of lock() and unlock()
* are used when debugging is enabled. See debug.h for more information.
*/
-#define lock(c, v) reallock(c, v)
-#define unlock(c) realunlock(c)
-
-/* Sizes of memory tables. The boot monitor distinguishes three memory areas,
- * namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
- * for DOS MINIX.
- */
-#define NR_MEMS 8
-
-#endif /* (CHIP == INTEL) */
+#define lock(c, v) reallock(c, v)
+#define unlock(c) realunlock(c)
+#endif
-#if (CHIP == M68000)
-/* M68000 specific constants go here. */
-#endif /* (CHIP == M68000) */
+/* args to intr_init() */
+#define INTS_ORIG 0 /* restore interrupts */
+#define INTS_MINIX 1 /* initialize interrupts for minix */
#endif /* CONST_H */
#define locktimeend(c)
#endif /* DEBUG_TIME_LOCKS */
-/* This check makes sure that the scheduling queues are in a consistent state.
- * The check is run when the queues are updated with ready() and unready().
- */
-#if DEBUG_SCHED_CHECK
-_PROTOTYPE( void check_runqueues, (char *when) );
-#endif /* DEBUG_SCHED_CHECK */
-
-/* The timing and checking of kernel locking requires a redefine of the lock()
- * and unlock() macros. That's done here. This redefine requires that this
- * header is included after the other kernel headers.
- */
-#if (DEBUG_TIME_LOCKS || DEBUG_LOCK_CHECK)
-# undef lock
-# define lock(c, v) do { reallock(c, v); locktimestart(c, v); } while(0)
-# undef unlock
-# define unlock(c) do { locktimeend(c); realunlock(c); } while(0)
-#endif
-
#endif /* DEBUG_H */
#endif
#include <minix/config.h>
+#include <archtypes.h>
#include "config.h"
/* Variables relating to shutting down MINIX. */
EXTERN char k_reenter; /* kernel reentry count (entry count less 1) */
EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */
-#if (CHIP == INTEL)
/* Interrupt related variables. */
EXTERN irq_hook_t irq_hooks[NR_IRQ_HOOKS]; /* hooks for general use */
-EXTERN irq_hook_t *irq_handlers[NR_IRQ_VECTORS];/* list of IRQ handlers */
EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */
EXTERN int irq_use; /* map of all in-use irq's */
extern struct segdesc_s gdt[]; /* global descriptor table */
EXTERN _PROTOTYPE( void (*level0_func), (void) );
-#endif /* (CHIP == INTEL) */
-
-#if (CHIP == M68000)
-/* M68000 specific variables go here. */
-#endif
#endif /* GLO_H */
+++ /dev/null
-/* This file contains routines for initializing the 8259 interrupt controller:
- * put_irq_handler: register an interrupt handler
- * rm_irq_handler: deregister an interrupt handler
- * intr_handle: handle a hardware interrupt
- * intr_init: initialize the interrupt controller(s)
- */
-
-#include "kernel.h"
-#include "proc.h"
-#include <minix/com.h>
-
-#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
-#define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */
-#define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */
-#define ICW4_AT_SLAVE 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
-#define ICW4_AT_MASTER 0x05 /* not SFNM, not buffered, normal EOI, 8086 */
-#define ICW4_PC_SLAVE 0x09 /* not SFNM, buffered, normal EOI, 8086 */
-#define ICW4_PC_MASTER 0x0D /* not SFNM, buffered, normal EOI, 8086 */
-
-#if _WORD_SIZE == 2
-typedef _PROTOTYPE( void (*vecaddr_t), (void) );
-
-FORWARD _PROTOTYPE( void set_vec, (int vec_nr, vecaddr_t addr) );
-
-PRIVATE vecaddr_t int_vec[] = {
- int00, int01, int02, int03, int04, int05, int06, int07,
-};
-
-PRIVATE vecaddr_t irq_vec[] = {
- hwint00, hwint01, hwint02, hwint03, hwint04, hwint05, hwint06, hwint07,
- hwint08, hwint09, hwint10, hwint11, hwint12, hwint13, hwint14, hwint15,
-};
-#else
-#define set_vec(nr, addr) ((void)0)
-#endif
-
-/*===========================================================================*
- * intr_init *
- *===========================================================================*/
-PUBLIC void intr_init(mine)
-int mine;
-{
-/* Initialize the 8259s, finishing with all interrupts disabled. This is
- * only done in protected mode, in real mode we don't touch the 8259s, but
- * use the BIOS locations instead. The flag "mine" is set if the 8259s are
- * to be programmed for MINIX, or to be reset to what the BIOS expects.
- */
- int i;
-
- intr_disable();
-
- if (machine.prot) {
- /* The AT and newer PS/2 have two interrupt controllers, one master,
- * one slaved at IRQ 2. (We don't have to deal with the PC that
- * has just one controller, because it must run in real mode.)
- */
- outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
- outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
- /* ICW2 for master */
- outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
- outb(INT_CTLMASK, ICW4_AT_MASTER);
- outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
- outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
- outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
- /* ICW2 for slave */
- outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
- outb(INT2_CTLMASK, ICW4_AT_SLAVE);
- outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
-
- /* Copy the BIOS vectors from the BIOS to the Minix location, so we
- * can still make BIOS calls without reprogramming the i8259s.
- */
-#if IRQ0_VECTOR != BIOS_IRQ0_VEC
- phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
-#endif
-#if IRQ8_VECTOR != BIOS_IRQ8_VEC
- phys_copy(BIOS_VECTOR(8) * 4L, VECTOR(8) * 4L, 8 * 4L);
-#endif
- } else {
- /* Use the BIOS interrupt vectors in real mode. We only reprogram the
- * exceptions here, the interrupt vectors are reprogrammed on demand.
- * SYS_VECTOR is the Minix system call for message passing.
- */
- for (i = 0; i < 8; i++) set_vec(i, int_vec[i]);
- set_vec(SYS_VECTOR, s_call);
- }
-}
-
-/*===========================================================================*
- * put_irq_handler *
- *===========================================================================*/
-PUBLIC void put_irq_handler(hook, irq, handler)
-irq_hook_t *hook;
-int irq;
-irq_handler_t handler;
-{
-/* Register an interrupt handler. */
- int id;
- irq_hook_t **line;
-
- if (irq < 0 || irq >= NR_IRQ_VECTORS)
- panic("invalid call to put_irq_handler", irq);
-
- line = &irq_handlers[irq];
- id = 1;
- while (*line != NULL) {
- if (hook == *line) return; /* extra initialization */
- line = &(*line)->next;
- id <<= 1;
- }
- if (id == 0) panic("Too many handlers for irq", irq);
-
- hook->next = NULL;
- hook->handler = handler;
- hook->irq = irq;
- hook->id = id;
- *line = hook;
-
- irq_use |= 1 << irq;
-}
-
-/*===========================================================================*
- * rm_irq_handler *
- *===========================================================================*/
-PUBLIC void rm_irq_handler(hook)
-irq_hook_t *hook;
-{
-/* Unregister an interrupt handler. */
- int irq = hook->irq;
- int id = hook->id;
- irq_hook_t **line;
-
- if (irq < 0 || irq >= NR_IRQ_VECTORS)
- panic("invalid call to rm_irq_handler", irq);
-
- line = &irq_handlers[irq];
- while (*line != NULL) {
- if ((*line)->id == id) {
- (*line) = (*line)->next;
- if (! irq_handlers[irq]) irq_use &= ~(1 << irq);
- return;
- }
- line = &(*line)->next;
- }
- /* When the handler is not found, normally return here. */
-}
-
-/*===========================================================================*
- * intr_handle *
- *===========================================================================*/
-PUBLIC void intr_handle(hook)
-irq_hook_t *hook;
-{
-/* Call the interrupt handlers for an interrupt with the given hook list.
- * The assembly part of the handler has already masked the IRQ, reenabled the
- * controller(s) and enabled interrupts.
- */
-
- /* Call list of handlers for an IRQ. */
- while (hook != NULL) {
- /* For each handler in the list, mark it active by setting its ID bit,
- * call the function, and unmark it if the function returns true.
- */
- irq_actids[hook->irq] |= hook->id;
- if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id;
- hook = hook->next;
- }
-
- /* The assembly code will now disable interrupts, unmask the IRQ if and only
- * if all active ID bits are cleared, and restart a process.
- */
-}
-
-#if _WORD_SIZE == 2
-/*===========================================================================*
- * set_vec *
- *===========================================================================*/
-PRIVATE void set_vec(vec_nr, addr)
-int vec_nr; /* which vector */
-vecaddr_t addr; /* where to start */
-{
-/* Set up a real mode interrupt vector. */
-
- u16_t vec[2];
-
- /* Build the vector in the array 'vec'. */
- vec[0] = (u16_t) addr;
- vec[1] = (u16_t) physb_to_hclick(code_base);
-
- /* Copy the vector into place. */
- phys_copy(vir2phys(vec), vec_nr * 4L, 4L);
-}
-#endif /* _WORD_SIZE == 2 */
--- /dev/null
+/* minix/kernel/interface.h - All interfaces the kernel needs. */
+
+#ifndef _KERNEL_IF_H_
+#define _KERNEL_IF_H_
+
+#include <minix/type.h>
+#include <archtypes.h>
+
+#endif /* #ifndef _KERNEL_IF_H_ */
--- /dev/null
+/*
+ * The Minix hardware interrupt system.
+ *
+ * This file contains routines for managing the interrupt
+ * controller.
+ *
+ * put_irq_handler: register an interrupt handler.
+ * rm_irq_handler: deregister an interrupt handler.
+ * intr_handle: handle a hardware interrupt.
+ * called by the system dependent part when an
+ * external interrupt occures.
+ * enable_irq: enable hook for IRQ.
+ * disable_irq: disable hook for IRQ.
+ */
+
+#include "kernel.h"
+#include "proc.h"
+#include <minix/com.h>
+#include <archconst.h>
+
+/* number of lists of IRQ hooks, one list per supported line. */
+PUBLIC irq_hook_t* irq_handlers[NR_IRQ_VECTORS] = {0};
+/*===========================================================================*
+ * put_irq_handler *
+ *===========================================================================*/
+/* Register an interrupt handler. */
+PUBLIC void put_irq_handler( irq_hook_t* hook, int irq, irq_handler_t handler)
+{
+ int id;
+ irq_hook_t **line;
+
+ if( irq < 0 || irq >= NR_IRQ_VECTORS )
+ panic("invalid call to put_irq_handler", irq);
+
+ line = &irq_handlers[irq];
+ id = 1;
+
+ while ( *line != NULL ) {
+ if(hook == *line) return; /* extra initialization */
+ line = &(*line)->next;
+ id <<= 1; /* max 32 hooks for one line. */
+ }
+
+ if(id == 0)
+ panic("Too many handlers for irq", irq);
+
+ hook->next = NULL;
+ hook->handler = handler;
+ hook->irq = irq;
+ hook->id = id;
+ *line = hook;
+ irq_use |= 1 << irq; /* this does not work for irq >= 32 */
+
+ /* And as last enable the irq at the hardware.
+ *
+ * Internal this activates the line or source of the given interrupt.
+ */
+ intr_unmask(hook);
+}
+
+/*===========================================================================*
+ * rm_irq_handler *
+ *===========================================================================*/
+/* Unregister an interrupt handler. */
+PUBLIC void rm_irq_handler( irq_hook_t* hook ) {
+ int irq = hook->irq;
+ int id = hook->id;
+ irq_hook_t **line;
+
+ if( irq < 0 || irq >= NR_IRQ_VECTORS )
+ panic("invalid call to rm_irq_handler", irq);
+
+ /* disable the irq. */
+ intr_mask(hook);
+
+ /* remove the hook. */
+ line = &irq_handlers[irq];
+
+ while( (*line) != NULL ) {
+ if((*line)->id == id) {
+ (*line) = (*line)->next;
+ if(!irq_handlers[irq])
+ irq_use &= ~(1 << irq);
+ return;
+ }
+ line = &(*line)->next;
+ }
+ /* When the handler is not found, normally return here. */
+}
+
+/*===========================================================================*
+ * intr_handle *
+ *===========================================================================*/
+PUBLIC void intr_handle(irq_hook_t *hook)
+{
+/* Call the interrupt handlers for an interrupt with the given hook list.
+ * The assembly part of the handler has already masked the IRQ, reenabled the
+ * controller(s) and enabled interrupts.
+ */
+
+ /* Call list of handlers for an IRQ. */
+ while( hook != NULL ) {
+ /* For each handler in the list, mark it active by setting its ID bit,
+ * call the function, and unmark it if the function returns true.
+ */
+ irq_actids[hook->irq] |= hook->id;
+
+ /* Call the hooked function. */
+ if( (*hook->handler)(hook) )
+ irq_actids[hook->irq] &= ~hook->id;
+
+ /* Next hooked function. */
+ hook = hook->next;
+ }
+
+ /* The assembly code will now disable interrupts, unmask the IRQ if and only
+ * if all active ID bits are cleared, and restart a process.
+ */
+}
+
+/* Enable/Disable a interrupt line. */
+PUBLIC void enable_irq(hook)
+irq_hook_t* hook;
+{
+ if((irq_actids[hook->irq] &= ~hook->id) == 0) {
+ intr_unmask(hook);
+ return;
+ }
+}
+
+/* Return true if the interrupt was enabled before call. */
+PUBLIC int disable_irq(hook)
+irq_hook_t* hook;
+{
+ if(irq_actids[hook->irq] & hook->id) /* already disabled */
+ return 0;
+ irq_actids[hook->irq] |= hook->id;
+ intr_mask(hook);
+ return TRUE;
+}
+
#include <timers.h> /* watchdog timer management */
#include <errno.h> /* return codes and error numbers */
-#if (CHIP == INTEL)
-#include <ibm/portio.h> /* device I/O and toggle interrupts */
-#endif
-
/* Important kernel header files. */
#include "config.h" /* configuration, MUST be first */
#include "const.h" /* constants, MUST be second */
+++ /dev/null
-#
-! Chooses between the 8086 and 386 versions of the low level kernel code.
-
-#include <minix/config.h>
-#if _WORD_SIZE == 2
-#include "klib88.s"
-#else
-#include "klib386.s"
-#endif
+++ /dev/null
-/*
- * printf for the kernel
- *
- * Changes:
- * Dec 10, 2004 kernel printing to circular buffer (Jorrit N. Herder)
- *
- * This file contains the routines that take care of kernel messages, i.e.,
- * diagnostic output within the kernel. Kernel messages are not directly
- * displayed on the console, because this must be done by the output driver.
- * Instead, the kernel accumulates characters in a buffer and notifies the
- * output driver when a new message is ready.
- */
-
-#include "kernel.h"
-#include "proc.h"
-#include <signal.h>
-
-#define printf kprintf
-
-#include "../lib/sysutil/kprintf.c"
-
-#define END_OF_KMESS 0
-FORWARD _PROTOTYPE( void ser_putc, (char c));
-
-/*===========================================================================*
- * kputc *
- *===========================================================================*/
-PUBLIC void kputc(c)
-int c; /* character to append */
-{
-/* Accumulate a single character for a kernel message. Send a notification
- * to the output driver if an END_OF_KMESS is encountered.
- */
- if (c != END_OF_KMESS) {
- if (do_serial_debug)
- ser_putc(c);
- kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
- if (kmess.km_size < KMESS_BUF_SIZE)
- kmess.km_size += 1;
- kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
- } else {
- int p, outprocs[] = OUTPUT_PROCS_ARRAY;
- for(p = 0; outprocs[p] != NONE; p++) {
- if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
- send_sig(outprocs[p], SIGKMESS);
- }
- }
- }
-}
-
-#define COM1_BASE 0x3F8
-#define COM1_THR (COM1_BASE + 0)
-#define LSR_THRE 0x20
-#define COM1_LSR (COM1_BASE + 5)
-
-PRIVATE void ser_putc(char c)
-{
- int i;
- int lsr, thr;
-
- return;
-
- lsr= COM1_LSR;
- thr= COM1_THR;
- for (i= 0; i<100000; i++)
- {
- if (inb(lsr) & LSR_THRE)
- break;
- }
- outb(thr, c);
-}
* The entries into this file are:
* main: MINIX main program
* prepare_shutdown: prepare to take MINIX down
- *
- * Changes:
- * Nov 24, 2004 simplified main() with system image (Jorrit N. Herder)
- * Aug 20, 2004 new prepare_shutdown() and shutdown() (Jorrit N. Herder)
*/
#include "kernel.h"
#include <signal.h>
/* Prototype declarations for PRIVATE functions. */
FORWARD _PROTOTYPE( void announce, (void));
-FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
+FORWARD _PROTOTYPE( void shutdown, (timer_t *));
/*===========================================================================*
* main *
reg_t ktsb; /* kernel task stack base */
struct exec e_hdr; /* for a copy of an a.out header */
- /* Initialize the interrupt controller. */
- intr_init(1);
-
/* Clear the process table. Anounce each slot as empty and set up mappings
* for proc_addr() and proc_nr() macros. Do the same for the table with
* privilege structures for the system processes.
alloc_segments(rp);
}
-#if ENABLE_BOOTDEV
- /* Expect an image of the boot device to be loaded into memory as well.
- * The boot device is the last module that is loaded into memory, and,
- * for example, can contain the root FS (useful for embedded systems).
- */
- hdrindex ++;
- phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
- if (e_hdr.a_flags & A_IMG) {
- kinfo.bootdev_base = e_hdr.a_syms;
- kinfo.bootdev_size = e_hdr.a_data;
- }
-#endif
-
#if SPROFILE
sprofiling = 0; /* we're not profiling until instructed to */
#endif /* SPROFILE */
kprintf("\nMINIX %s.%s. "
"Copyright 2006, Vrije Universiteit, Amsterdam, The Netherlands\n",
OS_RELEASE, OS_VERSION);
-#if (CHIP == INTEL)
- /* Real mode, or 16/32-bit protected mode? */
- kprintf("Executing in %s mode.\n\n",
- machine.prot ? "32-bit protected" : "real");
-#endif
}
/*===========================================================================*
tmr_arg(&shutdown_timer)->ta_int = how;
set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
}
+
/*===========================================================================*
* shutdown *
*===========================================================================*/
* down MINIX. How to shutdown is in the argument: RBT_HALT (return to the
* monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset).
*/
- int how = tmr_arg(tp)->ta_int;
- u16_t magic;
-
- /* Now mask all interrupts, including the clock, and stop the clock. */
- outb(INT_CTLMASK, ~0);
+ intr_init(INTS_ORIG);
clock_stop();
-
- if (mon_return && how != RBT_RESET) {
- /* Reinitialize the interrupt controllers to the BIOS defaults. */
- intr_init(0);
- outb(INT_CTLMASK, 0);
- outb(INT2_CTLMASK, 0);
-
- /* Return to the boot monitor. Set the program if not already done. */
- if (how != RBT_MONITOR) phys_copy(vir2phys(""), kinfo.params_base, 1);
- level0(monitor);
- }
-
- /* Reset the system by jumping to the reset address (real mode), or by
- * forcing a processor shutdown (protected mode). First stop the BIOS
- * memory test by setting a soft reset flag.
- */
- magic = STOP_MEM_CHECK;
- phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE);
- level0(reset);
+ arch_shutdown(tmr_arg(tp)->ta_int);
}
+++ /dev/null
-#
-! Chooses between the 8086 and 386 versions of the Minix startup code.
-
-#include <minix/config.h>
-#if _WORD_SIZE == 2
-#include "mpx88.s"
-#else
-#include "mpx386.s"
-#endif
* Jul 01, 2005 Created. (Jorrit N. Herder)
*/
#include <minix/com.h>
-#include "protect.h"
#include "const.h"
#include "type.h"
#include "kernel.h"
#include "proc.h"
#include <signal.h>
+#include <minix/portio.h>
/* Scheduling and message passing functions. The functions are available to
* other parts of the kernel through lock_...(). The lock temporarily disables
break; \
}
-#if (CHIP == INTEL)
#define CopyMess(s,sp,sm,dp,dm) \
cp_mess(proc_addr(s)->p_endpoint, \
- (sp)->p_memmap[D].mem_phys, \
+ (sp)->p_memmap[D].mem_phys, \
(vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm)
-#endif /* (CHIP == INTEL) */
-
-#if (CHIP == M68000)
-/* M68000 does not have cp_mess() in assembly like INTEL. Declare prototype
- * for cp_mess() here and define the function below. Also define CopyMess.
- */
-#endif /* (CHIP == M68000) */
/*===========================================================================*
* sys_call *
int src_dst;
vir_clicks vlo, vhi; /* virtual clicks containing message to send */
-#if 0
+#if 1
if (caller_ptr->p_rts_flags & SLOT_FREE)
{
kprintf("called by the dead?!?\n");
xpp = &caller_ptr->p_caller_q;
while (*xpp != NIL_PROC) {
if (src_e == ANY || src_p == proc_nr(*xpp)) {
-#if 0
+#if 1
if ((*xpp)->p_rts_flags & SLOT_FREE)
{
kprintf("listening to the dead?!?\n");
int front; /* add to front or back */
#if DEBUG_SCHED_CHECK
- check_runqueues("enqueue");
+ check_runqueues("enqueue1");
if (rp->p_ready) kprintf("enqueue() already ready process\n");
#endif
#if DEBUG_SCHED_CHECK
rp->p_ready = 1;
- check_runqueues("enqueue");
+ check_runqueues("enqueue2");
#endif
}
}
#if DEBUG_SCHED_CHECK
- check_runqueues("dequeue");
- if (! rp->p_ready) kprintf("dequeue() already unready process\n");
+ check_runqueues("dequeue1");
+ if (! rp->p_ready) kprintf("%s:%d: dequeue() already unready process\n",
+ f_str, f_line);
#endif
/* Now make sure that the process is not in its ready queue. Remove the
#if DEBUG_SCHED_CHECK
rp->p_ready = 0;
- check_runqueues("dequeue");
+ check_runqueues("dequeue2");
#endif
}
* struct proc, be sure to change sconst.h to match.
*/
#include <minix/com.h>
-#include "protect.h"
#include "const.h"
#include "priv.h"
struct proc {
struct stackframe_s p_reg; /* process' registers saved in stack frame */
-
-#if (CHIP == INTEL)
- reg_t p_ldt_sel; /* selector in gdt with ldt base and limit */
- struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */
-#endif
-
-#if (CHIP == M68000)
-/* M68000 specific registers and FPU details go here. */
-#endif
-
+ struct segframe p_seg; /* segment descriptors */
proc_nr_t p_nr; /* number of this process (for fast access) */
struct priv *p_priv; /* system privileges structure */
short p_rts_flags; /* process is runnable only if zero */
* profiling.
*
* Statistical Profiling:
- * The interrupt handler and control functions for the CMOS clock.
+ * The interrupt handler for profiling clock.
*
* Call Profiling:
* The table used for profiling data and a function to get its size.
#if SPROFILE || CPROFILE
#include <minix/profile.h>
+#include <minix/portio.h>
#include "kernel.h"
#include "profile.h"
#include "proc.h"
#if SPROFILE
#include <string.h>
-#include <ibm/cmos.h>
-/* Function prototype for the CMOS clock handler. */
-FORWARD _PROTOTYPE( int cmos_clock_handler, (irq_hook_t *hook) );
+/* Function prototype for the profiling clock handler. */
+FORWARD _PROTOTYPE( int profile_clock_handler, (irq_hook_t *hook) );
-/* A hook for the CMOS clock interrupt handler. */
-PRIVATE irq_hook_t cmos_clock_hook;
+/* A hook for the profiling clock interrupt handler. */
+PRIVATE irq_hook_t profile_clock_hook;
/*===========================================================================*
- * init_cmos_clock *
+ * init_profile_clock *
*===========================================================================*/
-PUBLIC void init_cmos_clock(unsigned freq)
+PUBLIC void init_profile_clock(u32_t freq)
{
- int r;
- /* Register interrupt handler for statistical system profiling.
- * This uses the CMOS timer.
- */
- cmos_clock_hook.proc_nr_e = CLOCK;
- put_irq_handler(&cmos_clock_hook, CMOS_CLOCK_IRQ, cmos_clock_handler);
- enable_irq(&cmos_clock_hook);
+ int r, irq;
intr_disable();
- /* Set CMOS timer frequency. */
- outb(RTC_INDEX, RTC_REG_A);
- outb(RTC_IO, RTC_A_DV_OK | freq);
- /* Enable CMOS timer interrupts. */
- outb(RTC_INDEX, RTC_REG_B);
- r = inb(RTC_IO);
- outb(RTC_INDEX, RTC_REG_B);
- outb(RTC_IO, r | RTC_B_PIE);
- /* Mandatory read of CMOS register to enable timer interrupts. */
- outb(RTC_INDEX, RTC_REG_C);
- inb(RTC_IO);
+ if((irq = arch_init_profile_clock(freq)) >= 0) {
+ /* Register interrupt handler for statistical system profiling. */
+ profile_clock_hook.proc_nr_e = CLOCK;
+ put_irq_handler(&profile_clock_hook, irq, profile_clock_handler);
+ enable_irq(&profile_clock_hook);
+ }
intr_enable();
}
/*===========================================================================*
- * cmos_clock_stop *
+ * profile_clock_stop *
*===========================================================================*/
-PUBLIC void stop_cmos_clock()
+PUBLIC void stop_profile_clock()
{
- int r;
-
intr_disable();
-
- /* Disable CMOS timer interrupts. */
- outb(RTC_INDEX, RTC_REG_B);
- r = inb(RTC_IO);
- outb(RTC_INDEX, RTC_REG_B);
- outb(RTC_IO, r & !RTC_B_PIE);
-
+ arch_stop_profile_clock();
intr_enable();
/* Unregister interrupt handler. */
- disable_irq(&cmos_clock_hook);
- rm_irq_handler(&cmos_clock_hook);
+ disable_irq(&profile_clock_hook);
+ rm_irq_handler(&profile_clock_hook);
}
/*===========================================================================*
- * cmos_clock_handler *
+ * profile_clock_handler *
*===========================================================================*/
-PRIVATE int cmos_clock_handler(hook)
+PRIVATE int profile_clock_handler(hook)
irq_hook_t *hook;
{
/* This executes on every tick of the CMOS timer. */
sprof_info.total_samples++;
- /* Mandatory read of CMOS register to re-enable timer interrupts. */
- outb(RTC_INDEX, RTC_REG_C);
- inb(RTC_IO);
+ /* Acknowledge interrupt if necessary. */
+ arch_ack_profile_clock();
return(1); /* reenable interrupts */
}
#if SPROFILE /* statistical profiling */
-_PROTOTYPE( void init_cmos_clock, (unsigned freq) );
-_PROTOTYPE( void stop_cmos_clock, (void) );
-
EXTERN int sprofiling; /* whether profiling is running */
EXTERN int sprof_mem_size; /* available user memory for data */
EXTERN struct sprof_info_s sprof_info; /* profiling info for user program */
#define PROTO_H
#include <minix/safecopies.h>
+#include <archtypes.h>
/* Struct declarations. */
struct proc;
/* clock.c */
_PROTOTYPE( void clock_task, (void) );
-_PROTOTYPE( void clock_stop, (void) );
_PROTOTYPE( clock_t get_uptime, (void) );
-_PROTOTYPE( unsigned long read_clock, (void) );
_PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) );
_PROTOTYPE( void reset_timer, (struct timer *tp) );
/* main.c */
_PROTOTYPE( void main, (void) );
_PROTOTYPE( void prepare_shutdown, (int how) );
+_PROTOTYPE( void idle_task, (void) );
/* utility.c */
_PROTOTYPE( int kprintf, (const char *fmt, ...) );
vir_bytes bytes) );
#define numap_local(proc_nr, vir_addr, bytes) \
umap_local(proc_addr(proc_nr), D, (vir_addr), (bytes))
-_PROTOTYPE( phys_bytes umap_local, (struct proc *rp, int seg,
- vir_bytes vir_addr, vir_bytes bytes) );
-_PROTOTYPE( phys_bytes umap_remote, (struct proc *rp, int seg,
- vir_bytes vir_addr, vir_bytes bytes) );
-_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
- vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_grant, (struct proc *, cp_grant_id_t,
vir_bytes));
_PROTOTYPE( phys_bytes umap_verify_grant, (struct proc *, endpoint_t,
cp_grant_id_t, vir_bytes, vir_bytes, int));
_PROTOTYPE( void clear_endpoint, (struct proc *rc) );
+_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
+ vir_bytes bytes));
/* system/do_newmap.c */
_PROTOTYPE( int newmap, (struct proc *rp, struct mem_map *map_ptr) );
-#if (CHIP == INTEL)
-
-/* exception.c */
-_PROTOTYPE( void exception, (unsigned vec_nr) );
-_PROTOTYPE( void stacktrace, (struct proc *) );
-
-/* i8259.c */
-_PROTOTYPE( void intr_init, (int mine) );
-_PROTOTYPE( void intr_handle, (irq_hook_t *hook) );
+/* interrupt.c */
+_PROTOTYPE( void intr_handle, (irq_hook_t *hook) );
_PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq,
- irq_handler_t handler) );
-_PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook) );
-
-/* klib*.s */
-_PROTOTYPE( void int86, (void) );
-_PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset,
- phys_clicks dst_clicks, vir_bytes dst_offset) );
-_PROTOTYPE( void enable_irq, (irq_hook_t *hook) );
-_PROTOTYPE( int disable_irq, (irq_hook_t *hook) );
-_PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset) );
-_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
- phys_bytes count) );
-_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
- phys_bytes count) );
-_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
-_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
-_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
-_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
-_PROTOTYPE( void reset, (void) );
-_PROTOTYPE( void level0, (void (*func)(void)) );
-_PROTOTYPE( void monitor, (void) );
-_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) );
-_PROTOTYPE( unsigned long read_cr0, (void) );
-_PROTOTYPE( void write_cr0, (unsigned long value) );
-_PROTOTYPE( void write_cr3, (unsigned long value) );
-_PROTOTYPE( unsigned long read_cpu_flags, (void) );
-
-/* mpx*.s */
-_PROTOTYPE( void idle_task, (void) );
-_PROTOTYPE( void restart, (void) );
-
-/* The following are never called from C (pure asm procs). */
-
-/* Exception handlers (real or protected mode), in numerical order. */
-void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) );
-void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
-void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) );
-void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
-void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) );
-void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) );
-void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
-void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
-void _PROTOTYPE( double_fault, (void) );
-void _PROTOTYPE( copr_seg_overrun, (void) );
-void _PROTOTYPE( inval_tss, (void) );
-void _PROTOTYPE( segment_not_present, (void) );
-void _PROTOTYPE( stack_exception, (void) );
-void _PROTOTYPE( general_protection, (void) );
-void _PROTOTYPE( page_fault, (void) );
-void _PROTOTYPE( copr_error, (void) );
-
-/* Hardware interrupt handlers. */
-_PROTOTYPE( void hwint00, (void) );
-_PROTOTYPE( void hwint01, (void) );
-_PROTOTYPE( void hwint02, (void) );
-_PROTOTYPE( void hwint03, (void) );
-_PROTOTYPE( void hwint04, (void) );
-_PROTOTYPE( void hwint05, (void) );
-_PROTOTYPE( void hwint06, (void) );
-_PROTOTYPE( void hwint07, (void) );
-_PROTOTYPE( void hwint08, (void) );
-_PROTOTYPE( void hwint09, (void) );
-_PROTOTYPE( void hwint10, (void) );
-_PROTOTYPE( void hwint11, (void) );
-_PROTOTYPE( void hwint12, (void) );
-_PROTOTYPE( void hwint13, (void) );
-_PROTOTYPE( void hwint14, (void) );
-_PROTOTYPE( void hwint15, (void) );
-
-/* Software interrupt handlers, in numerical order. */
-_PROTOTYPE( void trp, (void) );
-_PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
-_PROTOTYPE( void level0_call, (void) );
-
-/* protect.c */
-_PROTOTYPE( void prot_init, (void) );
-_PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
- vir_bytes size, int privilege) );
-_PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
- vir_bytes size, int privilege) );
-_PROTOTYPE( phys_bytes seg2phys, (U16_t seg) );
-_PROTOTYPE( void phys2seg, (u16_t *seg, vir_bytes *off, phys_bytes phys));
-_PROTOTYPE( void enable_iop, (struct proc *pp) );
-_PROTOTYPE( void alloc_segments, (struct proc *rp) );
+ irq_handler_t handler) );
+_PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook) );
+_PROTOTYPE( void enable_irq, (irq_hook_t *hook) );
+_PROTOTYPE( int disable_irq, (irq_hook_t *hook) );
+
+/* debug.c */
+#if DEBUG_SCHED_CHECK
+_PROTOTYPE( void check_runqueues, (char *when) );
+#endif
/* system/do_vm.c */
_PROTOTYPE( void vm_map_default, (struct proc *pp) );
_PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes,
int, vir_bytes, vir_bytes *, endpoint_t *));
-#endif /* (CHIP == INTEL) */
+#if SPROFILE
+/* profile.c */
+_PROTOTYPE( void init_profile_clock, (u32_t) );
+_PROTOTYPE( void stop_profile_clock, (void) );
+#endif
+
+/* functions defined in architecture-dependent files. */
+_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
+ phys_bytes count) );
+_PROTOTYPE( void alloc_segments, (struct proc *rp) );
+_PROTOTYPE( void vm_init, (void) );
+_PROTOTYPE( void vm_map_range, (u32_t base, u32_t size, u32_t offset) );
+_PROTOTYPE( phys_bytes umap_local, (register struct proc *rp, int seg,
+ vir_bytes vir_addr, vir_bytes bytes));
+_PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,
+ vir_bytes src_offset, phys_clicks dst_clicks, vir_bytes dst_offset));
+_PROTOTYPE( phys_bytes umap_remote, (struct proc* rp, int seg,
+ vir_bytes vir_addr, vir_bytes bytes) );
+_PROTOTYPE( phys_bytes seg2phys, (U16_t) );
+_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
+ phys_bytes count) );
+_PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *,
+ int, phys_bytes, vir_bytes, int));
+_PROTOTYPE( int arch_init_clock, (void) );
+_PROTOTYPE( clock_t read_clock, (void) );
+_PROTOTYPE( void clock_stop, (void) );
+_PROTOTYPE( int intr_init, (int) );
+_PROTOTYPE( int intr_disabled, (void) );
+_PROTOTYPE( int intr_unmask, (irq_hook_t* hook) );
+_PROTOTYPE( int intr_mask, (irq_hook_t* hook) );
+_PROTOTYPE( void idle_task, (void) );
+_PROTOTYPE( void system_init, (void) );
+_PROTOTYPE( void ser_putc, (char) );
+_PROTOTYPE( void arch_shutdown, (int) );
+_PROTOTYPE( void restart, (void) );
+_PROTOTYPE( void idle_task, (void) );
+_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) );
+_PROTOTYPE( int arch_init_profile_clock, (u32_t freq) );
+_PROTOTYPE( void arch_stop_profile_clock, (void) );
+_PROTOTYPE( void arch_ack_profile_clock, (void) );
-#if (CHIP == M68000)
-/* M68000 specific prototypes go here. */
-#endif /* (CHIP == M68000) */
#endif /* PROTO_H */
-/* This file contains the C startup code for Minix on Intel processors.
- * It cooperates with mpx.s to set up a good environment for main().
- *
- * This code runs in real mode for a 16 bit kernel and may have to switch
- * to protected mode for a 286.
- * For a 32 bit kernel this already runs in protected mode, but the selectors
- * are still those given by the BIOS with interrupts disabled, so the
- * descriptors need to be reloaded and interrupt descriptors made.
- */
+
+/* First C file used by the kernel. */
#include "kernel.h"
-#include "protect.h"
#include "proc.h"
#include <stdlib.h>
#include <string.h>
+#include <archconst.h>
+
+PRIVATE char params[K_PARAM_SIZE];
FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
/*===========================================================================*
extern int etext, end;
int h;
- /* Decide if mode is protected; 386 or higher implies protected mode.
- * This must be done first, because it is needed for, e.g., seg2phys().
- * For 286 machines we cannot decide on protected mode, yet. This is
- * done below.
- */
-#if _WORD_SIZE != 2
- machine.prot = 1;
-#endif
-
/* Record where the kernel and the monitor are. */
kinfo.code_base = seg2phys(cs);
kinfo.code_size = (phys_bytes) &etext; /* size of code segment */
kinfo.data_base = seg2phys(ds);
kinfo.data_size = (phys_bytes) &end; /* size of data segment */
- /* Initialize protected mode descriptors. */
- prot_init();
+ /* Architecture-dependent initialization. */
+ system_init();
/* Copy the boot parameters to the local buffer. */
kinfo.params_base = seg2phys(mds) + parmoff;
kinfo.params_size = MIN(parmsize,sizeof(params)-2);
- phys_copy(kinfo.params_base, vir2phys(params), kinfo.params_size);
+ phys_copy(kinfo.params_base,
+ vir2phys(params), kinfo.params_size);
/* Record miscellaneous information for user-space servers. */
kinfo.nr_procs = NR_PROCS;
for(h = 0; h < _LOAD_HISTORY; h++)
kloadinfo.proc_load_history[h] = 0;
- /* Processor? 86, 186, 286, 386, ...
- * Decide if mode is protected for older machines.
- */
+ /* Processor? Decide if mode is protected for older machines. */
machine.processor=atoi(get_value(params, "processor"));
-#if _WORD_SIZE == 2
- machine.prot = machine.processor >= 286;
-#endif
- if (! machine.prot) mon_return = 0;
/* XT, AT or MCA bus? */
value = get_value(params, "bus");
/* Return to assembler code to switch to protected mode (if 286),
* reload selectors and call main().
*/
+
+ intr_init(INTS_MINIX);
}
/*===========================================================================*
* get_priv: assign privilege structure to user or system process
* send_sig: send a signal directly to a system process
* cause_sig: take action to cause a signal to occur via PM
- * umap_local: map virtual address in LOCAL_SEG to physical
- * umap_remote: map virtual address in REMOTE_SEG to physical
* umap_bios: map virtual address in BIOS_SEG to physical
- * umap_grant: map grant number in a process to physical
* virtual_copy: copy bytes from one virtual address to another
* get_randomness: accumulate randomness in a buffer
* clear_endpoint: remove a process' ability to send and receive messages
#include <sys/sigcontext.h>
#include <minix/endpoint.h>
#include <minix/safecopies.h>
-#if (CHIP == INTEL)
-#include <ibm/memory.h>
-#include "protect.h"
-#endif
/* Declaration of the call vector that defines the mapping of system calls
* to handler functions. The vector is initialized in sys_init() with map(),
/* Device I/O. */
map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */
map(SYS_DEVIO, do_devio); /* inb, inw, inl, outb, outw, outl */
- map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
- map(SYS_INT86, do_int86); /* real-mode BIOS calls */
/* Memory management. */
map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
map(SYS_SAFECOPYFROM, do_safecopy); /* copy with pre-granted permission */
map(SYS_SAFECOPYTO, do_safecopy); /* copy with pre-granted permission */
map(SYS_VSAFECOPY, do_vsafecopy); /* vectored safecopy */
- map(SYS_READBIOS, do_readbios); /* read from BIOS locations */
/* Clock functionality. */
map(SYS_TIMES, do_times); /* get uptime and process times */
/* System control. */
map(SYS_ABORT, do_abort); /* abort MINIX */
map(SYS_GETINFO, do_getinfo); /* request system information */
- map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */
/* Profiling. */
map(SYS_SPROF, do_sprofile); /* start/stop statistical profiling */
map(SYS_CPROF, do_cprofile); /* get/reset call profiling data */
map(SYS_PROFBUF, do_profbuf); /* announce locations to kernel */
+
+ /* i386-specific. */
+#if _MINIX_CHIP == _CHIP_INTEL
+ map(SYS_INT86, do_int86); /* real-mode BIOS calls */
+ map(SYS_READBIOS, do_readbios); /* read from BIOS locations */
+ map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */
+ map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
+#endif
}
/*===========================================================================*
PUBLIC void get_randomness(source)
int source;
{
-/* On machines with the RDTSC (cycle counter read instruction - pentium
- * and up), use that for high-resolution raw entropy gathering. Otherwise,
- * use the realtime clock (tick resolution).
- *
- * Unfortunately this test is run-time - we don't want to bother with
- * compiling different kernels for different machines.
- *
- * On machines without RDTSC, we use read_clock().
+/* Use architecture-dependent high-resolution clock for
+ * raw entropy gathering.
*/
int r_next;
unsigned long tsc_high, tsc_low;
source %= RANDOM_SOURCES;
r_next= krandom.bin[source].r_next;
- if (machine.processor > 486) {
- read_tsc(&tsc_high, &tsc_low);
- krandom.bin[source].r_buf[r_next] = tsc_low;
- } else {
- krandom.bin[source].r_buf[r_next] = read_clock();
- }
+ read_tsc(&tsc_high, &tsc_low);
+ krandom.bin[source].r_buf[r_next] = tsc_low;
if (krandom.bin[source].r_size < RANDOM_ELEMENTS) {
krandom.bin[source].r_size ++;
}
}
}
+#if _MINIX_CHIP == _CHIP_INTEL
+
/*===========================================================================*
* umap_bios *
*===========================================================================*/
vir_bytes bytes; /* # of bytes to be copied */
{
/* Calculate the physical memory address at the BIOS. Note: currently, BIOS
- * address zero (the first BIOS interrupt vector) is not considered, as an
+ * address zero (the first BIOS interrupt vector) is not considered as an
* error here, but since the physical address will be zero as well, the
* calling function will think an error occurred. This is not a problem,
* since no one uses the first BIOS interrupt vector.
else if (vir_addr >= BASE_MEM_TOP && vir_addr + bytes <= UPPER_MEM_END)
return (phys_bytes) vir_addr;
-#if DEAD_CODE /* brutal fix, if the above is too restrictive */
- if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
- return (phys_bytes) vir_addr;
-#endif
-
kprintf("Warning, error in umap_bios, virtual address 0x%x\n", vir_addr);
return 0;
}
-
-/*===========================================================================*
- * umap_local *
- *===========================================================================*/
-PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes)
-register struct proc *rp; /* pointer to proc table entry for process */
-int seg; /* T, D, or S segment */
-vir_bytes vir_addr; /* virtual address in bytes within the seg */
-vir_bytes bytes; /* # of bytes to be copied */
-{
-/* Calculate the physical memory address for a given virtual address. */
- vir_clicks vc; /* the virtual address in clicks */
- phys_bytes pa; /* intermediate variables as phys_bytes */
-#if (CHIP == INTEL)
- phys_bytes seg_base;
-#endif
-
- /* If 'seg' is D it could really be S and vice versa. T really means T.
- * If the virtual address falls in the gap, it causes a problem. On the
- * 8088 it is probably a legal stack reference, since "stackfaults" are
- * not detected by the hardware. On 8088s, the gap is called S and
- * accepted, but on other machines it is called D and rejected.
- * The Atari ST behaves like the 8088 in this respect.
- */
-
- if (bytes <= 0) return( (phys_bytes) 0);
- if (vir_addr + bytes <= vir_addr) return 0; /* overflow */
- vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
-
-#if (CHIP == INTEL) || (CHIP == M68000)
- if (seg != T)
- seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S);
-#else
- if (seg != T)
- seg = (vc < rp->p_memmap[S].mem_vir ? D : S);
#endif
- if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir +
- rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
-
- if (vc >= rp->p_memmap[seg].mem_vir +
- rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );
-
-#if (CHIP == INTEL)
- seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys;
- seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
-#endif
- pa = (phys_bytes) vir_addr;
-#if (CHIP != M68000)
- pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
- return(seg_base + pa);
-#endif
-#if (CHIP == M68000)
- pa -= (phys_bytes)rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
- pa += (phys_bytes)rp->p_memmap[seg].mem_phys << CLICK_SHIFT;
- return(pa);
-#endif
-}
-
-/*===========================================================================*
- * umap_grant *
- *===========================================================================*/
-PUBLIC phys_bytes umap_grant(rp, grant, bytes)
-struct proc *rp; /* pointer to proc table entry for process */
-cp_grant_id_t grant; /* grant no. */
-vir_bytes bytes; /* size */
-{
- int proc_nr;
- vir_bytes offset;
- endpoint_t granter;
-
- /* See if the grant in that process is sensible, and
- * find out the virtual address and (optionally) new
- * process for that address.
- *
- * Then convert that process to a slot number.
- */
- if(verify_grant(rp->p_endpoint, ANY, grant, bytes, 0, 0,
- &offset, &granter) != OK) {
- return 0;
- }
-
- if(!isokendpt(granter, &proc_nr)) {
- return 0;
- }
-
- /* Do the mapping from virtual to physical. */
- return umap_local(proc_addr(proc_nr), D, offset, bytes);
-}
-
-/*===========================================================================*
- * umap_remote *
- *===========================================================================*/
-PUBLIC phys_bytes umap_remote(rp, seg, vir_addr, bytes)
-register struct proc *rp; /* pointer to proc table entry for process */
-int seg; /* index of remote segment */
-vir_bytes vir_addr; /* virtual address in bytes within the seg */
-vir_bytes bytes; /* # of bytes to be copied */
-{
-/* Calculate the physical memory address for a given virtual address. */
- struct far_mem *fm;
-
- if (bytes <= 0) return( (phys_bytes) 0);
- if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
-
- fm = &rp->p_priv->s_farmem[seg];
- if (! fm->in_use) return( (phys_bytes) 0);
- if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0);
-
- return(fm->mem_phys + (phys_bytes) vir_addr);
-}
-
/*===========================================================================*
* umap_verify_grant *
*===========================================================================*/
return umap_local(proc_addr(proc_nr), D, v_offset, bytes);
}
+/*===========================================================================*
+ * umap_grant *
+ *===========================================================================*/
+PUBLIC phys_bytes umap_grant(rp, grant, bytes)
+struct proc *rp; /* pointer to proc table entry for process */
+cp_grant_id_t grant; /* grant no. */
+vir_bytes bytes; /* size */
+{
+ int proc_nr;
+ vir_bytes offset;
+ endpoint_t granter;
+
+ /* See if the grant in that process is sensible, and
+ * find out the virtual address and (optionally) new
+ * process for that address.
+ *
+ * Then convert that process to a slot number.
+ */
+ if(verify_grant(rp->p_endpoint, ANY, grant, bytes, 0, 0,
+ &offset, &granter) != OK) {
+ return 0;
+ }
+
+ if(!isokendpt(granter, &proc_nr)) {
+ return 0;
+ }
+
+ /* Do the mapping from virtual to physical. */
+ return umap_local(proc_addr(proc_nr), D, offset, bytes);
+}
+
/*===========================================================================*
* virtual_copy *
*===========================================================================*/
seg_index = vir_addr[i]->segment & SEGMENT_INDEX;
phys_addr[i] = umap_remote(p, seg_index, vir_addr[i]->offset, bytes);
break;
+#if _MINIX_CHIP == _CHIP_INTEL
case BIOS_SEG:
if(!p) return EDEADSRCDST;
phys_addr[i] = umap_bios(p, vir_addr[i]->offset, bytes );
break;
+#endif
case PHYS_SEG:
phys_addr[i] = vir_addr[i]->offset;
break;
{
register struct proc *rp; /* iterate over process table */
register struct proc **xpp; /* iterate over caller queue */
- int i;
- int sys_id;
if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc));
# Makefile for system library implementation
+include /etc/make.conf
+
# Directories
u = /usr
i = $u/include
+a = ../arch
# Programs, flags, etc.
CC = exec cc $(CFLAGS) -c
CCNOPROF = exec cc $(CFLAGSNOPROF) -c # no call profiling for these
CPP = $l/cpp
LD = $(CC) -.o
-CFLAGS = -I$i $(CPROFILE)
+CFLAGS = -I$i $(CPROFILE) -I$a/$(ARCH)/include
CFLAGSNOPROF = -I$i
LDFLAGS = -i
$(SYSTEM)(do_irqctl.o) \
$(SYSTEM)(do_devio.o) \
$(SYSTEM)(do_vdevio.o) \
- $(SYSTEM)(do_int86.o) \
- $(SYSTEM)(do_sdevio.o) \
$(SYSTEM)(do_copy.o) \
$(SYSTEM)(do_vcopy.o) \
$(SYSTEM)(do_umap.o) \
$(SYSTEM)(do_getksig.o) \
$(SYSTEM)(do_endksig.o) \
$(SYSTEM)(do_kill.o) \
- $(SYSTEM)(do_readbios.o) \
$(SYSTEM)(do_sigsend.o) \
$(SYSTEM)(do_sigreturn.o) \
$(SYSTEM)(do_abort.o) \
$(SYSTEM)(do_getinfo.o) \
- $(SYSTEM)(do_iopenable.o) \
$(SYSTEM)(do_vm.o) \
$(SYSTEM)(do_vm_setbuf.o) \
$(SYSTEM)(do_sprofile.o) \
$(SYSTEM)(do_cprofile.o) \
$(SYSTEM)(do_profbuf.o)
-$(SYSTEM): $(OBJECTS)
+build $(SYSTEM): $(OBJECTS)
aal cr $@ *.o
clean:
$(SYSTEM)(do_devio.o): do_devio.c
$(CC) do_devio.c
-$(SYSTEM)(do_sdevio.o): do_sdevio.c
- $(CC) do_sdevio.c
-
$(SYSTEM)(do_vdevio.o): do_vdevio.c
$(CC) do_vdevio.c
-$(SYSTEM)(do_int86.o): do_int86.c
- $(CC) do_int86.c
-
$(SYSTEM)(do_copy.o): do_copy.c
$(CC) do_copy.c
$(SYSTEM)(do_abort.o): do_abort.c
$(CC) do_abort.c
-$(SYSTEM)(do_readbios.o): do_readbios.c
- $(CC) do_readbios.c
-
$(SYSTEM)(do_setgrant.o): do_setgrant.c
$(CC) do_setgrant.c
$(SYSTEM)(do_segctl.o): do_segctl.c
$(CC) do_segctl.c
-$(SYSTEM)(do_iopenable.o): do_iopenable.c
- $(CC) do_iopenable.c
-
$(SYSTEM)(do_vm.o): do_vm.o
do_vm.o: do_vm.c
$(CC) do_vm.c
#include "../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
+#include <minix/portio.h>
#if USE_DEVIO
/* Process a single I/O request for byte, word, and long values. */
if (io_dir == _DIO_INPUT) {
switch (io_type) {
+ /* maybe "it" should not be called ports */
case _DIO_BYTE: m_ptr->DIO_VALUE = inb(m_ptr->DIO_PORT); break;
case _DIO_WORD: m_ptr->DIO_VALUE = inw(m_ptr->DIO_PORT); break;
- case _DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
+ case _DIO_LONG: m_ptr->DIO_VALUE = inl(m_ptr->DIO_PORT); break;
default: return(EINVAL);
}
} else {
switch (io_type) {
- case _DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
+ case _DIO_BYTE: outb(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
case _DIO_WORD: outw(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
- case _DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
+ case _DIO_LONG: outl(m_ptr->DIO_PORT, m_ptr->DIO_VALUE); break;
default: return(EINVAL);
}
}
rp = proc_addr(proc);
sp = (reg_t) m_ptr->PR_STACK_PTR;
rp->p_reg.sp = sp; /* set the stack pointer */
-#if (CHIP == M68000)
- rp->p_splow = sp; /* set the stack pointer low water */
-#ifdef FPP
- /* Initialize fpp for this process */
- fpp_new_state(rp);
-#endif
-#endif
-#if (CHIP == INTEL) /* wipe extra LDT entries */
- phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 0,
- (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
+
+#if (_MINIX_CHIP == _CHIP_INTEL)
+ /* wipe extra LDT entries */
+ phys_memset(vir2phys(&rp->p_seg.p_ldt[EXTRA_LDT_INDEX]), 0,
+ (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_seg.p_ldt[0]));
#endif
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */
if (rp->p_rts_flags == 0) lock_enqueue(rp);
/* Save command name for debugging, ps(1) output, etc. */
phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR,
- (vir_bytes) P_NAME_LEN - 1);
+ (vir_bytes) P_NAME_LEN - 1);
if (phys_name != 0) {
phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1);
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
} else {
strncpy(rp->p_name, "<unset>", P_NAME_LEN);
}
+
return(OK);
}
#endif /* USE_EXEC */
#include "../system.h"
#include <signal.h>
-#if (CHIP == INTEL)
-#include "../protect.h"
-#endif
#include <minix/endpoint.h>
register message *m_ptr; /* pointer to request message */
{
/* Handle sys_fork(). PR_ENDPT has forked. The child is PR_SLOT. */
-#if (CHIP == INTEL)
+#if (_MINIX_CHIP == _CHIP_INTEL)
reg_t old_ldt_sel;
#endif
register struct proc *rpc; /* child process pointer */
/* Copy parent 'proc' struct to child. And reinitialize some fields. */
gen = _ENDPOINT_G(rpc->p_endpoint);
-#if (CHIP == INTEL)
- old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */
+#if (_MINIX_CHIP == _CHIP_INTEL)
+ old_ldt_sel = rpc->p_seg.p_ldt_sel; /* backup local descriptors */
*rpc = *rpp; /* copy 'proc' struct */
- rpc->p_ldt_sel = old_ldt_sel; /* restore descriptors */
+ rpc->p_seg.p_ldt_sel = old_ldt_sel; /* restore descriptors */
#else
*rpc = *rpp; /* copy 'proc' struct */
#endif
#include "../system.h"
+#if !( POWERPC )
+
static unsigned long bios_buf[1024]; /* 4K, what about alignment */
static vir_bytes bios_buf_vir, bios_buf_len;
+#endif /* #if !( POWERPC ) */
+
+
#if USE_GETINFO
/*===========================================================================*
break;
}
#endif
+
+#if !( POWERPC )
case GET_BIOSBUFFER:
bios_buf_vir = (vir_bytes)bios_buf;
bios_buf_len = sizeof(bios_buf);
length = sizeof(bios_buf_vir);
src_phys = vir2phys(&bios_buf_vir);
break;
-
+#endif /* #if !( POWERPC ) */
+
case GET_IRQACTIDS: {
length = sizeof(irq_actids);
src_phys = vir2phys(irq_actids);
src_phys = umap_local(proc_addr(who_p), D, (vir_bytes) map_ptr,
sizeof(rp->p_memmap));
if (src_phys == 0) return(EFAULT);
- phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap));
+ phys_copy(src_phys,vir2phys(rp->p_memmap),
+ (phys_bytes)sizeof(rp->p_memmap));
-#if (CHIP != M68000)
alloc_segments(rp);
-#else
- pmmu_init_proc(rp);
-#endif
old_flags = rp->p_rts_flags; /* save the previous value of the flags */
if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp);
if (pri == PRIO_STOP) {
/* Take process off the scheduling queues. */
- lock_dequeue(rp);
+ if(rp->p_rts_flags == 0) lock_dequeue(rp);
rp->p_rts_flags |= NO_PRIORITY;
return(OK);
}
/* Make sure the process is not running while changing its priority.
* Put the process back in its new queue if it is runnable.
*/
- lock_dequeue(rp);
+ if(rp->p_rts_flags == 0) lock_dequeue(rp);
rp->p_rts_flags &= ~NO_PRIORITY;
rp->p_max_priority = rp->p_priority = new_q;
if (! rp->p_rts_flags) lock_enqueue(rp);
PUBLIC int do_safecopy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
- static endpoint_t new_granter;
static int access, src_seg, dst_seg;
/* Set src and dst parameters.
* m4_l5: SEG_INDEX (return index into remote memory map here)
*/
#include "../system.h"
-#include "../protect.h"
#if USE_SEGCTL
/* Return a segment selector and offset that can be used to reach a physical
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
*/
- u16_t selector;
+ u32_t selector;
vir_bytes offset;
int i, index;
register struct proc *rp;
}
if (index < 0) return(ENOSPC);
- if (! machine.prot) {
- selector = phys / HCLICK_SIZE;
- offset = phys % HCLICK_SIZE;
- result = OK;
- } else {
- /* Check if the segment size can be recorded in bytes, that is, check
- * if descriptor's limit field can delimited the allowed memory region
- * precisely. This works up to 1MB. If the size is larger, 4K pages
- * instead of bytes are used.
- */
- if (size < BYTE_GRAN_MAX) {
- init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
- USER_PRIVILEGE);
- selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
- offset = 0;
- result = OK;
- } else {
- init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
- USER_PRIVILEGE);
- selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
- offset = phys & 0xFFFF;
- result = OK;
- }
- }
+ offset = alloc_remote_segment(&selector, &rp->p_seg,
+ i, phys, size, USER_PRIVILEGE);
+ result = OK;
/* Request successfully done. Now return the result. */
m_ptr->SEG_INDEX = index | REMOTE_SEG;
sc.sc_psw = rp->p_reg.psw;
-#if (CHIP == INTEL)
+#if (_MINIX_CHIP == _CHIP_INTEL)
/* Don't panic kernel if user gave bad selectors. */
sc.sc_cs = rp->p_reg.cs;
sc.sc_ds = rp->p_reg.ds;
#endif
/* Restore the registers. */
+#if _MINIX_CHIP == _CHIP_POWERPC
+ memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct stackframe_s));
+#else
memcpy(&rp->p_reg, &sc.sc_regs, sizeof(struct sigregs));
+#endif
return(OK);
}
#endif /* USE_SIGRETURN */
/* Copy the registers to the sigcontext structure. */
memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
+#ifdef POWERPC
+ memcpy(&sc.sc_regs, (char *) &rp->p_reg, struct(stackframe_s));
+#else
+ memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(struct sigregs));
+#endif
/* Finish the sigcontext initialization. */
sc.sc_flags = 0; /* unused at this time */
if (dst_phys == 0) return(EFAULT);
phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
+#if ( _MINIX_CHIP == _CHIP_POWERPC ) /* stuff that can't be done in the assembler code. */
+ /* When the signal handlers C code is called it will write this value
+ * into the signal frame (over the sf_retadr value).
+ */
+ rp->p_reg.lr = smsg.sm_sigreturn;
+ /* The first (and only) parameter for the user signal handler function.
+ */
+ rp->p_reg.retreg = smsg.sm_signo; /* note the retreg == first argument */
+#endif
+
/* Reset user registers to execute the signal handler. */
rp->p_reg.sp = (reg_t) frp;
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
sprof_mem_size = m_ptr->PROF_MEM_SIZE;
- init_cmos_clock(m_ptr->PROF_FREQ);
+ init_profile_clock(m_ptr->PROF_FREQ);
sprofiling = 1;
sprofiling = 0;
- stop_cmos_clock();
+ stop_profile_clock();
phys_copy(vir2phys((vir_bytes) &sprof_info),
sprof_info_addr, (phys_bytes) sizeof(sprof_info));
tr_addr > sizeof(struct stackframe_s) - sizeof(reg_t))
return(EIO);
i = (int) tr_addr;
-#if (CHIP == INTEL)
+#if (_MINIX_CHIP == _CHIP_INTEL)
/* Altering segment registers might crash the kernel when it
* tries to load them prior to restarting a process, so do
* not allow it.
case REMOTE_SEG:
phys_addr = umap_remote(proc_addr(proc_nr), seg_index, offset, count);
break;
+#if _MINIX_CHIP == _CHIP_INTEL
case BIOS_SEG:
phys_addr = umap_bios(proc_addr(proc_nr), offset, count);
break;
+#endif
case GRANT_SEG:
phys_addr = umap_grant(proc_addr(proc_nr), offset, count);
break;
#include "../system.h"
#include <minix/devio.h>
#include <minix/endpoint.h>
+#include <minix/portio.h>
#if USE_VDEVIO
lock(13, "do_vdevio");
switch (io_type) {
case _DIO_BYTE: /* byte values */
- if (io_in) for (i=0; i<vec_size; i++) pvb[i].value = inb(pvb[i].port);
- else for (i=0; i<vec_size; i++) outb(pvb[i].port, pvb[i].value);
+ if (io_in) for (i=0; i<vec_size; i++)
+ pvb[i].value = inb( pvb[i].port);
+ else for (i=0; i<vec_size; i++)
+ outb( pvb[i].port, pvb[i].value);
break;
case _DIO_WORD: /* word values */
- if (io_in) for (i=0; i<vec_size; i++) pvw[i].value = inw(pvw[i].port);
- else for (i=0; i<vec_size; i++) outw(pvw[i].port, pvw[i].value);
+ if (io_in) for (i=0; i<vec_size; i++)
+ pvw[i].value = inw( pvw[i].port);
+ else for (i=0; i<vec_size; i++)
+ outw( pvw[i].port, pvw[i].value);
break;
default: /* long values */
- if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);
- else for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value);
+ if (io_in) for (i=0; i<vec_size; i++)
+ pvl[i].value = inl(pvl[i].port);
+ else for (i=0; i<vec_size; i++)
+ outl( pvb[i].port, pvl[i].value);
}
unlock(13);
* m4_l2: Map (TRUE) or unmap (FALSE) (VM_MAP_MAPUNMAP)
* m4_l3: Base address (VM_MAP_BASE)
* m4_l4: Size (VM_MAP_SIZE)
- * m4_l5: Memory address (VM_MAP_ADDR)
+ * m4_l5: address (VM_MAP_ADDR)
*/
#include "../system.h"
-#include <sys/vm.h>
-
PRIVATE int vm_needs_init= 1;
-PRIVATE u32_t vm_cr3;
-FORWARD _PROTOTYPE( void vm_init, (void) );
-FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
-FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
-FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
-FORWARD _PROTOTYPE( void set_cr3, (void) );
-FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
-FORWARD _PROTOTYPE( void map_range, (u32_t base, u32_t size,
- u32_t offset) );
+#include <sys/vm.h>
/*===========================================================================*
* do_vm_map *
struct proc *pp;
/* do_serial_debug= 1; */
-
if (vm_needs_init)
{
- vm_needs_init= 0;
- vm_init();
+ vm_needs_init= 0;
+ vm_init();
}
if (m_ptr->VM_MAP_ENDPT == SELF) {
{
pp->p_misc_flags |= MF_VM;
- map_range(p_phys, size, offset);
+ vm_map_range(p_phys, size, offset);
}
else
{
- map_range(p_phys, size, p_phys);
+ vm_map_range(p_phys, size, p_phys);
}
- vm_set_cr3(vm_cr3);
return OK;
}
+
/*===========================================================================*
* vm_map_default *
*===========================================================================*/
base_clicks= pp->p_memmap[D].mem_phys;
size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
base_clicks;
- map_range(base_clicks << CLICK_SHIFT, size_clicks << CLICK_SHIFT,
- base_clicks << CLICK_SHIFT);
- vm_set_cr3(vm_cr3);
-}
-
-PRIVATE void vm_init(void)
-{
- int o;
- phys_bytes p, pt_size;
- phys_bytes vm_dir_base, vm_pt_base, phys_mem;
- u32_t entry;
- unsigned pages;
-
- if (!vm_size)
- panic("vm_init: no space for page tables", NO_NUM);
-
- /* Align page directory */
- o= (vm_base % PAGE_SIZE);
- if (o != 0)
- o= PAGE_SIZE-o;
- vm_dir_base= vm_base+o;
-
- /* Page tables start after the page directory */
- vm_pt_base= vm_dir_base+PAGE_SIZE;
-
- pt_size= (vm_base+vm_size)-vm_pt_base;
- pt_size -= (pt_size % PAGE_SIZE);
-
- /* Compute the number of pages based on vm_mem_high */
- pages= (vm_mem_high-1)/PAGE_SIZE + 1;
-
- if (pages * I386_VM_PT_ENT_SIZE > pt_size)
- panic("vm_init: page table too small", NO_NUM);
-
- for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
- {
- phys_mem= p*PAGE_SIZE;
- entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
- I386_VM_PRESENT;
- if (phys_mem >= vm_mem_high)
- entry= 0;
- phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
- }
-
- for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
- {
- phys_mem= vm_pt_base + p*PAGE_SIZE;
- entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
- I386_VM_PRESENT;
- if (phys_mem >= vm_pt_base + pt_size)
- entry= 0;
- phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
- }
- vm_set_cr3(vm_dir_base);
- level0(vm_enable_paging);
-}
-
-PRIVATE void phys_put32(addr, value)
-phys_bytes addr;
-u32_t value;
-{
- phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
-}
-
-PRIVATE u32_t phys_get32(addr)
-phys_bytes addr;
-{
- u32_t value;
-
- phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
-
- return value;
-}
-
-PRIVATE void vm_set_cr3(value)
-u32_t value;
-{
- vm_cr3= value;
- level0(set_cr3);
-}
-
-PRIVATE void set_cr3()
-{
- write_cr3(vm_cr3);
-}
-
-PRIVATE void vm_enable_paging(void)
-{
- u32_t cr0;
-
- cr0= read_cr0();
- write_cr0(cr0 | I386_CR0_PG);
+ vm_map_range(base_clicks << CLICK_SHIFT,
+ size_clicks << CLICK_SHIFT, base_clicks << CLICK_SHIFT);
}
-PRIVATE void map_range(base, size, offset)
-u32_t base;
-u32_t size;
-u32_t offset;
-{
- u32_t curr_pt, curr_pt_addr, entry;
- int dir_ent, pt_ent;
-
- if (base % PAGE_SIZE != 0)
- panic("map_range: bad base", base);
- if (size % PAGE_SIZE != 0)
- panic("map_range: bad size", size);
- if (offset % PAGE_SIZE != 0)
- panic("map_range: bad offset", offset);
-
- curr_pt= -1;
- curr_pt_addr= 0;
- while (size != 0)
- {
- dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
- pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
- if (dir_ent != curr_pt)
- {
- /* Get address of page table */
- curr_pt= dir_ent;
- curr_pt_addr= phys_get32(vm_cr3 +
- dir_ent * I386_VM_PT_ENT_SIZE);
- curr_pt_addr &= I386_VM_ADDR_MASK;
- }
- entry= offset | I386_VM_USER | I386_VM_WRITE |
- I386_VM_PRESENT;
-#if 0 /* Do we need this for memory mapped I/O? */
- entry |= I386_VM_PCD | I386_VM_PWT;
-#endif
- phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
- offset += PAGE_SIZE;
- base += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-}
#include "proc.h"
#include "ipc.h"
#include <minix/com.h>
-#include <ibm/int86.h>
/* Define stack sizes for the kernel tasks included in the system image. */
#define NO_STACK 0
} bin[RANDOM_SOURCES];
};
-#if (CHIP == INTEL)
-typedef unsigned reg_t; /* machine register */
-
-/* The stack frame layout is determined by the software, but for efficiency
- * it is laid out so the assembly code to use it is as simple as possible.
- * 80286 protected mode and all real modes use the same frame, built with
- * 16-bit registers. Real mode lacks an automatic stack switch, so little
- * is lost by using the 286 frame for it. The 386 frame differs only in
- * having 32-bit registers and more segment registers. The same names are
- * used for the larger registers to avoid differences in the code.
- */
-struct stackframe_s { /* proc_ptr points here */
-#if _WORD_SIZE == 4
- u16_t gs; /* last item pushed by save */
- u16_t fs; /* ^ */
-#endif
- u16_t es; /* | */
- u16_t ds; /* | */
- reg_t di; /* di through cx are not accessed in C */
- reg_t si; /* order is to match pusha/popa */
- reg_t fp; /* bp */
- reg_t st; /* hole for another copy of sp */
- reg_t bx; /* | */
- reg_t dx; /* | */
- reg_t cx; /* | */
- reg_t retreg; /* ax and above are all pushed by save */
- reg_t retadr; /* return address for assembly code save() */
- reg_t pc; /* ^ last item pushed by interrupt */
- reg_t cs; /* | */
- reg_t psw; /* | */
- reg_t sp; /* | */
- reg_t ss; /* these are pushed by CPU during interrupt */
-};
-
-struct segdesc_s { /* segment descriptor for protected mode */
- u16_t limit_low;
- u16_t base_low;
- u8_t base_middle;
- u8_t access; /* |P|DL|1|X|E|R|A| */
- u8_t granularity; /* |G|X|0|A|LIMT| */
- u8_t base_high;
-};
-
typedef unsigned long irq_policy_t;
typedef unsigned long irq_id_t;
typedef int (*irq_handler_t)(struct irq_hook *);
-#endif /* (CHIP == INTEL) */
-
-#if (CHIP == M68000)
-/* M68000 specific types go here. */
-#endif /* (CHIP == M68000) */
-
#endif /* TYPE_H */
/* This file contains a collection of miscellaneous procedures:
* panic: abort MINIX due to a fatal error
+ * kprintf: (from lib/sysutil/kprintf.c)
+ * kputc: buffered putc used by kernel kprintf
*/
#include "kernel.h"
+#include "proc.h"
+
#include <unistd.h>
+#include <signal.h>
/*===========================================================================*
* panic *
/* Abort MINIX. */
prepare_shutdown(RBT_PANIC);
}
+
+
+/* Include system printf() implementation named kprintf() */
+
+#define printf kprintf
+#include "../lib/sysutil/kprintf.c"
+#define END_OF_KMESS 0
+
+/*===========================================================================*
+ * kputc *
+ *===========================================================================*/
+PUBLIC void kputc(c)
+int c; /* character to append */
+{
+/* Accumulate a single character for a kernel message. Send a notification
+ * to the output driver if an END_OF_KMESS is encountered.
+ */
+ if (c != END_OF_KMESS) {
+ if (do_serial_debug)
+ ser_putc(c);
+ kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
+ if (kmess.km_size < KMESS_BUF_SIZE)
+ kmess.km_size += 1;
+ kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
+ } else {
+ int p, outprocs[] = OUTPUT_PROCS_ARRAY;
+ for(p = 0; outprocs[p] != NONE; p++) {
+ if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
+ send_sig(outprocs[p], SIGKMESS);
+ }
+ }
+ }
+}
+
#OBJDIR=.
+. /etc/make.conf
+
SUBDIRS="ansi \
curses \
dummy \
util \
sysutil \
timers \
- i386 \
+ $ARCH \
zlib-1.2.3 \
ack
gnu"
{
if (_clean) _clean(); /* flush all output files */
raise(SIGABRT);
+ /* NORETURN */
}
#!/bin/sh
# called with parameters: 1:dir 2:ackbase 3:gnubase
+set -e
+
+. /etc/make.conf
+
exec >Makefile
exec 3>Makedepend-ack
exec 4>Makedepend-gnu
echo "install: install-ack"
echo
echo "install-ack: all-ack"
- echo " cp $ACKBASE/*.[ao] /usr/lib/i386"
+ # $ARCH is from /etc/make.conf
+ echo " cp $ACKBASE/*.[ao] /usr/lib/$ARCH"
echo
echo "install-gnu: all-gnu"
echo " cp $GNUBASE/*.[ao] /usr/gnu/lib"
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include <net/netlib.h>
int getdomainname(domain, size)
#include <lib.h>
#define lstat _lstat
+#define stat _stat
#include <sys/stat.h>
#include <string.h>
#include "pci.h"
#include "syslib.h"
+#include <unistd.h>
#include <minix/rs.h>
#include <minix/sysutil.h>
CC=cc
-CFLAGS=-O
+CFLAGS="-O -D_POSIX_SOURCE -D_MINIX"
LIBRARIES=libz
# Makefile for Information Server (IS)
SERVER = is
+include /etc/make.conf
+
# directories
u = /usr
i = $u/include
# programs, flags, etc.
CC = exec cc
-CFLAGS = -I$i $(CPROFILE)
+CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$i
+CFLAGS = $(CPROFILE) $(CPPFLAGS)
LDFLAGS = -i
LIBS = -lsysutil -lsys
#include <timers.h>
#include <ibm/interrupt.h>
#include <minix/endpoint.h>
+#include <minix/sys_config.h>
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include "../../kernel/debug.h"
printf("- pc_at: %3d\n", machine.pc_at);
printf("- ps_mca: %3d\n", machine.ps_mca);
printf("- processor: %3d\n", machine.processor);
- printf("- protected: %3d\n", machine.prot);
printf("- vdu_ega: %3d\n", machine.vdu_ega);
printf("- vdu_vga: %3d\n\n", machine.vdu_vga);
printf("Kernel info structure:\n");
return;
}
- printf("\n-nr-----gen---endpoint-name--- -prior-quant- -user---sys----size-rts flags-\n");
+ printf("\n-nr-----gen---endpoint-name--- -prior-quant- -user----sys----size-rts flags\n");
for (rp = oldrp; rp < END_PROC_ADDR; rp++) {
if (isemptyp(rp)) continue;
else if (proc_nr(rp) < 0) printf("[%2d] ", proc_nr(rp));
else printf(" %2d ", proc_nr(rp));
printf(" %5d %10d ", _ENDPOINT_G(rp->p_endpoint), rp->p_endpoint);
- printf("%-8.8s %02u/%02u %02d/%02u %6lu%6lu %6uK %s",
+ printf("%-8.8s %02u/%02u %02d/%02u %6lu %6lu %5uK %s",
rp->p_name,
rp->p_priority, rp->p_max_priority,
rp->p_ticks_left, rp->p_quantum_size,
#include <unistd.h>
#include <signal.h>
+#include <archtypes.h>
#include "proto.h"
#include "glo.h"
# Makefile for Process Manager (PM)
SERVER = pm
+include /etc/make.conf
+
# directories
u = /usr
i = $u/include
# programs, flags, etc.
CC = exec cc
-CFLAGS = -I$i $(CPROFILE)
+CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$i
+CFLAGS = $(CPROFILE) $(CPPFLAGS)
LDFLAGS = -i
OBJ = main.o forkexit.o break.o exec.o time.o timers.o \
#include <signal.h>
#include <stdlib.h>
#include <string.h>
+#include <archconst.h>
#include "mproc.h"
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include <sys/resource.h>
#include <sys/utsname.h>
#include <string.h>
+#include <archconst.h>
+#include <archtypes.h>
#include "mproc.h"
#include "param.h"
#include <minix/sysinfo.h>
#include <minix/type.h>
#include <string.h>
+#include <archconst.h>
+#include <archtypes.h>
#include <lib.h>
#include "mproc.h"
#include "param.h"
struct mproc *p_mp;
clock_t t[5];
+ printf("dumpcore for %d / %s\n", rmp->mp_pid, rmp->mp_name);
+
/* Do not create core files for set uid execution */
if (rmp->mp_realuid != rmp->mp_effuid) return OK;
#include <minix/config.h>
#include <timers.h>
#include <string.h>
+#include <archconst.h>
+#include <archtypes.h>
#include "../../kernel/const.h"
#include "../../kernel/config.h"
#include "../../kernel/type.h"
SERVER = rs
UTIL = service
+include /etc/make.conf
+
# directories
u = /usr
i = $u/include
# programs, flags, etc.
CC = exec cc
-CFLAGS = -I$i $(CPROFILE)
+CPPFLAGS = -I../../kernel/arch/$(ARCH)/include
+CFLAGS = -I$i $(CPROFILE) $(CPPFLAGS)
LDFLAGS = -i
UTIL_LIBS = -lsysutil -lsys
LIBS = -lsysutil -lsys
#include <minix/keymap.h>
#include <minix/bitmap.h>
+#include <archtypes.h>
#include <timers.h> /* For priv.h */
#include "../../kernel/priv.h"