/* Register function key for debugging dumps. */
fkey_enable(SF8);
-/* Set special disk parameters then call the generic main loop. */
+#if DEAD_CODE
if ((s=get_own_proc_nr(&win_tasknr)) != OK)
server_panic(w_name(),"Couldn't get own process number",s);
+#endif
+ printf("AT wini task started.\n");
+/* Set special disk parameters then call the generic main loop. */
init_params();
driver_task(&w_dtab);
}
int s;
/* Get the number of drives from the BIOS data area */
- if ((s=sys_vircopy(SELF, BIOS_SEG, ADR_WINI_PARAMS,
- SELF, D, (vir_bytes) params, LEN_WINI_PARAMS)) != OK)
+ if ((s=sys_vircopy(SELF, BIOS_SEG, NR_HD_DRIVES_ADDR,
+ SELF, D, (vir_bytes) params, NR_HD_DRIVES_SIZE)) != OK)
server_panic(w_name(), "Couldn't read BIOS", s);
if ((nr_drives = params[0]) > 2) nr_drives = 2;
for (drive = 0, wn = wini; drive < MAX_DRIVES; drive++, wn++) {
if (drive < nr_drives) {
- /* Copy the BIOS parameter vector */
- vector = drive == 0 ? ADR_WINI_0_PARM_VEC:ADR_WINI_1_PARM_VEC;
- size = drive == 0 ? LEN_WINI_0_PARM_VEC:LEN_WINI_1_PARM_VEC;
- if ((s=sys_vircopy(SELF, BIOS_SEG, vector,
+ /* Copy the BIOS parameter vector */
+ vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR:BIOS_HD1_PARAMS_ADDR;
+ size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE:BIOS_HD1_PARAMS_SIZE;
+ if ((s=sys_vircopy(SELF, BIOS_SEG, vector,
SELF, D, (vir_bytes) parv, size)) != OK)
server_panic(w_name(), "Couldn't read BIOS", s);
if (w_specify() != OK && w_specify() != OK) return(ERR);
- printf("%s: user-level AT Winchester driver detected ", w_name());
+ printf("%s: user-space AT Winchester driver detected ", w_name());
if (wn->state & (SMART|ATAPI)) {
printf("%.40s\n", id_string);
} else {
/* Everything looks OK; register IRQ so we can stop polling. */
wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ;
+#if DEAD_CODE
sys_irqsetpolicy(w_wn->irq, (IRQ_READ_PORT | IRQ_BYTE | IRQ_REENABLE), SELF,
(w_wn->base + REG_STATUS), &w_byteval, 0);
+#else
+ sys_irqsetpolicy(w_wn->irq, IRQ_REENABLE, SELF, 0, 0, 0);
+#endif
sys_irqenable(wn->irq);
return(OK);
}
if (m.m_type == SYN_ALARM) { /* but check for timeout */
w_timeout(); /* a.o. set w_status */
} else if (m.m_type == HARD_INT) {
+#if DEAD_CODE
w_status = w_byteval; /* read by generic handler */
+#else
+ sys_inb((w_wn->base + REG_STATUS), &w_status);
+#endif
}
}
} else {
r = do_vrdwt(dp, &mess); break;
case HARD_INT: /* leftover interrupt or expired timer. */
- /* printf("Driver.c: Left-over interrupt!\n"); */
continue;
case HARD_STOP: (*dp->dr_stop)(dp);
continue; /* don't reply */
/* Read the partition table at 'offset'. */
if (proc_nr == NONE) {
- if ((s=get_proc_nr(&proc_nr,NULL)) != OK) {
+ if ((s=sys_getprocnr(&proc_nr,0,0)) != OK) {
printf("%s: can't get own proc nr: %d\n", (*dp->dr_name)(), s);
- return 0;
+ return(0);
}
}
position = offset << SECTOR_SHIFT;
* /dev/mem - absolute memory
* /dev/kmem - kernel virtual memory
* /dev/null - null device (data sink)
- * /dev/boot - boot FS loaded from boot image
+ * /dev/boot - boot device loaded from boot image
+ * /dev/random - random number generator
+ * /dev/zero - null byte stream generator
*
* Changes:
- * Apr 09, 2005 added support for boot FS (Jorrit N. Herder)
+ * Apr 29, 2005 added null byte generator (Jorrit N. Herder)
+ * Apr 27, 2005 added random device handling (Jorrit N. Herder)
+ * Apr 09, 2005 added support for boot device (Jorrit N. Herder)
* Sep 03, 2004 secured code with ENABLE_USERPRIV (Jorrit N. Herder)
* Jul 26, 2004 moved RAM driver to user-space (Jorrit N. Herder)
* Apr 20, 1992 device dependent/independent split (Kees J. Bot)
#include "../drivers.h"
#include "../libdriver/driver.h"
#include <sys/ioc_memory.h>
-#if (CHIP == INTEL) && ENABLE_USERBIOS
-#include <ibm/int86.h>
-#endif
-#define NR_DEVS 6 /* number of RAM-type devices */
+#define NR_DEVS 7 /* number of minor devices */
-PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each RAM disk */
+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 */
-PRIVATE struct kenviron kenv; /* need protected_mode */
+PRIVATE struct kinfo kinfo; /* need kernel info */
+PRIVATE struct machine machine; /* need machine info */
PRIVATE struct psinfo psinfo = { NR_TASKS, NR_PROCS, 0, 0, 0 };
-#define RANDOM_BUFFER_SIZE (1024*32)
-PRIVATE char random_state[RANDOM_BUFFER_SIZE];
-
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) );
nop_alarm, /* ignore leftover alarms */
};
+/* Buffer for the /dev/zero null byte feed. */
+#define ZERO_BUF_SIZE 1024
+PRIVATE char zero[ZERO_BUF_SIZE];
+
+/* Buffer for the /dev/random number generator. */
+#define RANDOM_BUF_SIZE 1024
+PRIVATE char random[RANDOM_BUF_SIZE];
+
/*===========================================================================*
* main *
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
{
-/* Read or write /dev/null, /dev/mem, /dev/kmem, /dev/ram, /dev/boot,
- * /dev/random, or /dev/urandom
- */
-
+/* Read or write /dev/null, /dev/mem, /dev/kmem, /dev/ram, or /dev/boot. */
int device;
phys_bytes mem_phys, user_phys;
- unsigned count;
+ int seg;
+ unsigned count, left, chunk;
vir_bytes user_vir;
struct device *dv;
unsigned long dv_size;
+ int s;
/* Get minor device number and check for /dev/null. */
device = m_device;
dv = &m_geom[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;
switch (device) {
+
+ /* No copying; ignore request. */
case NULL_DEV:
if (opcode == DEV_GATHER) return(OK); /* always at EOF */
break;
- case RANDOM_DEV:
- return OK;
- break;
- default:
- /* /dev/mem, /dev/kmem, /dev/ram, /dev/boot: check for EOF */
- if (position >= dv_size) return(OK);
+ /* Virtual copying. For boot device. */
+ case RAM_DEV:
+ case KMEM_DEV:
+ case BOOT_DEV:
+ if (position >= dv_size) return(OK); /* check for EOF */
+ if (position + count > dv_size) count = dv_size - position;
+ seg = m_seg[device];
+
+ if (opcode == DEV_GATHER) { /* copy actual data */
+ sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count);
+ } else {
+ sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count);
+ }
+ break;
+
+ /* Physical copying. Only used to access entire memory. */
+ case MEM_DEV:
+ if (position >= dv_size) return(OK); /* check for EOF */
if (position + count > dv_size) count = dv_size - position;
mem_phys = cv64ul(dv->dv_base) + position;
- /* Copy the data. */
- if (opcode == DEV_GATHER) {
- sys_copy(ABS, D, mem_phys, proc_nr, D, user_vir, count);
+ if (opcode == DEV_GATHER) { /* copy data */
+ sys_physcopy(NONE, PHYS_SEG, mem_phys,
+ proc_nr, D, user_vir, count);
} else {
- sys_copy(proc_nr, D, user_vir, ABS, D, mem_phys, count);
+ sys_physcopy(proc_nr, D, user_vir,
+ NONE, PHYS_SEG, mem_phys, count);
}
+ break;
+
+ /* Random number generator. Character instead of block device. */
+ case RANDOM_DEV:
+ printf("MEMORY: please note /dev/random is NOT yet random!\n");
+ left = count;
+ while (left > 0) {
+ chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
+ if (opcode == DEV_GATHER) {
+ sys_vircopy(SELF, D, (vir_bytes) random,
+ proc_nr, D, user_vir, chunk);
+ } else if (opcode == DEV_SCATTER) {
+ sys_vircopy(proc_nr, D, user_vir,
+ SELF, D, (vir_bytes) random, chunk);
+ }
+ left -= chunk;
+ }
+ break;
+
+ /* Null byte stream generator. */
+ case ZERO_DEV:
+ if (opcode == DEV_GATHER) {
+ left = count;
+ while (left > 0) {
+ chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left;
+ if (OK != (s=sys_vircopy(SELF, D, (vir_bytes) zero,
+ proc_nr, D, user_vir, chunk)))
+ printf("MEMORY: sys_vircopy failed: %d\n", s);
+ left -= chunk;
+ }
+ }
+ break;
+
+ /* Unknown (illegal) minor device. */
+ default:
+ return(EINVAL);
}
/* Book the number of bytes transferred. */
position += count;
iov->iov_addr += count;
if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
+
}
return(OK);
}
message *m_ptr;
{
/* Check device number on open. Give I/O privileges to a process opening
- * /dev/mem or /dev/kmem. This is needed for systems with memory mapped I/O.
+ * /dev/mem or /dev/kmem. This may be needed in case of memory mapped I/O.
*/
if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
*===========================================================================*/
PRIVATE void m_init()
{
- /* Initialize this task. */
- extern int end;
- int s;
+ /* Initialize this task. All minor devices are initialized one by one. */
+ int i,s;
/* Print welcome message. */
- printf("MEMORY: user-level memory (RAM) driver is alive");
+ printf("MEMORY: user-level memory (RAM, etc.) driver is alive\n");
- /* Get kernel environment (protected_mode and addresses). */
- if (OK != (s=sys_getkenviron(&kenv))) {
- server_panic("MEM","Couldn't get kernel environment.",s);
+ /* Get kernel info for memory addresses of kernel and boot device. */
+ if (OK != (s=sys_getkinfo(&kinfo))) {
+ server_panic("MEM","Couldn't get kernel information.",s);
}
- m_geom[KMEM_DEV].dv_base = cvul64(kenv.kmem_base);
- m_geom[KMEM_DEV].dv_size = cvul64(kenv.kmem_size);
- m_geom[BOOT_DEV].dv_base = cvul64(kenv.bootfs_base);
- m_geom[BOOT_DEV].dv_size = cvul64(kenv.bootfs_size);
- /* dv_base isn't used for the random device */
- m_geom[RANDOM_DEV].dv_base = cvul64(NULL);
- m_geom[RANDOM_DEV].dv_size = cvul64(RANDOM_BUFFER_SIZE);
+ /* Install remote segment for /dev/kmem memory. */
+ m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base);
+ m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size);
+ if (OK != (s=sys_segctl(&m_seg[KMEM_DEV], (u16_t *) &s, (vir_bytes *) &s,
+ kinfo.kmem_base, kinfo.kmem_size))) {
+ server_panic("MEM","Couldn't install remote segment.",s);
+ }
+
+ /* Install remote segment for /dev/boot memory, if enabled. */
+ m_geom[BOOT_DEV].dv_base = cvul64(kinfo.bootdev_base);
+ m_geom[BOOT_DEV].dv_size = cvul64(kinfo.bootdev_size);
+ if (kinfo.bootdev_base > 0) {
+ if (OK != (s=sys_segctl(&m_seg[BOOT_DEV], (u16_t *) &s, (vir_bytes *) &s,
+ kinfo.bootdev_base, kinfo.bootdev_size))) {
+ server_panic("MEM","Couldn't install remote segment.",s);
+ }
+ }
- psinfo.proc = kenv.proc_addr;
+ psinfo.proc = kinfo.proc_addr;
+ /* Initialize /dev/random and /dev/zero. */
+ for (i=0; i<ZERO_BUF_SIZE; i++) {
+ zero[i] = '\0';
+ }
+ for (i=0; i<RANDOM_BUF_SIZE; i++) {
+ random[i] = 'a' + i % 256;
+ }
+
+ /* Set up memory ranges for /dev/mem. */
#if (CHIP == INTEL)
- if (!kenv.protected) {
+ if (OK != (s=sys_getmachine(&machine))) {
+ server_panic("MEM","Couldn't get machine information.",s);
+ }
+ if (! machine.protected) {
m_geom[MEM_DEV].dv_size = cvul64(0x100000); /* 1M for 8086 systems */
} else {
#if _WORD_SIZE == 2
switch (m_ptr->REQUEST) {
case MIOCRAMSIZE: {
/* FS wants to create a new RAM disk with the given size. */
- unsigned long bytesize;
- phys_bytes base;
+ unsigned long ramdev_size;
+ phys_bytes ramdev_base;
int s;
if (m_ptr->PROC_NR != FS_PROC_NR) return(EPERM);
- /* Try to allocate a piece of kernel memory for the RAM disk. */
- bytesize = m_ptr->POSITION;
- if (OK != (s = sys_kmalloc(bytesize, &base)))
+ /* Try to allocate a piece of memory for the RAM disk. */
+ ramdev_size = m_ptr->POSITION;
+ if (OK != (s=sys_kmalloc(ramdev_size, &ramdev_base)))
server_panic("MEM","Couldn't allocate kernel memory", s);
- dv->dv_base = cvul64(base);
- dv->dv_size = cvul64(bytesize);
+ dv->dv_base = cvul64(ramdev_base);
+ dv->dv_size = cvul64(ramdev_size);
+ if (OK != (s=sys_segctl(&m_seg[RAM_DEV], (u16_t *) &s, (vir_bytes *) &s,
+ ramdev_base, ramdev_size))) {
+ server_panic("MEM","Couldn't install remote segment.",s);
+ }
+
break;
}
/* Perhaps it is cleaner to move all code relating to psinfo to the info
/* MM or FS set the address of their process table. */
phys_bytes psinfo_phys;
- if (m_ptr->PROC_NR == MM_PROC_NR) {
+ if (m_ptr->PROC_NR == PM_PROC_NR) {
psinfo.mproc = (vir_bytes) m_ptr->ADDRESS;
- } else
- if (m_ptr->PROC_NR == FS_PROC_NR) {
+ } else if (m_ptr->PROC_NR == FS_PROC_NR) {
psinfo.fproc = (vir_bytes) m_ptr->ADDRESS;
} else {
return(EPERM);
* are written to the printer without any changes at all.
*
* Changes:
- * May 07, 2004 wait until printer is ready (Jorrit N. Herder)
+ * May 07, 2004 fix: wait until printer is ready (Jorrit N. Herder)
* May 06, 2004 printer driver moved to user-space (Jorrit N. Herder)
*
* The valid messages and their parameters are:
if (initialized) return;
initialized = TRUE;
+#if DEAD_CODE
/* Get the base port for first printer. This used to be done from the
* BIOS with phys_copy(0x408L, vir2phys(&port_base), 2L); but currently
* a magic number is put in place.
*/
port_base = 0x378;
+#endif
+ sys_vircopy(SELF, BIOS_SEG, LPT1_IO_PORT_ADDR,
+ SELF, D, (vir_bytes) &port_base, LPT1_IO_PORT_SIZE);
sys_outb(port_base + 2, INIT_PRINTER);
tick_delay(1); /* easily satisfies Centronics minimum */
/* was 2 millisecs; now is ~17 millisecs */
#define GA_FONT_SIZE 8192
/* Global variables used by the console driver and assembly support. */
+PUBLIC int vid_index; /* index of video segment in remote mem map */
PUBLIC u16_t vid_seg;
PUBLIC vir_bytes vid_off; /* video ram is found at vid_seg:vid_off */
PUBLIC unsigned vid_size; /* 0x2000 for color or 0x0800 for mono */
if (! vdu_initialized++) {
/* How about error checking? What to do on failure??? */
- s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) 0x44AL,
- SELF, D, (vir_bytes) &bios_columns, 2L);
- s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) 0x463L,
- SELF, D, (vir_bytes) &bios_crtbase, 2L);
- s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) 0x484L,
- SELF, D, (vir_bytes) &bios_rows, 1L);
- s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) 0x485L,
- SELF, D, (vir_bytes) &bios_fontlines, 2L);
+ s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_SCREEN_COLS_ADDR,
+ SELF, D, (vir_bytes) &bios_columns, VDU_SCREEN_COLS_SIZE);
+ s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_CRT_BASE_ADDR,
+ SELF, D, (vir_bytes) &bios_crtbase, VDU_CRT_BASE_SIZE);
+ s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_SCREEN_ROWS_ADDR,
+ SELF, D, (vir_bytes) &bios_rows, VDU_SCREEN_ROWS_SIZE);
+ s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_FONTLINES_ADDR,
+ SELF, D, (vir_bytes) &bios_fontlines, VDU_FONTLINES_SIZE);
vid_port = bios_crtbase;
scr_width = bios_columns;
font_lines = bios_fontlines;
- scr_lines = kenv.ega ? bios_rows+1 : 25;
+ scr_lines = machine.vdu_ega ? bios_rows+1 : 25;
if (color) {
vid_base = COLOR_BASE;
vid_base = MONO_BASE;
vid_size = MONO_SIZE;
}
- if (kenv.ega) vid_size = EGA_SIZE;
- wrap = !kenv.ega;
+ if (machine.vdu_ega) vid_size = EGA_SIZE;
+ wrap = ! machine.vdu_ega;
- s = sys_phys2seg(&vid_seg, &vid_off, vid_base, vid_size);
+ s = sys_segctl(&vid_index, &vid_seg, &vid_off, vid_base, vid_size);
vid_size >>= 1; /* word count */
vid_mask = vid_size - 1;
seq2[6].value= color ? 0x0E : 0x0A;
- if (!kenv.ega) return(ENOTTY);
+ if (!machine.vdu_ega) return(ENOTTY);
result = ga_program(seq1); /* bring font memory into view */
- result = sys_copy(m->PROC_NR, D, (vir_bytes) m->ADDRESS,
- ABS, 0, (phys_bytes) GA_VIDEO_ADDRESS, (phys_bytes)GA_FONT_SIZE);
+ result = sys_physcopy(m->PROC_NR, D, (vir_bytes) m->ADDRESS,
+ NONE, PHYS_SEG, (phys_bytes) GA_VIDEO_ADDRESS, (phys_bytes)GA_FONT_SIZE);
result = ga_program(seq2); /* restore */
{
/* Set the LEDs on the caps, num, and scroll lock keys */
int s;
- if (!kenv.pc_at) return; /* PC/XT doesn't have LEDs */
+ if (! machine.pc_at) return; /* PC/XT doesn't have LEDs */
kb_wait(); /* wait for buffer empty */
if ((s=sys_outb(KEYBD, LED_CODE)) != OK)
PUBLIC int ccurrent; /* currently active console */
PUBLIC timer_t *tty_timers; /* queue of TTY timers */
PUBLIC clock_t tty_next_timeout; /* time that the next alarm is due */
-PUBLIC struct kenviron kenv; /* kernel environment variables */
+PUBLIC struct machine machine; /* kernel environment variables */
/*===========================================================================*
}
/* Get kernel environment (protected_mode, pc_at and ega are needed). */
- if (OK != (s=sys_getkenviron(&kenv))) {
+ if (OK != (s=sys_getmachine(&machine))) {
server_panic("TTY","Couldn't obtain kernel environment.", s);
}
#define bufend(buf) ((buf) + buflen(buf))
/* Memory allocated in tty.c, so extern here. */
-extern struct kenviron kenv; /* kernel environment (a.o.: pc_at, ega) */
-
+extern struct machine machine; /* machine information (a.o.: pc_at, ega) */
/* Function prototypes for TTY driver. */
/* tty.c */
-/* BIOS definitions. Each BIOS entry has an index that is to be used with the
- * sys_bioscopy() system call. The raw addresses, sizes, and magic numbers
- * are defined here as well. The values that are defined here were collected
- * from various kernel files in MINIX 2.0.4.
- *
- * Author: Jorrit N. Herder
+/* Definitions of several known BIOS addresses. The addresses listed here
+ * are found in three memory areas that have been defined in <ibm/memory.h>.
+ * - the BIOS interrupt vectors
+ * - the BIOS data area
+ * - the motherboard BIOS memory
+ *
+ * Created: March 2005, Jorrit N. Herder
*/
#ifndef _BIOS_H
#define _BIOS_H
-/* Memory check (is stopped on reboot). */
-#define BIOS_MEM_CHECK 0 /* address to stop memory check */
-#define ADR_MEM_CHECK 0x472L
-#define LEN_MEM_CHECK 1L
-#define STOP_MEM_CHECK 0x1234 /* magic number to stop memory check */
-
-/* Centronics printers. */
-#define BIOS_PRN_PORTBASE 1 /* base of printer ports */
-#define ADR_PRN_PORTBASE 0x408L
-#define LEN_PRN_PORTBASE 2L
-
-/* Hard disk parameter vectors. */
-#define BIOS_WINI_PARAMS 2 /* number of hard disk drives */
-#define ADR_WINI_PARAMS 0x475L
-#define LEN_WINI_PARAMS 1L
-#define BIOS_WINI_0_PARM_VEC 3 /* disk 0 parameters */
-#define ADR_WINI_0_PARM_VEC 0x41*4L
-#define LEN_WINI_0_PARM_VEC 4L
-#define BIOS_WINI_1_PARM_VEC 4 /* disk 1 parameters */
-#define ADR_WINI_1_PARM_VEC 0x46*4L
-#define LEN_WINI_1_PARM_VEC 4L
+/* PART I --
+ * The BIOS interrupt vector table (IVT) area (1024 B as of address 0x0000).
+ * Although this area holds 256 interrupt vectors (with jump addresses), some
+ * vectors actually contain important BIOS data. Some addresses are below.
+ */
+#define BIOS_EQUIP_CHECK_ADDR 0x0044
+#define BIOS_EQUIP_CHECK_SIZE 4L
+
+#define BIOS_VIDEO_PARAMS_ADDR 0x0074
+#define BIOS_VIDEO_PARAMS_SIZE 4L
+
+#define BIOS_FLOP_PARAMS_ADDR 0x0078
+#define BIOS_FLOP_PARAMS_SIZE 4L
+
+#define BIOS_HD0_PARAMS_ADDR 0x0104 /* disk 0 parameters */
+#define BIOS_HD0_PARAMS_SIZE 4L
+
+#define BIOS_HD1_PARAMS_ADDR 0x0118 /* disk 1 parameters */
+#define BIOS_HD1_PARAMS_SIZE 4L
+
+
+/* PART I --
+ * Addresses in the BIOS data area (256 B as of address 0x0400). The addresses
+ * listed below are the most important ones, and the ones that are currently
+ * used. Other addresses may be defined below when new features are added.
+ */
+
+/* Parallel ports (LPT1-LPT4). */
+#define COM1_IO_PORT_ADDR 0x400 /* COM1 port address */
+#define COM1_IO_PORT_SIZE 2L
+#define COM2_IO_PORT_ADDR 0x402 /* COM2 port address */
+#define COM2_IO_PORT_SIZE 2L
+#define COM3_IO_PORT_ADDR 0x404 /* COM3 port address */
+#define COM3_IO_PORT_SIZE 2L
+#define COM4_IO_PORT_ADDR 0x406 /* COM4 port address */
+#define COM4_IO_PORT_SIZE 2L
+
+/* Serial ports (COM1-COM4). */
+#define LPT1_IO_PORT_ADDR 0x408 /* LPT1 port address */
+#define LPT1_IO_PORT_SIZE 2L
+#define LPT2_IO_PORT_ADDR 0x40A /* LPT2 port address */
+#define LPT2_IO_PORT_SIZE 2L
+#define LPT3_IO_PORT_ADDR 0x40C /* LPT3 port address */
+#define LPT3_IO_PORT_SIZE 2L
+#define LPT4_IO_PORT_ADDR 0x40E /* LPT4 port (except on PS/2) */
+#define LPT4_IO_PORT_SIZE 2L
+
/* Video controller (VDU). */
-#define BIOS_VDU_COLUMNS 5
-#define ADR_VDU_COLUMNS 0x44AL
-#define LEN_VDU_COLUMNS 2L
-#define BIOS_VDU_CRTBASE 6
-#define ADR_VDU_CRTBASE 0x463L
-#define LEN_VDU_CRTBASE 2L
-#define BIOS_VDU_ROWS 7
-#define ADR_VDU_ROWS 0x484L
-#define LEN_VDU_ROWS 1L
-#define BIOS_VDU_FONTLINES 8
-#define ADR_VDU_FONTLINES 0x485L
-#define LEN_VDU_FONTLINES 2L
-
-/* Machine ID. */
-#define BIOS_MACHINE_ID 9
-#define ADR_MACHINE_ID 0xFFFFEL
-#define LEN_MACHINE_ID 1L
-#define PS_386_MACHINE 0xF8 /* Machine ID byte for PS/2 model 80 */
-#define PC_AT_MACHINE 0xFC /* PC/AT, PC/XT286, PS/2 models 50/60 */
+#define VDU_SCREEN_COLS_ADDR 0x44A /* VDU nr of screen columns */
+#define VDU_SCREEN_COLS_SIZE 2L
+
+/* Base I/O port address for active 6845 CRT controller. */
+#define VDU_CRT_BASE_ADDR 0x463 /* 3B4h = mono, 3D4h = color */
+#define VDU_CRT_BASE_SIZE 2L
+
+/* Soft reset flags to control shutdown. */
+#define SOFT_RESET_FLAG_ADDR 0x472 /* soft reset flag on Ctl-Alt-Del */
+#define SOFT_RESET_FLAG_SIZE 2L
+#define STOP_MEM_CHECK 0x1234 /* bypass memory tests & CRT init */
+#define PRESERVE_MEMORY 0x4321 /* preserve memory */
+#define SYSTEM_SUSPEND 0x5678 /* system suspend */
+#define MANUFACTURER_TEST 0x9ABC /* manufacturer test */
+#define CONVERTIBLE_POST 0xABCD /* convertible POST loop */
+ /* ... many other values are used during POST */
+
+/* Hard disk parameters. (Also see BIOS interrupt vector table above.) */
+#define NR_HD_DRIVES_ADDR 0x475 /* number of hard disk drives */
+#define NR_HD_DRIVES_SIZE 1L
+
+/* Parallel ports (LPT1-LPT4) timeout values. */
+#define LPT1_TIMEOUT_ADDR 0x478 /* time-out value for LPT1 */
+#define LPT1_TIMEOUT_SIZE 1L
+#define LPT2_TIMEOUT_ADDR 0x479 /* time-out value for LPT2 */
+#define LPT2_TIMEOUT_SIZE 1L
+#define LPT3_TIMEOUT_ADDR 0x47A /* time-out value for LPT3 */
+#define LPT3_TIMEOUT_SIZE 1L
+#define LPT4_TIMEOUT_ADDR 0x47B /* time-out for LPT4 (except PS/2) */
+#define LPT4_TIMEOUT_SIZE 1L
+
+/* Serial ports (COM1-COM4) timeout values. */
+#define COM1_TIMEOUT_ADDR 0x47C /* time-out value for COM1 */
+#define COM1_TIMEOUT_SIZE 1L
+#define COM2_TIMEOUT_ADDR 0x47D /* time-out value for COM2 */
+#define COM2_TIMEOUT_SIZE 1L
+#define COM3_TIMEOUT_ADDR 0x47E /* time-out value for COM3 */
+#define COM3_TIMEOUT_SIZE 1L
+#define COM4_TIMEOUT_ADDR 0x47F /* time-out value for COM4 */
+#define COM4_TIMEOUT_SIZE 1L
+
+/* Video controller (VDU). */
+#define VDU_SCREEN_ROWS_ADDR 0x484 /* screen rows (less 1, EGA+)*/
+#define VDU_SCREEN_ROWS_SIZE 1L
+#define VDU_FONTLINES_ADDR 0x485 /* point height of char matrix */
+#define VDU_FONTLINES_SIZE 2L
+
+/* Video controller (VDU). */
+#define VDU_VIDEO_MODE_ADDR 0x49A /* current video mode */
+#define VDU_VIDEO_MODE_SIZE 1L
+
+
+/* PART III --
+ * The motherboard BIOS memory contains some known values that are currently
+ * in use. Other sections in the upper memory area (UMA) addresses vary in
+ * size and locus and are not further defined here. A rough map is given in
+ * <ibm/memory.h>.
+ */
+
+/* Machine ID (we're interested in PS/2 and AT models). */
+#define MACHINE_ID_ADDR 0xFFFFE /* BIOS machine ID byte */
+#define MACHINE_ID_SIZE 1L
+#define PS_386_MACHINE 0xF8 /* ID byte for PS/2 modela 70/80 */
+#define PC_AT_MACHINE 0xFC /* PC/AT, PC/XT286, PS/2 models 50/60 */
+
#endif /* _BIOS_H */
+
--- /dev/null
+/* Physical memory layout on IMB compatible PCs. Only the major, fixed memory
+ * areas are detailed here. Known addresses of the BIOS data area are defined
+ * in <ibm/bios.h>. The map upper memory area (UMA) is only roughly defined
+ * since the UMA sections may vary in size and locus.
+ *
+ * Created: March 2005, Jorrit N. Herder
+ */
+
+
+/* I/O-mapped peripherals. I/O addresses are different from memory addresses
+ * due to the I/O signal on the ISA bus. Individual I/O ports are defined by
+ * the drivers that use them or looked up with help of the BIOS.
+ */
+#define IO_MEMORY_BEGIN 0x0000
+#define IO_MEMORY_END 0xFFFF
+
+
+/* Physical memory layout. Design decisions made for the earliest PCs, caused
+ * memory to be broken broken into the following four basic pieces:
+ * - Conventional or base memory: first 640 KB (incl. BIOS data, see below);
+ * - Upper Memory Area (UMA): upper 384 KB of the first megabyte of memory;
+ * - High Memory Area (HMA): ~ first 64 KB of the second megabyte of memory;
+ * - Extended Memory: all the memory above first megabyte of memory.
+ * The high memory area overlaps with the first 64 KB of extended memory, but
+ * is different from the rest of extended memory because it can be accessed
+ * when the processor is in real mode.
+ */
+#define BASE_MEM_BEGIN 0x000000
+#define BASE_MEM_END 0x09FFFF
+
+#define UPPER_MEM_BEGIN 0x0A0000
+#define UPPER_MEM_END 0x0FFFFF
+
+#define HIGH_MEM_BEGIN 0x100000
+#define HIGH_MEM_END 0x10FFEF
+
+#define EXTENDED_MEM_BEGIN 0x100000
+#define EXTENDED_MEM_END ((unsigned) -1)
+
+
+/* The logical memory map of the first 1.5 MB is as follows (hexadecimals):
+ *
+ * offset [size] (id) = memory usage
+ * ------------------------------------------------------------------------
+ * 000000 [00400] (I) = Real-Mode Interrupt Vector Table (1024 B)
+ * 000400 [00100] (B) = BIOS Data Area (256 B)
+ * 000800 [00066] (W) = 80286 Loadall workspace
+ * 010000 [10000] (c) = Real-Mode Compatibility Segment (64 KB)
+ * 020000 [70000] (.) = Program-accessible memory (free)
+ * 090000 [10000] (E) = BIOS Extension
+ * 0A0000 [10000] (G) = Graphics Mode Video RAM
+ * 0B0000 [08000] (M) = Monochrome Text Mode Video RAM
+ * 0B8000 [08000] (C) = Color Text Mode Video RAM
+ * 0C0000 [08000] (V) = Video ROM BIOS (would be "a" in PS/2)
+ * 0C8000 [18000] (a) = Adapter ROM + special-purpose RAM (free UMA space)
+ * 0E0000 [10000] (r) = PS/2 Motherboard ROM BIOS (free UMA in non-PS/2)
+ * 0F0000 [06000] (R) = Motherboard ROM BIOS
+ * 0F6000 [08000] (b) = IBM Cassette BASIC ROM ("R" in IBM compatibles)
+ * 0FD000 [02000] (R) = Motherboard ROM BIOS
+ * 100000 [.....] (.) = Extended memory, program-accessible (free)
+ * 100000 [0FFEF] (h) = High Memory Area (HMA)
+ *
+ *
+ * Conventional (Base) Memory:
+ *
+ * : [~~~~~16 KB~~~~][~~~~~16 KB~~~~][~~~~~16 KB~~~~][~~~~~16 KB~~~~]
+ * : 0---1---2---3---4---5---6---7---8---9---A---B---C---D---E---F---
+ * 000000: IBW.............................................................
+ * 010000: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+ * 020000: ................................................................
+ * 030000: ................................................................
+ * 040000: ................................................................
+ * 050000: ................................................................
+ * 060000: ................................................................
+ * 070000: ................................................................
+ * 080000: ................................................................
+ * 090000: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
+ *
+ * Upper Memory Area (UMA):
+ *
+ * : 0---1---2---3---4---5---6---7---8---9---A---B---C---D---E---F---
+ * 0A0000: GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
+ * 0B0000: MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+ * 0C0000: VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ * 0D0000: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+ * 0E0000: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
+ * 0F0000: RRRRRRRRRRRRRRRRRRRRRRRRbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbRRRRRRRR
+ *
+ * Extended Memory:
+ *
+ * : 0---1---2---3---4---5---6---7---8---9---A---B---C---D---E---F---
+ * 100000: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh.
+ * 110000: ................................................................
+ * 120000: ................................................................
+ * 130000: ................................................................
+ * 140000: ................................................................
+ * 150000: ................................................................
+ * 160000: ................................................................
+ * 170000: ................................................................
+ *
+ * Source: The logical memory map was partly taken from the book "Upgrading
+ * & Repairing PCs Eight Edition", Macmillan Computer Publishing.
+ */
+
+
+/* The bottom part of conventional or base memory is occupied by BIOS data.
+ * The BIOS memory can be distinguished in two parts:
+ * o The first the first 1024 bytes of addressable memory contains the BIOS
+ * real-mode interrupt vector table (IVT). The table is used to access BIOS
+ * hardware services in real-mode by loading a interrupt vector and issuing
+ * an INT instruction. Some vectors contain BIOS data that can be retrieved
+ * directly and are useful in protected-mode as well.
+ * o The BIOS data area is located directly above the interrupt vectors. It
+ * comprises 256 bytes of memory. These data are used by the device drivers
+ * to retrieve hardware details, such as I/O ports to be used.
+ */
+#define BIOS_MEM_BEGIN 0x00000 /* all BIOS memory */
+#define BIOS_MEM_END 0x004FF
+#define BIOS_IVT_BEGIN 0x00000 /* BIOS interrupt vectors */
+#define BIOS_IVT_END 0x003FF
+#define BIOS_DATA_BEGIN 0x00400 /* BIOS data area */
+#define BIOS_DATA_END 0x004FF
+
+
+/* The base memory is followed by 384 KB reserved memory located at the top of
+ * the first MB of physical memory. This memory is known as the upper memory
+ * area (UMA). It is used for memory-mapped peripherals, such as video RAM,
+ * adapter BIOS (adapter ROM and special purpose RAM), and the motherboard
+ * BIOS (I/O system, Power-On Self Test, bootstrap loader). The upper memory
+ * can roughly be distinguished in three parts:
+ *
+ * o The first 128K of the upper memory area (A0000-BFFFF) is reserved for use
+ * by memory-mapped video adapters. Hence, it is also called Video RAM. The
+ * display driver can directly write to this memory and request the hardware
+ * to show the data on the screen.
+ */
+#define UMA_VIDEO_RAM_BEGIN 0xA0000 /* video RAM */
+#define UMA_VIDEO_RAM_END 0xBFFFF
+#define UMA_GRAPHICS_RAM_BEGIN 0xA0000 /* graphics RAM */
+#define UMA_GRAPHICS_RAM_END 0xAFFFF
+#define UMA_MONO_TEXT_BEGIN 0xB0000 /* monochrome text */
+#define UMA_MONO_TEXT_END 0xB7FFF
+#define UMA_COLOR_TEXT_BEGIN 0xB8000 /* color text */
+#define UMA_COLOR_TEXT_END 0xBFFFF
+
+
+/* o The next 128K (the memory range C0000-DFFFF) is reserved for the adapter
+ * BIOS that resides in the ROM on some adapter boards. Most VGA-compatible
+ * video adapters use the first 32 KB of this area for their on-board BIOS.
+ * The rest can be used by any other adapters. The IDE controller often
+ * occupies the second 32 KB.
+ */
+#define UMA_ADAPTER_BIOS_BEGIN 0xC0000 /* adapter BIOS */
+#define UMA_ADAPTER_BIOS_END 0xDFFFF
+#define UMA_VIDEO_BIOS_BEGIN 0xC0000 /* video adapter */
+#define UMA_VIDEO_BIOS_END 0xC7FFF
+#define UMA_IDE_HD_BIOS_BEGIN 0xC8000 /* IDE hard disk */
+#define UMA_IDE_HD_BIOS_END 0xCBFFF
+
+
+/* o The last 128K of the upper memory area (E0000-FFFFF) is reserved for
+ * motherboard BIOS (Basic I/O System). The POST (Power-On Self Test) and
+ * bootstrap loader also reside in this space. The memory falls apart in
+ * two areas: Plug & Play BIOS data and the system BIOS data.
+ */
+#define UMA_MB_BIOS_BEGIN 0xE0000 /* motherboard BIOS */
+#define UMA_MB_BIOS_END 0xFFFFF
+#define UMA_PNP_ESCD_BIOS_BEGIN 0xE0000 /* PnP extended data */
+#define UMA_PNP_ESCD_BIOS_END 0xEFFFF
+#define UMA_SYSTEM_BIOS_BEGIN 0xF0000 /* system BIOS */
+#define UMA_SYSTEM_BIOS_END 0xFFFFF
+
+
+
#define CTRLR(n) (NONE + (n))
/* User-level processes, that is, device drivers, servers, and INIT. */
-#define MM_PROC_NR 0 /* memory manager */
+#define PM_PROC_NR 0 /* process manager */
#define FS_PROC_NR 1 /* file system */
#define IS_PROC_NR 5 /* information server */
#define TTY 6 /* terminal (TTY) driver */
# define NULL_DEV 3 /* minor device for /dev/null */
# define BOOT_DEV 4 /* minor device for /dev/boot */
# define RANDOM_DEV 5 /* minor device for /dev/random */
-# define URANDOM_DEV 6 /* minor device for /dev/urandom */
+# define ZERO_DEV 6 /* minor device for /dev/zero */
+/* Full device numbers that are special to the boot monitor and FS. */
# define DEV_RAM 0x0100 /* device number of /dev/ram */
# define DEV_BOOT 0x0104 /* device number of /dev/boot */
-# define DEV_RANDOM 0x0105 /* device number of /dev/random */
-# define DEV_URANDOM 0x0106 /* device number of /dev/urandom */
/*===========================================================================*
* modifying the system call numbers. The numbers here determine which call
* is made from the call vector.
*/
-#define NR_SYS_CALLS 32 /* number of system calls */
+#define NR_SYS_CALLS 33 /* number of system calls */
# define SYS_TIMES 0 /* sys_times(proc_nr, bufptr) */
# define SYS_XIT 1 /* sys_xit(parent, proc) */
+# define SYS_GETSIG 2 /* sys_getsig(proc_nr, sig_map) */
-# define SYS_SIGCTL 3 /* sys_sigctl(req,pnr,sig,ctxt,flag,pnr,map) */
# define SYS_FORK 4 /* sys_fork(parent, child, pid) */
# define SYS_NEWMAP 5 /* sys_newmap(proc_nr, map_ptr) */
-# define SYS_COPY 6 /* sys_copy(ptr) */
+# define SYS_ENDSIG 6 /* sys_endsig(proc_nr) */
# define SYS_EXEC 7 /* sys_exec(proc_nr, new_sp) */
-
+# define SYS_SIGSEND 8 /* sys_sigsend(proc_nr, ctxt_ptr) */
# define SYS_ABORT 9 /* sys_abort() */
# define SYS_KILL 10 /* sys_kill(proc_nr, sig) */
# define SYS_UMAP 11 /* sys_umap(proc_nr, etc) */
-
+# define SYS_RANDOM 12 /* sys_random(...) */
# define SYS_TRACE 13 /* sys_trace(req,pid,addr,data) */
-# define SYS_VCOPY 14 /* sys_vcopy(src_p, dst_p, vcpy_s, vcpy_ptr) */
+
# define SYS_SIGNALRM 15 /* sys_signalrm(proc_nr, ticks) */
# define SYS_SYNCALRM 16 /* sys_syncalrm(proc_nr,exp_time,abs_time) */
# define SYS_FLAGALRM 17 /* sys_flagalrm(ticks, flag_ptr) */
# define SYS_SVRCTL 19 /* sys_svrctl(proc_nr, req, argp) */
# define SYS_SDEVIO 20 /* sys_sdevio(port, proc_nr, buf, count) */
-
+# define SYS_SIGRETURN 21 /* sys_sigreturn(proc_nr, ctxt_ptr, flags) */
# define SYS_GETINFO 22 /* sys_getinfo(what, whereto) */
# define SYS_DEVIO 23 /* sys_devio(port, value) */
# define SYS_VDEVIO 24 /* sys_vdevio(buf_ptr, nr_ports) */
# define SYS_IRQCTL 25 /* sys_irqctl() */
# define SYS_KMALLOC 26 /* sys_kmalloc(size, phys_base) */
# define SYS_IOPENABLE 27 /* sys_enable_iop() */
-# define SYS_PHYS2SEG 28 /* sys_phys2seg(*seg, *off, phys) */
+# define SYS_SEGCTL 28 /* sys_segctl(*idx, *seg, *off, phys, size) */
# define SYS_EXIT 29 /* sys_exit(status) */
# define SYS_VIRCOPY 30 /* sys_vircopy(src,seg,addr,dst,seg,addr,cnt) */
# define SYS_PHYSCOPY 31 /* sys_physcopy(src_addr,dst_addr,count) */
-# define SYS_MSTATS 32
+# define SYS_VIRVCOPY 32 /* sys_virvcopy(vec_ptr, vec_size) */
/* Field names for SYS_MEM, SYS_KMALLOC. */
#define MEM_CHUNK_BASE m4_l1 /* physical base address */
/* Names of message field and paramaters for SYS_EXIT request. */
#define EXIT_STATUS m2_i1 /* zero for normal exit, non-zero else */
-/* Field names for SYS_PHYS2SEG. */
+/* Field names for SYS_SEGCTL. */
#define SEG_SELECT m4_l1 /* segment selector returned */
#define SEG_OFFSET m4_l2 /* offset in segment returned */
#define SEG_PHYS m4_l3 /* physical address of segment */
#define SEG_SIZE m4_l4 /* segment size */
+#define SEG_INDEX m4_l5 /* segment index in remote map */
/* Field names for SYS_VIDCOPY. */
#define VID_REQUEST m4_l1 /* what to do? */
#define ABRT_MON_LEN m1_i3 /* length of monitor params */
#define ABRT_MON_ADDR m1_p1 /* virtual address of monitor params */
-/* Field names for SYS_COPY, _UMAP, _VIRCOPY, _PHYSCOPY. */
+/* Field names for _UMAP, _VIRCOPY, _PHYSCOPY. */
#define CP_SRC_SPACE m5_c1 /* T or D space (stack is also D) */
#define CP_SRC_PROC_NR m5_i1 /* process to copy from */
#define CP_SRC_ADDR m5_l1 /* address where data come from */
/* Field names for SYS_GETINFO. */
#define I_REQUEST m7_i3 /* what info to get */
-# define GET_KENVIRON 0 /* get kernel environment variables */
+# define GET_KINFO 0 /* get kernel information structure */
# define GET_IMAGE 1 /* get system image table */
# define GET_PROCTAB 2 /* get (kernel) process table */
# define GET_PROCNR 3 /* find nr of process with name */
# define GET_KADDRESSES 9 /* get various kernel addresses */
# define GET_SCHEDINFO 10 /* get scheduling queues */
# define GET_PROC 11 /* get process slot if given process */
+# define GET_MACHINE 12 /* get machine information */
#define I_PROC_NR m7_i4 /* calling process */
#define I_VAL_PTR m7_p1 /* virtual address at caller */
#define I_VAL_LEN m7_i1 /* max length of value */
#endif
#if (MACHINE == IBM_PC && _WORD_SIZE == 4)
-#define NR_BUFS 128 /* # blocks in the buffer cache */
+#define NR_BUFS 1024 /* # blocks in the buffer cache */
#define NR_BUF_HASH 1024 /* size of buf hash table; MUST BE POWER OF 2*/
#endif
#define LINEWRAP 1 /* console.c - wrap lines at column 80 */
#define ALLOW_GAP_MESSAGES 1 /* proc.c - allow messages in the gap between
* the end of bss and lowest stack address */
-#define KMESS_BUF_SIZE 512 /* size in B for kernel messages */
+#define KMESS_BUF_SIZE 512 /* size in bytes for kernel messages */
/* Number of controller tasks (/dev/cN device classes). */
#define NR_CTRLRS 2
/* Enable or disable kernel calls (allows for minimal kernel). */
#define ENABLE_K_TRACING 1 /* process tracing can be disabled */
-#define ENABLE_K_DEBUGGING 1 /* kernel debugging calls */
+#define ENABLE_K_DEBUGGING 0 /* kernel debugging calls */
+
+/* Include or exclude an image of /dev/boot in the boot image. */
+#define ENABLE_BOOTDEV 1
/* Include or exclude device drivers. Set to 1 to include, 0 to exclude. */
#define ENABLE_BIOS_WINI 0 /* enable BIOS winchester driver */
* ENABLE_USERPRIV must be set to 1 to allow the features anyway.
*/
#define ENABLE_USERBIOS 0 /* enable user mode BIOS calls */
-#define ENABLE_LOOSELDT 0 /* allow imprecise, page based LDT entries */
-#define ENABLE_USERIOPL 1 /* enable CPU's IOPL bits for /dev/(k)mem */
+#define ENABLE_USERIOPL 0 /* enable CPU's IOPL bits for /dev/(k)mem */
/* NR_CONS, NR_RS_LINES, and NR_PTYS determine the number of terminals the
* system can handle.
#define BIOS_SEG 0x0200 /* flags indicating BIOS memory segment */
#define NR_BIOS_SEGS 3 /* # BIOS memory regions (variable) */
+#define PHYS_SEG 0x0300 /* flag indicating entire physical memory */
+
/* Labels used to disable code sections for different reasons. */
#define DEAD_CODE 0 /* unused code in normal configuration */
#define FUTURE_CODE 0 /* new code to be activated + tested later */
* Sep 02, 2004 added sys_exit (Jorrit N. Herder)
* Aug 15, 2004 added sys_getinfo (Jorrit N. Herder)
* Jul 23, 2004 added sys_umap (Jorrit N. Herder)
- * Jul 13, 2004 added sys_enable_iop, sys_phys2seg (Jorrit N. Herder)
+ * Jul 13, 2004 added sys_enable_iop, sys_segctl (Jorrit N. Herder)
* Mar 20, 2004 added sys_devio, sys_vdevio (Jorrit N. Herder)
*/
_PROTOTYPE( int sys_abort, (int how, ...) );
_PROTOTYPE( int sys_adjmap, (int proc, struct mem_map *ptr,
vir_clicks data_clicks, vir_clicks sp) );
-_PROTOTYPE( int sys_copy, (int src_proc, int src_seg, phys_bytes src_vir,
- int dst_proc, int dst_seg, phys_bytes dst_vir, phys_bytes bytes));
_PROTOTYPE( int sys_exec, (int proc, char *ptr, int traced,
char *aout, vir_bytes initpc) );
_PROTOTYPE( int sys_execmap, (int proc, struct mem_map *ptr) );
_PROTOTYPE( int sys_getuptime, (clock_t *ticks) );
_PROTOTYPE( int sys_trace, (int req, int proc, long addr, long *data_p) );
_PROTOTYPE( int sys_xit, (int parent, int proc) );
-_PROTOTYPE( int sys_kill, (int proc, int sig) );
_PROTOTYPE( int sys_svrctl, (int proc, int req, int priv,vir_bytes argp));
-/*==========================================================================*
- * New prototypes since MINIX release 2 (Jorrit N. Herder) *
- *==========================================================================*/
-
/* Shorthands for sys_sdevio() system call. */
#define sys_insb(port, proc_nr, buffer, count) \
sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc_nr, buffer, count)
_PROTOTYPE ( int sys_irqctl, (int request, int irq_vec, int policy,
int proc_nr, long port, void *val_ptr, long mask_val) );
-/* Shorthands for sys_vircopy() system call. */
+/* Shorthands for sys_vircopy() and sys_physcopy() system calls. */
#define sys_biosin(bios_vir, dst_vir, bytes) \
sys_vircopy(SELF, BIOS_SEG, bios_vir, SELF, D, dst_vir, bytes)
#define sys_biosout(src_vir, bios_vir, bytes) \
_PROTOTYPE(int sys_vircopy, (int src_proc, int src_seg, vir_bytes src_vir,
int dst_proc, int dst_seg, vir_bytes dst_vir, phys_bytes bytes) );
-_PROTOTYPE(int sys_physcopy, (phys_bytes src_phys, phys_bytes dst_phys,
- phys_bytes bytes) );
+#define sys_abscopy(src_phys, dst_phys, bytes) \
+ sys_physcopy(NONE, PHYS_SEG, src_phys, NONE, PHYS_SEG, dst_phys, bytes)
+_PROTOTYPE(int sys_physcopy, (int src_proc, int src_seg, vir_bytes src_vir,
+ int dst_proc, int dst_seg, vir_bytes dst_vir, phys_bytes bytes) );
+
_PROTOTYPE(int sys_umap, (int proc_nr, int seg, vir_bytes vir_addr,
vir_bytes bytes, phys_bytes *phys_addr) );
-_PROTOTYPE(int sys_phys2seg, (u16_t *seg,vir_bytes *off,phys_bytes phys, vir_bytes size));
+_PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off,
+ phys_bytes phys, vir_bytes size));
_PROTOTYPE(int sys_enable_iop, (int proc_nr) );
_PROTOTYPE(int sys_kmalloc, (size_t size, phys_bytes *phys_base) );
/* Shorthands for sys_getinfo() system call. */
#define sys_getkmessages(dst) sys_getinfo(GET_KMESSAGES, dst, 0,0,0)
-#define sys_getkenviron(dst) sys_getinfo(GET_KENVIRON, dst, 0,0,0)
+#define sys_getkinfo(dst) sys_getinfo(GET_KINFO, dst, 0,0,0)
+#define sys_getmachine(dst) sys_getinfo(GET_MACHINE, dst, 0,0,0)
#define sys_getproctab(dst) sys_getinfo(GET_PROCTAB, dst, 0,0,0)
#define sys_getproc(dst,nr) sys_getinfo(GET_PROC, dst, 0,0, nr)
#define sys_getprocnr(dst,k,kl) sys_getinfo(GET_PROCNR, dst, 0,k,kl)
_PROTOTYPE(int sys_exit, (int status) );
-/* Shorthands for sys_sigctl() system call. */
-#define sys_getsig(proc_nr, sig_map) \
- sys_sigctl(S_GETSIG, 0,0,0, proc_nr, sig_map)
-#define sys_endsig(proc_nr) \
- sys_sigctl(S_ENDSIG, proc_nr, 0,0,0,0)
-#define sys_sendsig(proc_nr, sig_ctxt) \
- sys_sigctl(S_SENDSIG, proc_nr, sig_ctxt, 0,0,0)
-#define sys_sigreturn(proc_nr, sig_ctxt, flags) \
- sys_sigctl(S_SIGRETURN, proc_nr, sig_ctxt, flags, 0,0)
-_PROTOTYPE(int sys_sigctl, (int request, int proc_nr, struct sigmsg *sig_ctxt,
- int flags, int *k_proc_nr, sigset_t *k_sig_map) );
+/* Signal control. */
+_PROTOTYPE(int sys_kill, (int proc, int sig) );
+_PROTOTYPE(int sys_sigsend, (int proc_nr, struct sigmsg *sig_ctxt) );
+_PROTOTYPE(int sys_sigreturn, (int proc_nr, struct sigmsg *sig_ctxt, int flags) );
+_PROTOTYPE(int sys_getsig, (int *k_proc_nr, sigset_t *k_sig_map) );
+_PROTOTYPE(int sys_endsig, (int proc_nr) );
/* NOTE: two different approaches were used to distinguish the device I/O
* types 'byte', 'word', 'long': the latter uses #define and results in a
typedef unsigned long vir_bytes;/* virtual addresses and lengths in bytes */
#endif
+/* Memory map for local text, stack, data segments. */
struct mem_map {
vir_clicks mem_vir; /* virtual address */
phys_clicks mem_phys; /* physical address */
vir_clicks mem_len; /* length */
};
+/* Memory map for remote memory areas, e.g., for the RAM disk. */
struct far_mem {
+ int in_use; /* entry in use, unless zero */
phys_clicks mem_phys; /* physical address */
vir_clicks mem_len; /* length */
};
+/* Structure for virtual copying by means of a vector with requests. */
+struct vir_addr {
+ int proc_nr;
+ int segment;
+ vir_bytes offset;
+};
+
+struct vir_cp_req {
+ struct vir_addr src;
+ struct vir_addr dst;
+ phys_bytes count;
+};
+
typedef struct {
vir_bytes iov_addr; /* address of an I/O buffer */
vir_bytes iov_size; /* sizeof an I/O buffer */
};
/* This is used to obtain system information through SYS_GETINFO. */
-struct kenviron {
- int pc_at;
- int ps_mca;
- int processor;
- int protected;
- int ega;
- int vga;
+struct kinfo {
+ phys_bytes code_base; /* base of kernel code */
+ phys_bytes code_size;
+ phys_bytes data_base; /* base of kernel data */
+ phys_bytes data_size;
vir_bytes proc_addr; /* virtual address of process table */
phys_bytes kmem_base; /* kernel memory layout (/dev/kmem) */
phys_bytes kmem_size;
- phys_bytes bootfs_base; /* FS image from boot image (/dev/boot) */
- phys_bytes bootfs_size;
+ phys_bytes bootdev_base; /* boot device from boot image (/dev/boot) */
+ phys_bytes bootdev_size;
phys_bytes params_base; /* parameters passed by boot monitor */
phys_bytes params_size;
+ char version[8]; /* kernel version number */
+};
+
+struct machine {
+ int pc_at;
+ int ps_mca;
+ int processor;
+ int protected;
+ int vdu_ega;
+ int vdu_vga;
};
/* The kernel outputs messages in a local buffer, which can be requested and
HEAD = mpx.o
OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \
- i8259.o exception.o system.o clock.o memory.o misc.o \
+ i8259.o exception.o system.o clock.o misc.o \
dummy.o \
rtl8139.o pci.o pci_table.o
main.o: proc.h
main.o: sendmask.h
-memory.o: $a
-memory.o: proc.h
-memory.o: protect.h
-
misc.o: $a
misc.o: $i/stdlib.h
misc.o: $h/com.h
system/system.a: system/misc.c
system/system.a: system/proctl.c
system/system.a: system/sigctl.c
-system/system.a: system/srvrctl.c
+system/system.a: system/sysctl.c
system/system.a: system/tracing.c
system/system.a: system/debugging.c
-system/system.a: system/do_copy.c
-system/system.a: system/do_vcopy.c
clock_t now;
/* Acknowledge the PS/2 clock interrupt. */
- if (ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
+ if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT);
/* Update user and system accounting times. Charge the current process for
* user time. If the current process is not billable, that is, if a non-user
/* 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) (data_base + (vir_bytes) (vir))
+#define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir))
/* Constants used in virtual_copy(). Values must be 0 and 1, respectively! */
#define _SRC_ 0
/* How many bytes for (port,value)-pairs vector to copy in. */
#define VDEVIO_BUF_SIZE 128
+/* How many elements in vector of virtual copy requests. */
+#define VCOPY_VEC_SIZE 16
+
/* Program stack words and masks. */
#define INIT_PSW 0x0200 /* initial psw */
#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
}
/* Exception in system code. This is not supposed to happen. */
- if (ep->msg == NIL_PTR || processor < ep->minprocessor)
+ if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor)
kprintf("\nIntel-reserved exception %d\n", vec_nr);
else
kprintf("\n%s\n", karg(ep->msg));
EXTERN struct proc *shutdown_process; /* process awaiting shutdown of */
EXTERN timer_t shutdown_timer; /* watchdog function called after timeout */
-/* Kernel memory. */
-EXTERN phys_bytes code_base; /* base of kernel code */
-EXTERN phys_bytes data_base; /* base of kernel data */
+/* Kernel information structures. This groups vital kernel information. */
EXTERN phys_bytes aout; /* address of a.out headers */
+EXTERN struct kinfo kinfo; /* kernel information for users */
+EXTERN struct machine machine; /* machine information for users */
+EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
+EXTERN struct memory mem[NR_MEMS]; /* base and size of chunks of memory */
/* Low level notifications may be put on the 'held' queue to prevent races. */
EXTERN struct proc *held_head; /* head of queue of held-up interrupts */
/* Process table. Here to stop too many things having to include proc.h. */
EXTERN struct proc *proc_ptr; /* pointer to currently running process */
-/* Memory sizes. */
-EXTERN struct memory mem[NR_MEMS]; /* base and size of chunks of memory */
-EXTERN phys_clicks tot_mem_size; /* total system memory size */
-
/* Miscellaneous. */
EXTERN unsigned lost_ticks; /* clock ticks counted outside the clock task */
#if (CHIP == INTEL)
-/* Machine type. */
-EXTERN int pc_at; /* PC-AT compatible hardware interface */
-EXTERN int ps_mca; /* PS/2 with Micro Channel */
-EXTERN unsigned int processor; /* 86, 186, 286, 386, ... */
-#if _WORD_SIZE == 2
-EXTERN int protected_mode; /* nonzero if running in Intel protected mode*/
-#else
-#define protected_mode 1 /* 386 mode implies protected mode */
-#endif
-
-/* Video card types. */
-EXTERN int ega; /* nonzero if console is EGA */
-EXTERN int vga; /* nonzero if console is VGA */
-
/* Interrupt related variables. */
EXTERN struct irqtab irqtab[NR_IRQ_VECTORS]; /* table with IRQ policies */
EXTERN irq_hook_t *irq_hooks[NR_IRQ_VECTORS]; /* list of IRQ handlers */
EXTERN int irq_use; /* bit map of all in-use irq's */
/* Miscellaneous. */
-EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
EXTERN reg_t mon_ss, mon_sp; /* monitor stack */
EXTERN int mon_return; /* true if return to the monitor possible */
-EXTERN phys_bytes mon_params; /* boot parameter block passed in/out */
-EXTERN size_t mon_parmsize; /* boot parameter block size */
/* Variables that are initialized elsewhere are just extern here. */
extern struct system_image image[]; /* system image processes (table.c) */
int i;
lock();
- if (protected_mode) {
+ if (machine.protected) {
/* 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, ps_mca ? ICW1_PS : ICW1_AT);
+ 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);
outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
- outb(INT2_CTL, ps_mca ? ICW1_PS : ICW1_AT);
+ 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 */
.define _reset ! reset the system
.define _idle_task ! task executed when there is no work
.define _level0 ! call a function at level 0
+.define _read_tsc ! read the cycle counter (Pentium and up)
! The routines only guarantee to preserve the registers the C compiler
! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
mov (_level0_func), eax
int LEVEL0_VECTOR
ret
+
+
+!*===========================================================================*
+!* read_tsc *
+!*===========================================================================*
+! PUBLIC void read_tsc(unsigned long *low, unsigned long *high);
+! Read the cycle counter of the CPU. Pentium and up.
+.align 16
+_read_tsc:
+.data1 0x0f ! this is the RDTSC instruction
+.data1 0x31 ! it places the TSC in EDX:EAX
+ push ebp
+ mov ebp, 8(esp)
+ mov (ebp), edx
+ mov ebp, 12(esp)
+ mov (ebp), eax
+ pop ebp
+ ret
+
-#
-#include <minix/config.h>
-#include <minix/const.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 _monitor ! exit Minix and return to the monitor
-.define _int86 ! make an 8086 interrupt call
-.define real2prot ! switch from real to protected mode
-.define prot2real ! switch from protected to real mode
-.define _cp_mess ! copies messages from source to destination
-.define _exit ! dummy for library routines
-.define __exit ! dummy for library routines
-.define ___exit ! dummy for library routines
-.define .fat, .trp ! dummies for library routines
-.define _phys_insw ! transfer data from (disk controller) port to memory
-.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 _phys_copy ! copy data from anywhere to anywhere in memory
-.define _mem_rdw ! copy one word from [segment:offset]
-.define _reset ! reset the system
-.define _mem_vid_copy ! copy data to video ram
-.define _vid_vid_copy ! move data in video ram
-.define _idle_task ! executed when there is no work
-.define _level0 ! call a function at level 0
-.define klib_init_prot ! initialize klib functions for protected mode
-
-! The routines only guarantee to preserve the registers the C compiler
-! expects to be preserved (si, di, bp, sp, segment registers, and direction
-! bit in the flags), though some of the older ones preserve bx, cx and dx.
-
-#define DS_286_OFFSET DS_286_INDEX*DESC_SIZE
-#define ES_286_OFFSET ES_286_INDEX*DESC_SIZE
-# define EM_XFER_FUNC 0x87
-#define JMP_OPCODE 0xE9 /* opcode used for patching */
-#define OFF_MASK 0x000F /* offset mask for phys_b -> hclick:offset */
-#define HCHIGH_MASK 0x0F /* h/w click mask for low byte of hi word */
-#define HCLOW_MASK 0xF0 /* h/w click mask for low byte of low word */
-
-! Exported variables
-.extern kernel_cs
-
- .text
-!*===========================================================================*
-!* monitor *
-!*===========================================================================*
-! PUBLIC void monitor();
-! Return to the monitor.
-
-_monitor:
- call prot2real ! switch to real mode
- mov sp, _mon_sp ! restore monitor stack pointer
- mov bx, _mon_ss ! monitor data segment
- mov ds, bx
- mov es, bx
- mov ss, bx
- pop di
- pop si
- pop bp
- retf ! return to the monitor
-
-
-!*===========================================================================*
-!* int86 *
-!*===========================================================================*
-! PUBLIC void int86();
-_int86: ! make an 8086 interrupt call.
- push bp
- push si
- push di ! save C variable registers
- pushf ! save flags
-
- call int86 ! make the actual call
-
- popf ! restore flags
- pop di ! restore C registers
- pop si
- pop bp
- ret
-
-! Do an 8086 interrupt from protected mode
-p_int86:
- push bp
- push si
- push di ! save C variable registers
- pushf ! save flags
-
- cli ! no interruptions
- inb INT2_CTLMASK
- movb ah, al
- inb INT_CTLMASK
- push ax ! save interrupt masks
- mov ax, _irq_use ! map of in-use IRQs
- and ax, #~[1<<CLOCK_IRQ] ! keep the clock ticking
- outb INT_CTLMASK ! enable all unused IRQs and vv.
- movb al, ah
- outb INT2_CTLMASK
-
- call prot2real ! switch to real mode
-
- xor ax, ax
- mov es, ax ! vector & BIOS data segments
- eseg mov 0x046C, ax ! clear BIOS clock counter
- eseg mov 0x046E, ax
-
- sti ! enable interrupts
- call int86 ! make the actual call
- cli ! disable interrupts
-
- xor ax, ax
- mov es, ax
- eseg mov ax, 0x046C
- add _lost_ticks, ax ! record lost clock ticks
-
- call real2prot ! back to protected mode
-
- pop ax ! restore interrupt masks
- outb INT_CTLMASK
- movb al, ah
- outb INT2_CTLMASK
-
- popf ! restore flags
- pop di ! restore C registers
- pop si
- pop bp
- ret
-
-int86:
- mov bp, #_reg86 ! address of parameter block
- movb al, #0xCD ! INT instruction
- movb ah, (bp) ! Interrupt number?
- testb ah, ah
- jnz 0f ! nonzero if INT, otherwise far call
- push cs
- push #intret+2 ! far return address
- push 6(bp)
- push 4(bp) ! far driver address
- mov ax, #0x90CB ! RETF; NOP
-0: cseg mov intret, ax ! patch `INT n` or `RETF; NOP` into code
- jmp .+2 ! clear instruction queue
-
- mov ds, 8(bp) ! Load parameters
- mov es, 10(bp)
- mov ax, 12(bp) ! (sorry, only ax set, not eax)
- mov bx, 16(bp)
- mov cx, 20(bp)
- mov dx, 24(bp)
- mov si, 28(bp)
- mov di, 32(bp)
- mov bp, 36(bp)
-
-intret: int 0xFF ! do the interrupt or far call
-
- push bp
- pushf
- mov bp, #_reg86 ! address of parameter block
- pop (bp) ! eflags
- mov 8(bp), ds
- mov 10(bp), es
- mov 12(bp), ax
- mov 16(bp), bx
- mov 20(bp), cx
- mov 24(bp), dx
- mov 28(bp), si
- mov 32(bp), di
- pop 36(bp) ! bp
-
- mov ax, ss
- mov ds, ax ! restore ds and es
- mov es, ax
- ret
-
-
-!*===========================================================================*
-!* real2prot *
-!*===========================================================================*
-! Switch from real to protected mode.
-real2prot:
- lgdt _gdt+GDT_SELECTOR ! set global descriptor table
- smsw ax
- mov msw, ax ! save real mode msw
- orb al, #0x01 ! set PE (protection enable) bit
- lmsw ax ! set msw, enabling protected mode
-
- jmpf csinit, CS_SELECTOR ! set code segment selector
-csinit:
- mov ax, #DS_SELECTOR ! set data selectors
- mov ds, ax
- mov es, ax
- mov ss, ax
- lidt _gdt+IDT_SELECTOR ! set interrupt vectors
- andb _gdt+TSS_SELECTOR+DESC_ACCESS, #~0x02 ! clear TSS busy bit
- mov ax, #TSS_SELECTOR
- ltr ax ! set TSS register
-
- movb ah, #0x02
- jmp gate_A20 ! enable the A20 address line
-
-
-!*===========================================================================*
-!* prot2real *
-!*===========================================================================*
-! Switch from protected to real mode.
-prot2real:
- mov save_sp, sp ! save stack pointer
- cmp _processor, #386 ! is this a 386?
- jae p2r386
-p2r286:
- xor ax, ax
- mov _gdt+ES_286_OFFSET+DESC_BASE, ax
- movb _gdt+ES_286_OFFSET+DESC_BASE_MIDDLE, al
- movb _gdt+ES_286_OFFSET+DESC_BASE_HIGH, al
- mov ax, #ES_286_SELECTOR
- mov es, ax ! BIOS data segment
- eseg mov 0x0467, #real ! set return from shutdown address
- cseg mov ax, kernel_cs
- eseg mov 0x0469, ax
- movb al, #0x8F
- outb 0x70 ! select CMOS byte 0x0F (disable NMI)
- jmp .+2
- movb al, #0x0A
- outb 0x71 ! set shutdown code to 0x0A "jump far"
- jmp p_reset ! cause a processor shutdown
-p2r386:
- lidt idt_vectors ! real mode interrupt vectors
- push _gdt+CS_SELECTOR+0
- push _gdt+DS_SELECTOR+0 ! save CS and DS limits
- mov _gdt+CS_SELECTOR+0, #0xFFFF
- mov _gdt+DS_SELECTOR+0, #0xFFFF ! set 64k limits
- jmpf cs64k, CS_SELECTOR ! reload selectors
-cs64k: mov ax, #DS_SELECTOR
- mov ds, ax
- mov es, ax
- mov ss, ax
- pop _gdt+DS_SELECTOR+0
- pop _gdt+CS_SELECTOR+0 ! restore CS and DS limits
- .data1 0x0F,0x20,0xC0 ! mov eax, cr0
- mov ax, msw ! restore real mode (16 bits) msw
- .data1 0x0F,0x22,0xC0 ! mov cr0, eax
- .data1 0xEA ! jmpf real, "kernel_cs"
- .data2 real
-kernel_cs:
- .data2 0
-real:
- cseg mov ax, kernel_ds ! reload data segment registers
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov sp, save_sp ! restore stack
-
- xorb ah, ah
- !jmp gate_A20 ! disable the A20 address line
-
-! Enable (ah = 0x02) or disable (ah = 0x00) the A20 address line.
-gate_A20:
- cmp _ps_mca, #0 ! PS/2 bus?
- jnz gate_PS_A20
- call kb_wait
- movb al, #0xD1 ! Tell keyboard that a command is coming
- outb 0x64
- call kb_wait
- movb al, #0xDD ! 0xDD = A20 disable code if ah = 0x00
- orb al, ah ! 0xDF = A20 enable code if ah = 0x02
- outb 0x60
- call kb_wait
- movb al, #0xFF ! Pulse output port
- outb 0x64
- call kb_wait ! Wait for the A20 line to settle down
- ret
-kb_wait:
- inb 0x64
- testb al, #0x02 ! Keyboard input buffer full?
- jnz kb_wait ! If so, wait
- ret
-
-gate_PS_A20: ! The PS/2 can twiddle A20 using port A
- inb 0x92 ! Read port A
- andb al, #0xFD
- orb al, ah ! Set A20 bit to the required state
- outb 0x92 ! Write port A
- jmp .+2 ! Small delay
-A20ok: inb 0x92 ! Check port A
- andb al, #0x02
- cmpb al, ah ! A20 line settled down to the new state?
- jne A20ok ! If not then wait
- ret
-
-
-!*===========================================================================*
-!* cp_mess *
-!*===========================================================================*
-! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
-! phys_clicks dst_clicks, vir_bytes dst_offset);
-! This routine makes a fast copy of a message from anywhere in the address
-! space to anywhere else. It also copies the source address provided as a
-! parameter to the call into the first word of the destination message.
-!
-! Note that the message size, "Msize" is in WORDS (not bytes) and must be set
-! correctly. Changing the definition of message in the type file and not
-! changing it here will lead to total disaster.
-
-_cp_mess:
- cld
- push es ! save es
- push ds ! save ds
- mov bx,sp ! index off bx because machine cannot use sp
- push si ! save si
- push di ! save di
-
- mov ax,12(bx) ! destination click
-#if HCLICK_SHIFT > CLICK_SHIFT
-#error /* Small click sizes are not supported (right shift will lose bits). */
-#endif
-#if HCLICK_SHIFT < CLICK_SHIFT
- movb cl,#CLICK_SHIFT-HCLICK_SHIFT
- shl ax,cl ! destination segment
-#endif
- mov es,ax
- mov di,14(bx) ! offset of destination message
-
-! Be careful not to destroy ds before we are finished with the bx pointer.
-! We are using bx and not the more natural bp to save pushing bp.
-
- mov ax,6(bx) ! process number of sender
- mov si,10(bx) ! offset of source message
- mov bx,8(bx) ! source click (finished with bx as a pointer)
-#if HCLICK_SHIFT < CLICK_SHIFT
- shl bx,cl ! source segment
-#endif
- mov ds,bx
-
- stos ! copy process number of sender to dest message
- add si,*2 ! do not copy first word
- mov cx,*Msize-1 ! remember, first word does not count
- rep ! iterate cx times to copy 11 words
- movs ! copy the message
- pop di ! restore di
- pop si ! restore si
- pop ds ! restore ds
- pop es ! restore es
- ret ! that is all folks!
-
-
-!*===========================================================================*
-!* exit *
-!*===========================================================================*
-! PUBLIC void exit();
-! Some library routines use exit, so provide a dummy version.
-! Actual calls to exit cannot occur in the kernel.
-! Same for .fat & .trp.
-
-_exit:
-__exit:
-___exit:
-.fat:
-.trp:
- sti
- jmp __exit
-
-
-!*===========================================================================*
-!* phys_insw *
-!*===========================================================================*
-! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);
-! Input an array from an I/O port. Absolute address version of insw().
-
-_phys_insw:
- call portio_intro
- mov es, bx ! destination segment
- mov di, ax ! destination offset
- shr cx, #1 ! word count
- rep ins ! input many words
- jmp portio_return
-
-portio_intro:
- pop ax ! hold return address
- push bp ! create stack frame
- mov bp, sp
- push si
- push di
- push ax ! retore return address
- mov dx, 4(bp) ! port to do I/O
- mov ax, 6(bp) ! source/destination address in bx:ax
- mov bx, 8(bp)
- mov cx, 10(bp) ! count in bytes
- cld ! direction is UP
-portio_setup:
- push cx ! segment/offset setup
- movb ch, bl
- mov bx, ax
- and ax, #0x000F ! ax = offset = address % HCLICK_SIZE
- movb cl, #4
- shr bx, cl
- shlb ch, cl
- orb bh, ch ! bx = segment = address / HCLICK_SIZE
- pop cx
- ret
-
-portio_return:
- mov ax, ss ! restore segment registers
- mov ds, ax
- mov es, ax
- pop di ! unwind stack frame
- pop si
- pop bp
- ret
-
-
-!*===========================================================================*
-!* phys_insb *
-!*===========================================================================*
-! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);
-! Input an array from an I/O port. Absolute address version of insb().
-! Note: The 8086 doesn't have string I/O instructions, so a loop is used.
-
-_phys_insb:
- call portio_intro
- mov es, bx ! destination segment
- mov di, ax ! destination offset
- jcxz 1f
-0: inb dx ! input 1 byte
- stosb ! write 1 byte
- loop 0b ! many times
-1:
- jmp portio_return
-
-
-!*===========================================================================*
-!* phys_outsw *
-!*===========================================================================*
-! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);
-! Output an array to an I/O port. Absolute address version of outsw().
-
-_phys_outsw:
- call portio_intro
- mov ds, bx ! source segment
- mov si, ax ! source offset
- shr cx, #1 ! word count
- rep outs ! output many words
- jmp portio_return
-
-
-!*===========================================================================*
-!* phys_outsb *
-!*===========================================================================*
-! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);
-! Output an array to an I/O port. Absolute address version of outsb().
-
-_phys_outsb:
- call portio_intro
- mov ds, bx ! source segment
- mov si, ax ! source offset
- jcxz 1f
-0: lodsb ! read 1 byte
- outb dx ! output 1 byte
- loop 0b ! many times
-1:
- jmp portio_return
-
-
-!*==========================================================================*
-!* enable_irq *
-!*==========================================================================*/
-! PUBLIC void enable_irq(irq_hook_t *hook)
-! Enable an interrupt request line by clearing an 8259 bit.
-! Equivalent code for irq < 8:
-! if ((irq_actids[hook->irq] &= ~hook->id) == 0)
-! outb(INT_CTLMASK, inb(INT_CTLMASK) & ~(1 << irq));
-
-_enable_irq:
- push bp
- mov bp, sp
- pushf
- cli
- mov bx, 4(bp) ! hook
- mov cx, 4(bx) ! irq
- mov ax, 6(bx) ! id bit
- not ax
- mov bx, cx
- add bx, bx
- and _irq_actids(bx), ax ! clear this id bit
- jnz en_done ! still masked by other handlers?
- movb ah, #~1
- rolb ah, cl ! ah = ~(1 << (irq % 8))
- mov dx, #INT_CTLMASK ! enable irq < 8 at the master 8259
- cmpb cl, #8
- jb 0f
- mov dx, #INT2_CTLMASK ! enable irq >= 8 at the slave 8259
-0: inb dx
- andb al, ah
- outb dx ! clear bit at the 8259
-en_done:popf
- leave
- ret
-
-
-!*==========================================================================*
-!* disable_irq *
-!*==========================================================================*/
-! PUBLIC int disable_irq(irq_hook_t *hook)
-! Disable an interrupt request line by setting an 8259 bit.
-! Equivalent code for irq < 8:
-! irq_actids[hook->irq] |= hook->id;
-! outb(INT_CTLMASK, inb(INT_CTLMASK) | (1 << irq));
-! Returns true iff the interrupt was not already disabled.
-
-_disable_irq:
- push bp
- mov bp, sp
- pushf
- cli
- mov bx, 4(bp) ! hook
- mov cx, 4(bx) ! irq
- mov ax, 6(bx) ! id bit
- pushf
- cli
- mov bx, cx
- add bx, bx
- or _irq_actids(bx), ax ! set this id bit
- movb ah, #1
- rolb ah, cl ! ah = (1 << (irq % 8))
- mov dx, #INT_CTLMASK ! disable irq < 8 at the master 8259
- cmpb cl, #8
- jb 0f
- mov dx, #INT2_CTLMASK ! disable irq >= 8 at the slave 8259
-0: inb dx
- testb al, ah
- jnz dis_already ! already disabled?
- orb al, ah
- outb dx ! set bit at the 8259
- mov ax, #1 ! disabled by this function
- popf
- leave
- ret
-dis_already:
- xor ax, ax ! already disabled
- popf
- leave
- ret
-
-
-!*===========================================================================*
-!* phys_copy *
-!*===========================================================================*
-! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination,
-! phys_bytes bytecount);
-! Copy a block of physical memory.
-
-SRCLO = 4
-SRCHI = 6
-DESTLO = 8
-DESTHI = 10
-COUNTLO = 12
-COUNTHI = 14
-
-_phys_copy:
- push bp ! save only registers required by C
- mov bp,sp ! set bp to point to source arg less 4
-
- push si ! save si
- push di ! save di
- push ds ! save ds
- push es ! save es
-
- mov ax,SRCLO(bp) ! dx:ax = source address (dx is NOT segment)
- mov dx,SRCHI(bp)
- mov si,ax ! si = source offset = address % 16
- and si,#OFF_MASK
- andb dl,#HCHIGH_MASK ! ds = source segment = address / 16 % 0x10000
- andb al,#HCLOW_MASK
- orb al,dl ! now bottom 4 bits of dx are in ax
- movb cl,#HCLICK_SHIFT ! rotate them to the top 4
- ror ax,cl
- mov ds,ax
-
- mov ax,DESTLO(bp) ! dx:ax = destination addr (dx is NOT segment)
- mov dx,DESTHI(bp)
- mov di,ax ! di = dest offset = address % 16
- and di,#OFF_MASK
- andb dl,#HCHIGH_MASK ! es = dest segment = address / 16 % 0x10000
- andb al,#HCLOW_MASK
- orb al,dl
- ror ax,cl
- mov es,ax
-
- mov ax,COUNTLO(bp) ! dx:ax = remaining count
- mov dx,COUNTHI(bp)
-
-! copy upwards (cannot handle overlapped copy)
-
-pc_loop:
- mov cx,ax ! provisional count for this iteration
- test ax,ax ! if count >= 0x8000, only do 0x8000 per iter
- js pc_bigcount ! low byte already >= 0x8000
- test dx,dx
- jz pc_upcount ! less than 0x8000
-pc_bigcount:
- mov cx,#0x8000 ! use maximum count per iteration
-pc_upcount:
- sub ax,cx ! update count
- sbb dx,#0 ! cannot underflow, so carry clear now for rcr
- rcr cx,#1 ! count in words, carry remembers if byte
- jnb pc_even ! no odd byte
- movb ! copy odd byte
-pc_even:
- rep ! copy 1 word at a time
- movs ! word copy
-
- mov cx,ax ! test if remaining count is 0
- or cx,dx
- jnz pc_more ! more to do
-
- pop es ! restore es
- pop ds ! restore ds
- pop di ! restore di
- pop si ! restore si
- pop bp ! restore bp
- ret ! return to caller
-
-pc_more:
- sub si,#0x8000 ! adjust pointers so the offset does not
- mov cx,ds ! overflow in the next 0x8000 bytes
- add cx,#0x800 ! pointers end up same physical location
- mov ds,cx ! the current offsets are known >= 0x8000
- sub di,#0x8000 ! since we just copied that many
- mov cx,es
- add cx,#0x800
- mov es,cx
- jmp pc_loop ! start next iteration
-
-
-!*===========================================================================*
-!* mem_rdw *
-!*===========================================================================*
-! PUBLIC u16_t mem_rdw(u16_t segment, u16_t *offset);
-! Load and return the word at the far pointer segment:offset.
-
-_mem_rdw:
- mov cx,ds ! save ds
- pop dx ! return adr
- pop ds ! segment
- pop bx ! offset
- sub sp,#2+2 ! adjust for parameters popped
- mov ax,(bx) ! load the word to return
- mov ds,cx ! restore ds
- jmp (dx) ! return
-
-
-!*===========================================================================*
-!* reset *
-!*===========================================================================*
-! PUBLIC void reset();
-! Reset the system.
-! In real mode we simply jump to the reset address at F000:FFF0.
-
-_reset:
- jmpf 0xFFF0,0xF000
-
-
-!*===========================================================================*
-!* mem_vid_copy *
-!*===========================================================================*
-! PUBLIC void mem_vid_copy(u16 *src, unsigned dst, unsigned count);
-!
-! Copy count characters from kernel memory to video memory. Src is an ordinary
-! pointer to a word, but dst and count are character (word) based video offset
-! and count. If src is null then screen memory is blanked by filling it with
-! blank_color.
-
-_mem_vid_copy:
- push bp
- mov bp, sp
- push si
- push di
- push es
- mov si, 4(bp) ! source
- mov di, 6(bp) ! destination
- mov dx, 8(bp) ! count
- mov es, _vid_seg ! segment containing video memory
- cld ! make sure direction is up
-mvc_loop:
- and di, _vid_mask ! wrap address
- mov cx, dx ! one chunk to copy
- mov ax, _vid_size
- sub ax, di
- cmp cx, ax
- jbe 0f
- mov cx, ax ! cx = min(cx, vid_size - di)
-0: sub dx, cx ! count -= cx
- shl di, #1 ! byte address
- add di, _vid_off ! in video memory
- test si, si ! source == 0 means blank the screen
- jz mvc_blank
-mvc_copy:
- rep ! copy words to video memory
- movs
- jmp mvc_test
-mvc_blank:
- mov ax, _blank_color ! ax = blanking character
- rep
- stos ! copy blanks to video memory
- !jmp mvc_test
-mvc_test:
- sub di, _vid_off
- shr di, #1 ! back to a word address
- test dx, dx
- jnz mvc_loop
-mvc_done:
- pop es
- pop di
- pop si
- pop bp
- ret
-
-
-!*===========================================================================*
-!* vid_vid_copy *
-!*===========================================================================*
-! PUBLIC void vid_vid_copy(unsigned src, unsigned dst, unsigned count);
-!
-! Copy count characters from video memory to video memory. Handle overlap.
-! Used for scrolling, line or character insertion and deletion. Src, dst
-! and count are character (word) based video offsets and counts.
-
-_vid_vid_copy:
- push bp
- mov bp, sp
- push si
- push di
- push es
- mov si, 4(bp) ! source
- mov di, 6(bp) ! destination
- mov dx, 8(bp) ! count
- mov es, _vid_seg ! segment containing video memory
- cmp si, di ! copy up or down?
- jb vvc_down
-vvc_up:
- cld ! direction is up
-vvc_uploop:
- and si, _vid_mask ! wrap addresses
- and di, _vid_mask
- mov cx, dx ! one chunk to copy
- mov ax, _vid_size
- sub ax, si
- cmp cx, ax
- jbe 0f
- mov cx, ax ! cx = min(cx, vid_size - si)
-0: mov ax, _vid_size
- sub ax, di
- cmp cx, ax
- jbe 0f
- mov cx, ax ! cx = min(cx, vid_size - di)
-0: sub dx, cx ! count -= cx
- call vvc_copy
- test dx, dx
- jnz vvc_uploop ! again?
- jmp vvc_done
-vvc_down:
- std ! direction is down
- add si, dx ! start copying at the top
- dec si
- add di, dx
- dec di
-vvc_downloop:
- and si, _vid_mask ! wrap addresses
- and di, _vid_mask
- mov cx, dx ! one chunk to copy
- lea ax, 1(si)
- cmp cx, ax
- jbe 0f
- mov cx, ax ! cx = min(cx, si + 1)
-0: lea ax, 1(di)
- cmp cx, ax
- jbe 0f
- mov cx, ax ! cx = min(cx, di + 1)
-0: sub dx, cx ! count -= cx
- call vvc_copy
- test dx, dx
- jnz vvc_downloop ! again?
- cld ! C compiler expect up
- !jmp vvc_done
-vvc_done:
- pop es
- pop di
- pop si
- pop bp
- ret
-
-! Copy video words. (Inner code of both the up and downcopying loop.)
-vvc_copy:
- shl si, #1
- shl di, #1 ! byte addresses
- add si, _vid_off
- add di, _vid_off ! in video memory
- push ds ! must set ds here, 8086 can't do
- mov ds, _vid_seg ! 'rep eseg movs' with interrupts on
- rep
- movs ! copy video words
- pop ds
- sub si, _vid_off
- sub di, _vid_off
- shr si, #1
- shr di, #1 ! back to word addresses
- ret
-
-
-!*===========================================================================*
-!* level0 *
-!*===========================================================================*
-! PUBLIC void level0(void (*func)(void))
-! Not very interesting in real mode, see p_level0.
-!
-_level0:
- mov bx, sp
- jmp @2(bx)
-
-
-!*===========================================================================*
-!* klib_init_prot *
-!*===========================================================================*
-! PUBLIC void klib_init_prot();
-! Initialize klib for protected mode by patching some real mode functions
-! at their starts to jump to their protected mode equivalents, according to
-! the patch table. Saves a lot of tests on the "protected_mode" variable.
-! Note that this function must be run in real mode, for it writes the code
-! segment. (One otherwise has to set up a descriptor, etc, etc.)
-
-klib_init_prot:
- mov si,#patch_table
-kip_next:
- lods ! original function
- mov bx,ax
- cseg movb (bx),#JMP_OPCODE ! overwrite start of function by a long jump
- lods ! new function - target of jump
- sub ax,bx ! relative jump
- sub ax,#3 ! adjust by length of jump instruction
- cseg mov 1(bx),ax ! set address
- cmp si,#end_patch_table ! end of table?
- jb kip_next
-kip_done:
- ret
-
-
-!*===========================================================================*
-!* variants for protected mode *
-!*===========================================================================*
-! Some routines are different in protected mode.
-! The only essential difference is the handling of segment registers.
-! One complication is that the method of building segment descriptors is not
-! reentrant, so the protected mode versions must not be called by interrupt
-! handlers.
-
-
-!*===========================================================================*
-!* p_cp_mess *
-!*===========================================================================*
-! The real mode version attempts to be efficient by passing raw segments but
-! that just gets in the way here.
-
-p_cp_mess:
- mov bx, sp ! bx -> arguments
- push si
- push di
- push ds
- push es
-
- mov ax, 4(bx) ! Compute source descriptor base
- mov dx, ax
- shl ax, #CLICK_SHIFT
- shr dx, #16-CLICK_SHIFT ! dx:ax = src_clicks * CLICK_SIZE
- add ax, 6(bx)
- adc dx, #0 ! dx:ax += src_offset
- mov _gdt+DS_286_OFFSET+DESC_BASE, ax
- movb _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE, dl
- movb _gdt+DS_286_OFFSET+DESC_BASE_HIGH, dh
-
- mov ax, 8(bx) ! Compute destination descriptor base
- mov dx, ax
- shl ax, #CLICK_SHIFT
- shr dx, #16-CLICK_SHIFT ! dx:ax = dst_clicks * CLICK_SIZE
- add ax, 10(bx)
- adc dx, #0 ! dx:ax += dst_offset
- mov _gdt+ES_286_OFFSET+DESC_BASE, ax
- movb _gdt+ES_286_OFFSET+DESC_BASE_MIDDLE, dl
- movb _gdt+ES_286_OFFSET+DESC_BASE_HIGH, dh
-
- mov bx, 2(bx) ! proc no
- mov ax, #DS_286_SELECTOR
- mov ds, ax
- mov ax, #ES_286_SELECTOR
- mov es, ax
-
- eseg mov 0, bx ! proc no. of sender from arg, not msg
- mov si, #2 ! src offset is now 2 relative to start of seg
- mov di, si ! and destination offset
- mov cx, #Msize-1 ! word count
- cld ! direction is up
- rep
- movs ! copy message (except first word)
-
- pop es
- pop ds
- pop di
- pop si
- ret
-
-
-!*===========================================================================*
-!* p_portio_setup *
-!*===========================================================================*
-! The phys_insw, phys_outsw, etc. functions need an address setup routine that
-! uses a segment descriptor.
-p_portio_setup:
- mov _gdt+DS_286_OFFSET+DESC_BASE, ax
- movb _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE, bl
- movb _gdt+DS_286_OFFSET+DESC_BASE_HIGH, bh
- xor ax, ax ! ax = 0 = start of segment
- mov bx, #DS_286_SELECTOR ! bx = segment selector
- ret
-
-
-!*===========================================================================*
-!* p_phys_copy *
-!*===========================================================================*
-p_phys_copy:
- cld
- pop dx
- pop _gdt+DS_286_OFFSET+DESC_BASE
- pop ax ! pop source into base of source descriptor
- movb _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,al
- movb _gdt+DS_286_OFFSET+DESC_BASE_HIGH,ah
- pop _gdt+ES_286_OFFSET+DESC_BASE
- pop ax ! pop destination into base of dst descriptor
- movb _gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,al
- movb _gdt+ES_286_OFFSET+DESC_BASE_HIGH,ah
- pop cx ! byte count in bx:cx
- pop bx
- sub sp,#4+4+4
-
- push di
- push si
- push es
- push ds
- sub si,si ! src offset is now 0 relative to start of seg
- mov di,si ! and destination offset
- jmp ppc_next
-
-! It is too much trouble to align the segment bases, so word alignment is hard.
-! Avoiding the book-keeping for alignment may be good anyway.
-
-ppc_large:
- push cx
- mov cx,#0x8000 ! copy a large chunk of this many words
- rep
- movs
- pop cx
- dec bx
- pop ds ! update the descriptors
- addb _gdt+DS_286_OFFSET+DESC_BASE_MIDDLE,#1
- adcb _gdt+DS_286_OFFSET+DESC_BASE_HIGH,#0
- addb _gdt+ES_286_OFFSET+DESC_BASE_MIDDLE,#1
- adcb _gdt+ES_286_OFFSET+DESC_BASE_HIGH,#0
- push ds
-ppc_next:
- mov ax,#DS_286_SELECTOR ! (re)load the selectors
- mov ds,ax
- mov ax,#ES_286_SELECTOR
- mov es,ax
- test bx,bx
- jnz ppc_large
-
- shr cx,#1 ! word count
- rep
- movs ! move any leftover words
- rcl cx,#1 ! restore old bit 0
- rep
- movb ! move any leftover byte
- pop ds
- pop es
- pop si
- pop di
- jmp (dx)
-
-!*===========================================================================*
-!* p_reset *
-!*===========================================================================*
-! Reset the system by loading IDT with offset 0 and interrupting.
-
-p_reset:
- lidt idt_zero
- int 3 ! anything goes, the 286 will not like it
-
-!*===========================================================================*
-!* idle_task *
-!*===========================================================================*
-_idle_task:
-! This task is called when the system has nothing else to do. The HLT
-! instruction puts the processor in a state where it draws minimum power.
- mov ax, #halt
- push ax
- call _level0 ! level0(halt)
- pop ax
- jmp _idle_task
-halt:
- sti
- hlt
- cli
- ret
-
-
-!*===========================================================================*
-!* p_level0 *
-!*===========================================================================*
-! PUBLIC void level0(void (*func)(void))
-! Call a function at permission level 0. This allows kernel tasks to do
-! things that are only possible at the most privileged CPU level.
-!
-p_level0:
- mov bx, sp
- mov ax, 2(bx)
- mov _level0_func, ax
- int LEVEL0_VECTOR
- ret
-
-
-!*===========================================================================*
-!* data *
-!*===========================================================================*
- .data
-patch_table: ! pairs (old function, new function)
- .data2 _int86, p_int86
- .data2 _cp_mess, p_cp_mess
- .data2 _phys_copy, p_phys_copy
- .data2 portio_setup, p_portio_setup
- .data2 _reset, p_reset
- .data2 _level0, p_level0
- .data2 _restart, p_restart ! in mpx file
- .data2 save, p_save ! in mpx file
-end_patch_table: ! end of table
-
-idt_vectors: ! limit and base of real mode interrupt vectors
- .data2 0x3FF
-idt_zero: ! zero limit IDT to cause a processor shutdown
- .data2 0, 0, 0
-
- .bss
-save_sp: ! place to put sp when switching to real mode
- .space 2
-msw: ! saved real mode machine status word
- .space 2
* Changes:
* Nov 24, 2004 simplified main() with system image (Jorrit N. Herder)
* Oct 21, 2004 moved copyright to announce() (Jorrit N. Herder)
- * Sep 30, 2004 moved mem_init() to this file (Jorrit N. Herder)
* Sep 04, 2004 created stop_sequence() to cleanup (Jorrit N. Herder)
* Aug 20, 2004 split wreboot() and shutdown() (Jorrit N. Herder)
* Jun 15, 2004 moved wreboot() to this file (Jorrit N. Herder)
register struct proc *rp;
register int i;
int hdrindex; /* index to array of a.out headers */
- phys_clicks text_base;
- vir_clicks text_clicks;
+ phys_clicks text_base, bootdev_base;
+ vir_clicks text_clicks, bootdev_clicks;
vir_clicks data_clicks;
reg_t ktsb; /* kernel task stack base */
struct memory *memp;
/* Initialize the interrupt controller. */
intr_init(1);
- /* Make free memory list from memory sizes passed by boot monitor. */
- mem_init();
-
/* Clear the process table. Anounce each slot as empty and
* set up mappings for proc_addr() and proc_number() macros.
*/
}
ktsb += ttp->stksize; /* point to high end of stack */
rp->p_reg.sp = ktsb; /* this task's initial stack ptr */
- text_base = code_base >> CLICK_SHIFT;
+ text_base = kinfo.code_base >> CLICK_SHIFT;
/* processes that are in the kernel */
hdrindex = 0; /* all use the first a.out header */
} else {
/* Code and data segments must be allocated in protected mode. */
alloc_segments(rp);
}
- bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
-
- /* This actually is not needed, because ready() already set 'proc_ptr' to
- * first task that was announced ready.
- */
- lock_pick_proc();
- /* Expect an image of the root FS to be loaded into memory as well. The
- * root FS image is located directly after the programs.
+#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);
- kprintf("Root FS image found: %s\n", (e_hdr.a_flags&A_IMG)? "yes" : "no");
+ phys_copy(aout + hdrindex * A_MINHDR,vir2phys(&e_hdr),(phys_bytes) A_MINHDR);
if (e_hdr.a_flags & A_IMG) {
- kprintf("Size of root FS: %u, ", e_hdr.a_data);
- kprintf("base : %u, ", e_hdr.a_syms);
- kprintf("header size : %u, ", e_hdr.a_hdrlen);
- rp = proc_addr(MEMORY);
- rp->p_farmem[0].mem_phys = e_hdr.a_syms;
- rp->p_farmem[0].mem_len = e_hdr.a_data;
+
+ kinfo.bootdev_base = e_hdr.a_syms;
+ kinfo.bootdev_size = e_hdr.a_data;
/* Remove from free list, to prevent being overwritten. */
- text_base = e_hdr.a_syms >> CLICK_SHIFT;
- text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
- if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* Common I&D */
- data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
+ bootdev_base = e_hdr.a_syms >> CLICK_SHIFT;
+ bootdev_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
for (memp = mem; memp < &mem[NR_MEMS]; memp++) {
- if (memp->base == text_base) {
- kprintf("Memory removed from free list.\n", NO_ARG);
- memp->base += text_clicks + data_clicks;
- memp->size -= text_clicks + data_clicks;
+ if (memp->base == bootdev_base) {
+ memp->base += bootdev_clicks;
+ memp->size -= bootdev_clicks;
}
}
}
-
+#endif
- /* MINIX and all system services have been loaded. Announce to the user.
- * Then go to the assembly code to start running the current process.
+ /* This actually is not needed, because ready() already set 'proc_ptr.' */
+ lock_pick_proc();
+ bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
+
+ /* MINIX is now ready. Display the startup banner to the user and return
+ * to the assembly code to start running the current process.
*/
announce();
restart();
PRIVATE void announce(void)
{
/* Display the MINIX startup banner. */
- kprintf("MINIX %s Copyright 2001 Prentice-Hall, Inc.\n",
- karg(OS_RELEASE "." OS_VERSION));
+ kprintf("MINIX %s. Copyright 2001 Prentice-Hall, Inc.\n",
+ karg(kinfo.version));
#if (CHIP == INTEL)
/* Real mode, or 16/32-bit protected mode? */
kprintf("Executing in %s mode\n\n",
- protected_mode ? karg("32-bit protected") : karg("real"));
+ machine.protected ? karg("32-bit protected") : karg("real"));
#endif
+
+ /* Check if boot device was loaded with the kernel. */
+ if (kinfo.bootdev_base > 0)
+ kprintf("Image of /dev/boot loaded. Size: %u KB.\n", kinfo.bootdev_size);
}
/* See if the last process' shutdown was successfull. Else, force exit. */
if (p != NIL_PROC) {
- kprintf("[%s]\n", isalivep(p) ? "FAILED" : "OK");
+ kprintf("[%s]\n", isalivep(p) ? karg("FAILED") : karg("OK"));
if (isalivep(p))
clear_proc(p->p_nr); /* now force process to exit */
}
if (p == NIL_PROC) p = BEG_PROC_ADDR;
while (TRUE) {
if (isalivep(p) && p->p_type == level) { /* found a process */
- kprintf("- Stopping %s ", p->p_name);
- kprintf("%s ... ", types[p->p_type]);
+ kprintf("- Stopping %s ", karg(p->p_name));
+ kprintf("%s ... ", karg(types[p->p_type]));
shutdown_process = p; /* directly continue if exited */
notify(proc_number(p), HARD_STOP);
set_timer(tp, get_uptime()+STOP_TICKS, stop_sequence);
* For RBT_MONITOR, the MM has provided the program.
*/
if (how == RBT_HALT) {
- phys_copy(vir2phys(" "), mon_params, 2);
+ phys_copy(vir2phys("delay;"), kinfo.params_base, 7);
} else if (how == RBT_REBOOT) {
- phys_copy(vir2phys("delay;boot"), mon_params, 11);
+ phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
}
level0(monitor);
}
/* Stop BIOS memory test. */
- phys_copy(vir2phys(&magic), (phys_bytes) ADR_MEM_CHECK, LEN_MEM_CHECK);
+ phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE);
/* Reset the system by jumping to the reset address (real mode), or by
* forcing a processor shutdown (protected mode).
+++ /dev/null
-/* Entry points into this file:
- * mem_init: create a list a free memory
- * alloc_segments: allocate segments for 8088 or higher processor
- */
-
-#include "kernel.h"
-#include "protect.h"
-#include "proc.h"
-
-
-#if (CHIP == INTEL)
-
-/* In real mode only 1M can be addressed, and in 16-bit protected we can go
- * no further than we can count in clicks. (The 286 is further limited by
- * its 24 bit address bus, but we can assume in that case that no more than
- * 16M memory is reported by the BIOS.)
- */
-#define MAX_REAL 0x00100000L
-#define MAX_16BIT (0xFFF0L << CLICK_SHIFT)
-
-/*=========================================================================*
- * mem_init *
- *=========================================================================*/
-PUBLIC void mem_init()
-{
-/* Initialize the free memory list from the 'memory' boot variable. Translate
- * the byte offsets and sizes in this list to clicks, properly truncated. Also
- * make sure that we don't exceed the maximum address space of the 286 or the
- * 8086, i.e. when running in 16-bit protected mode or real mode.
- */
- long base, size, limit;
- char *s, *end; /* use to parse boot variable */
- int i;
- struct memory *memp;
-#if _WORD_SIZE == 2
- unsigned long max_address;
-#endif
-
- /* The available memory is determined by MINIX' boot loader as a list of
- * (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
- * in boot.s. The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
- * b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1
- * and b2:s2 are combined if the memory is adjacent.
- */
- s = getkenv("memory"); /* get memory boot variable */
- tot_mem_size = 0;
- for (i = 0; i < NR_MEMS; i++) {
- memp = &mem[i]; /* result is stored here */
- base = size = 0;
- if (*s != 0) { /* end of boot variable */
- /* Expect base to be read (end != s) and ':' as next char. */
- base = kstrtoul(s, &end, 0x10); /* get number */
- if (end != s && *end == ':') s = ++end; /* skip ':' */
- else *s=0; /* fake end for next; should not happen */
- /* Expect size to be read and skip ',', unless at end. */
- size = kstrtoul(s, &end, 0x10); /* get number */
- if (end != s && *end == ',') s = ++end; /* skip ',' */
- else if (end != s && *end == 0) s = end; /* end found */
- else *s=0; /* fake end for next; should not happen */
- }
- limit = base + size;
-#if _WORD_SIZE == 2
- max_address = protected_mode ? MAX_16BIT : MAX_REAL;
- if (limit > max_address) limit = max_address;
-#endif
- base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
- limit &= ~(long)(CLICK_SIZE-1);
- if (limit <= base) continue;
- memp->base = base >> CLICK_SHIFT;
- memp->size = (limit - base) >> CLICK_SHIFT;
- tot_mem_size += memp->size;
- }
-}
-
-/*==========================================================================*
- * alloc_segments *
- *==========================================================================*/
-PUBLIC void alloc_segments(rp)
-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.
- * Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
- */
- phys_bytes code_bytes;
- phys_bytes data_bytes;
- int privilege;
-
- if (protected_mode) {
- 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)
- code_bytes = data_bytes; /* common I&D, poor protect */
- else
- code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
- privilege = (isidlep(rp) || istaskp(rp)) ?
- TASK_PRIVILEGE : USER_PRIVILEGE;
- init_codeseg(&rp->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],
- (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);
- }
-}
-#endif /* (CHIP == INTEL) */
-
-#
-! This file, mpx88.s, is included by mpx.s when Minix is compiled for
-! 16-bit Intel CPUs. The alternative mpx386.s is compiled for 32-bit CPUs.
-!
-! This file contains the assembler startup code for Minix and the 16-bit
-! interrupt handlers. It cooperates with cstart.c to set up a good
-! environment for main().
-
-! This file is part of the lowest layer of the MINIX kernel. The other part
-! is "proc.c". The lowest layer does process switching and message handling.
-
-! Every transition to the kernel goes through this file. Transitions are
-! caused by sending/receiving messages and by most interrupts. (RS232
-! interrupts may be handled in the file "rs2.s" and then they rarely enter
-! the kernel.)
-
-! Transitions to the kernel may be nested. The initial entry may be with a
-! system call, exception or hardware interrupt; reentries may only be made
-! by hardware interrupts. The count of reentries is kept in "k_reenter".
-! It is important for deciding whether to switch to the kernel stack and
-! for protecting the message passing code in "proc.c".
-
-! For the message passing trap, most of the machine state is saved in the
-! proc table. (Some of the registers need not be saved.) Then the stack is
-! switched to "k_stack", and interrupts are reenabled. Finally, the system
-! call handler (in C) is called. When it returns, interrupts are disabled
-! again and the code falls into the restart routine, to finish off held-up
-! interrupts and run the process or task whose pointer is in "proc_ptr".
-
-! Hardware interrupt handlers do the same, except (1) The entire state must
-! be saved. (2) There are too many handlers to do this inline, so the save
-! routine is called. A few cycles are saved by pushing the address of the
-! appropiate restart routine for a return later. (3) A stack switch is
-! avoided when the stack is already switched. (4) The (master) 8259 interrupt
-! controller is reenabled centrally in save(). (5) Each interrupt handler
-! masks its interrupt line using the 8259 before enabling (other unmasked)
-! interrupts, and unmasks it after servicing the interrupt. This limits the
-! nest level to the number of lines and protects the handler from itself.
-
-! For communication with the boot monitor at startup time some constant
-! data are compiled into the beginning of the text segment. This facilitates
-! reading the data at the start of the boot process, since only the first
-! sector of the file needs to be read.
-
-! Some data storage is also allocated at the end of this file. This data
-! will be at the start of the data segment of the kernel and will be read
-! and modified by the boot monitor before the kernel starts.
-
-#include <minix/config.h>
-#include <minix/const.h>
-#include <minix/com.h>
-#include "const.h"
-#include "sconst.h"
-#include "protect.h"
-
-! The external entry points into this file are:
-! Note: in assembly language the .define statement applied to a function name
-! is loosely equivalent to a prototype in C code -- it makes it possible to
-! link to an entity declared in the assembly code but does not create
-! the entity.
-
-.define _int00 ! handlers for traps and exceptions
-.define _int01
-.define _int02
-.define _int03
-.define _int04
-.define _int05
-.define _int06
-.define _int07
-.define _hwint00 ! handlers for hardware interrupts
-.define _hwint01
-.define _hwint02
-.define _hwint03
-.define _hwint04
-.define _hwint05
-.define _hwint06
-.define _hwint07
-.define _hwint08
-.define _hwint09
-.define _hwint10
-.define _hwint11
-.define _hwint12
-.define _hwint13
-.define _hwint14
-.define _hwint15
-.define _restart ! start running a task or process
-.define save ! save the machine state in the proc table
-.define _s_call ! process or task wants to send or receive a message
-
-! Exported variables.
-.define kernel_ds
-.define begbss
-.define begdata
-
- .text
-!*===========================================================================*
-!* MINIX *
-!*===========================================================================*
-MINIX: ! this is the entry point for the MINIX kernel
- jmp over_kernel_ds ! skip over the next few bytes
- .data2 CLICK_SHIFT ! for the monitor: memory granularity
-kernel_ds:
- .data2 0x01B4 ! boot monitor flags: (later kernel DS)
- ! call in 8086 mode, make bss, make stack,
- ! load low, don`t patch, will return,
- ! (has own INT calls), memory vector,
- ! new boot code return
-over_kernel_ds:
-
-! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds
-! right. The ss register still references the monitor data segment.)
- push bp
- mov bp, sp
- push si
- push di
- cmp 4(bp), #0 ! monitor code segment is
- jz noret ! nonzero if return possible
- inc _mon_return
-noret: mov _mon_ss, ss ! save stack location for later return
- mov _mon_sp, sp
-
-! Locate boot parameters, set up kernel segment registers and stack.
- mov bx, 6(bp) ! boot parameters offset
- mov dx, 8(bp) ! boot parameters length
- mov ax, 10(bp) ! address of a.out headers
- mov _aout+0, ax
- mov ax, 12(bp)
- mov _aout+2, ax
- mov ax, ds ! kernel data
- mov es, ax
- mov ss, ax
- mov sp, #k_stktop ! set sp to point to the top of kernel stack
-
-! Real mode needs to get kernel DS from the code segment. Protected mode
-! needs CS in the jump back to real mode.
-
- cseg mov kernel_cs, cs
- cseg mov kernel_ds, ds
-
-! Call C startup code to set up a proper environment to run main().
- push dx
- push bx
- push _mon_ss
- push ds
- push cs
- call _cstart ! cstart(cs, ds, mds, parmoff, parmlen)
- add sp, #5*2
-
- cmp _protected_mode, #0
- jz nosw ! ok to switch to protected mode?
-
- call klib_init_prot ! initialize klib functions for protected mode
- call real2prot ! switch to protected mode
-
- push #0 ! set flags to known good state
- popf ! especially, clear nested task and int enable
-nosw:
- jmp _main ! main()
-
-
-!*===========================================================================*
-!* interrupt handlers *
-!*===========================================================================*
-
-
-!*===========================================================================*
-!* hwint00 - 07 *
-!*===========================================================================*
-! Note that the first few lines are a macro
-#define hwint_master(irq) \
- call save /* save interrupted process state */;\
- mov si, *[2*irq] /* load array index offset */;\
- mov di, *[1<<irq] /* irq mask bit */;\
- jmp hwint_master /* continue with common code */
-hwint_master:
- inb INT_CTLMASK
- or ax, di ! al |= (1 << irq)
- outb INT_CTLMASK ! disable the irq
- movb al, *ENABLE
- outb INT_CTL ! reenable master 8259
- mov cx, _irq_hooks(si) ! irq_hooks[irq]
- push cx
- sti ! enable interrupts
- call _intr_handle ! intr_handle(irq_hooks[irq])
- cli ! disable interrupts
- pop cx
- cmp _irq_actids(si), *0 ! interrupt still active?
- jnz 0f
- inb INT_CTLMASK
- not di
- and ax, di ! al &= ~(1 << irq)
- outb INT_CTLMASK ! enable the irq
-0: ret ! restart (another) process
-
-! Each of these entry points is an expansion of the hwint_master macro
-
-_hwint00: ! Interrupt routine for irq 0 (the clock).
- hwint_master(0)
-
-
-_hwint01: ! Interrupt routine for irq 1 (keyboard)
- hwint_master(1)
-
-
-_hwint02: ! Interrupt routine for irq 2 (cascade!)
- hwint_master(2)
-
-
-_hwint03: ! Interrupt routine for irq 3 (second serial)
- hwint_master(3)
-
-
-_hwint04: ! Interrupt routine for irq 4 (first serial)
- hwint_master(4)
-
-
-_hwint05: ! Interrupt routine for irq 5 (XT winchester)
- hwint_master(5)
-
-
-_hwint06: ! Interrupt routine for irq 6 (floppy)
- hwint_master(6)
-
-
-_hwint07: ! Interrupt routine for irq 7 (printer)
- hwint_master(7)
-
-
-!*===========================================================================*
-!* hwint08 - 15 *
-!*===========================================================================*
-! Note that the first few lines are a macro
-#define hwint_slave(irq) \
- call save /* save interrupted process state */;\
- mov si, *[2*irq] /* load array index offset */;\
- mov di, *[1<<[irq-8]] /* irq mask bit */;\
- jmp hwint_slave /* continue with common code */
-hwint_slave:
- inb INT2_CTLMASK
- or ax, di ! al |= (1 << (irq-8))
- outb INT2_CTLMASK ! disable the irq
- movb al, *ENABLE
- outb INT_CTL ! reenable master 8259
- mov cx, _irq_hooks(si) ! irq_hooks[irq]
- outb INT2_CTL ! reenable slave 8259
- push cx
- sti ! enable interrupts
- call _intr_handle ! intr_handle(irq_hooks[irq])
- cli ! disable interrupts
- pop cx
- cmp _irq_actids(si), *0 ! interrupt still active?
- jnz 0f
- inb INT2_CTLMASK
- not di
- and ax, di ! al &= ~(1 << (irq-8))
- outb INT2_CTLMASK ! enable the irq
-0: ret ! restart (another) process
-
-! Each of these entry points is an expansion of the hwint_slave macro
-
-_hwint08: ! Interrupt routine for irq 8 (realtime clock)
- hwint_slave(8)
-
-
-_hwint09: ! Interrupt routine for irq 9 (irq 2 redirected)
- hwint_slave(9)
-
-
-_hwint10: ! Interrupt routine for irq 10
- hwint_slave(10)
-
-
-_hwint11: ! Interrupt routine for irq 11
- hwint_slave(11)
-
-
-_hwint12: ! Interrupt routine for irq 12
- hwint_slave(12)
-
-
-_hwint13: ! Interrupt routine for irq 13 (FPU exception)
- hwint_slave(13)
-
-
-_hwint14: ! Interrupt routine for irq 14 (AT winchester)
- hwint_slave(14)
-
-
-_hwint15: ! Interrupt routine for irq 15
- hwint_slave(15)
-
-
-!*===========================================================================*
-!* save *
-!*===========================================================================*
-save: ! save the machine state in the proc table.
-
-! In protected mode a jump to p_save is patched over the following
-! code during initialization.
-
- cld ! set direction flag to a known value
- push ds
- push si
- cseg mov ds,kernel_ds
- incb _k_reenter ! from -1 if not reentering
- jnz push_current_stack ! stack is already kernel stack
-
- mov si,_proc_ptr
- mov AXREG(si),ax
- mov BXREG(si),bx
- mov CXREG(si),cx
- mov DXREG(si),dx
- pop SIREG(si)
- mov DIREG(si),di
- mov BPREG(si),bp
- mov ESREG(si),es
- pop DSREG(si)
- pop bx ! return adr
- pop PCREG(si)
- pop CSREG(si)
- pop PSWREG(si)
- mov SPREG(si),sp
- mov SSREG(si),ss
-
- mov dx,ds
- mov ss,dx
- mov sp,#k_stktop
- mov ax,#_restart ! build return address for interrupt handler
- push ax
-
-stack_switched:
- mov es,dx
- jmp (bx)
-
-push_current_stack:
- push es
- push bp
- push di
- push dx
- push cx
- push bx
- push ax
- mov bp,sp
- mov bx,18(bp) ! get the return adr; it becomes junk on stack
- mov ax,#restart1
- push ax
- mov dx,ss
- mov ds,dx
- jmp stack_switched
-
-
-!*===========================================================================*
-!* s_call *
-!*===========================================================================*
-! This is real mode version. Alternate (_p_s_call) will be used in
-! protected mode
-
-_s_call: ! System calls are vectored here.
- ! Do save routine inline for speed,
- ! but do not save ax, bx, cx, dx,
- ! since C does not require preservation,
- ! and ax returns the result code anyway.
- ! Regs bp, si, di get saved by sys_call as
- ! well, but it is impractical not to preserve
- ! them here, in case context gets switched.
- ! Some special-case code in pick_proc()
- ! could avoid this.
- cld ! set direction flag to a known value
- push ds
- push si
- cseg mov ds,kernel_ds
- incb _k_reenter
- mov si,_proc_ptr
- pop SIREG(si)
- mov DIREG(si),di
- mov BPREG(si),bp
- mov ESREG(si),es
- pop DSREG(si)
- pop PCREG(si)
- pop CSREG(si)
- pop PSWREG(si)
- mov SPREG(si),sp
- mov SSREG(si),ss
- mov dx,ds
- mov es,dx
- mov ss,dx ! interrupt handlers may not make system calls
- mov sp,#k_stktop ! so stack is not already switched
- ! end of inline save
- ! now set up parameters for C routine sys_call
- push bx ! pointer to user message
- push ax ! src/dest
- push cx ! SEND/RECEIVE/BOTH
- sti ! allow SWITCHER to be interrupted
- call _sys_call ! sys_call(function, src_dest, m_ptr)
- ! caller is now explicitly in proc_ptr
- mov AXREG(si),ax ! sys_call MUST PRESERVE si
- cli
-
-! Fall into code to restart proc/task running.
-
-
-!*===========================================================================*
-!* restart *
-!*===========================================================================*
-_restart:
-
-! Flush any held-up interrupts.
-! This reenables interrupts, so the current interrupt handler may reenter.
-! This does not matter, because the current handler is about to exit and no
-! other handlers can reenter since flushing is only done when k_reenter == 0.
-
-! In protected mode a jump to p_restart is patched over the following
-! code during initialization.
-
- cmp _held_head,#0 ! do fast test to usually avoid function call
- jz over_call_unhold
- call _unhold ! this is rare so overhead is acceptable
-over_call_unhold:
-
- mov si,_proc_ptr
- decb _k_reenter
- mov ax,AXREG(si) ! start restoring registers from proc table
- ! could make AXREG == 0 to use lodw here
- mov bx,BXREG(si)
- mov cx,CXREG(si)
- mov dx,DXREG(si)
- mov di,DIREG(si)
- mov bp,BPREG(si)
- mov es,ESREG(si)
- mov ss,SSREG(si)
- mov sp,SPREG(si)
- push PSWREG(si) ! fake interrupt stack frame
- push CSREG(si)
- push PCREG(si)
- ! could put si:ds together to use
- ! lds si,SIREG(si)
- push DSREG(si)
- mov si,SIREG(si)
- pop ds
- iret
-
-restart1:
- decb _k_reenter
- pop ax
- pop bx
- pop cx
- pop dx
- pop di
- pop bp
- pop es
- pop si
- pop ds
- add sp,#2 ! skip return adr
- iret
-
-
-!*===========================================================================*
-!* int00-07 *
-!*===========================================================================*
-! These are entry points for exceptions (processor generated interrupts,
-! usually caused by error conditions such as an attempt to divide by zero)
-
-_int00: ! interrupt through vector 0
- push ax
- movb al,#0
- jmp exception
-
-_int01: ! interrupt through vector 1, etc
- push ax
- movb al,#1
- jmp exception
-
-_int02:
- push ax
- movb al,#2
- jmp exception
-
-_int03:
- push ax
- movb al,#3
- jmp exception
-
-_int04:
- push ax
- movb al,#4
- jmp exception
-
-_int05:
- push ax
- movb al,#5
- jmp exception
-
-_int06:
- push ax
- movb al,#6
- jmp exception
-
-_int07:
- push ax
- movb al,#7
- !jmp exception
-
-exception:
- cseg movb ex_number,al ! it is cumbersome to get this into dseg
- pop ax
- call save
- cseg push ex_number ! high byte is constant 0
- call _exception ! do whatever is necessary (sti only if safe)
- add sp,#2
- cli
- ret
-
-
-!*===========================================================================*
-!* level0_call *
-!*===========================================================================*
-_level0_call:
- call save
- jmp @_level0_func
-
-!*===========================================================================*
-!* data *
-!*===========================================================================*
-! NB some variables are stored in code segment.
-
-ex_number: ! exception number
- .space 2
-
-
-!*===========================================================================*
-!* variants for 286 protected mode *
-!*===========================================================================*
-
-! Most routines are different in 286 protected mode.
-! The only essential difference is that an interrupt in protected mode
-! (usually) switches the stack, so there is less to do in software.
-
-! These functions are reached along jumps patched in by klib_init_prot():
-
- .define p_restart ! replaces _restart
- .define p_save ! replaces save
-
-! These exception and software-interrupt handlers are enabled by the new
-! interrupt vector table set up in protect.c:
-
- .define _divide_error ! _int00
- .define _single_step_exception ! _int01
- .define _nmi ! _int02
- .define _breakpoint_exception ! _int03
- .define _overflow ! _int04
- .define _bounds_check ! _int05
- .define _inval_opcode ! _int06
- .define _copr_not_available ! _int07
- .define _double_fault ! (286 trap)
- .define _copr_seg_overrun ! (etc)
- .define _inval_tss
- .define _segment_not_present
- .define _stack_exception
- .define _general_protection
- .define _p_s_call ! _s_call
- .define _level0_call
-
-! The hardware interrupt handlers need not be altered apart from putting
-! them in the new table (save() handles the differences).
-! Some of the intxx handlers (those for exceptions which do not push an
-! error code) need not have been replaced, but the names here are better.
-
-#include "protect.h"
-
-/* Selected 286 tss offsets. */
-#define TSS2_S_SP0 2
-
-! imported variables
-
- .extern _tss
- .extern _level0_func
-
-!*===========================================================================*
-!* p_save *
-!*===========================================================================*
-! Save for 286 protected mode.
-! This is much simpler than for 8086 mode, because the stack already points
-! into process table, or has already been switched to the kernel stack.
-
-p_save:
- cld ! set direction flag to a known value
- pusha ! save "general" registers
- push ds ! save ds
- push es ! save es
- mov dx,ss ! ss is kernel data segment
- mov ds,dx ! load rest of kernel segments
- mov es,dx
- mov bp,sp ! prepare to return
- incb _k_reenter ! from -1 if not reentering
- jnz set_p1_restart ! stack is already kernel stack
- mov sp,#k_stktop
- push #p_restart ! build return address for interrupt handler
- jmp @RETADR-P_STACKBASE(bp)
-
-set_p1_restart:
- push #p1_restart
- jmp @RETADR-P_STACKBASE(bp)
-
-
-!*===========================================================================*
-!* p_s_call *
-!*===========================================================================*
-_p_s_call:
- cld ! set direction flag to a known value
- sub sp,#6*2 ! skip RETADR, ax, cx, dx, bx, st
- push bp ! stack already points into process table
- push si
- push di
- push ds
- push es
- mov dx,ss
- mov ds,dx
- mov es,dx
- incb _k_reenter
- mov si,sp ! assumes P_STACKBASE == 0
- mov sp,#k_stktop
- ! end of inline save
- sti ! allow SWITCHER to be interrupted
- ! now set up parameters for C routine sys_call
- push bx ! pointer to user message
- push ax ! src/dest
- push cx ! SEND/RECEIVE/BOTH
- call _sys_call ! sys_call(function, src_dest, m_ptr)
- ! caller is now explicitly in proc_ptr
- mov AXREG(si),ax ! sys_call MUST PRESERVE si
- cli
-
-! Fall into code to restart proc/task running.
-
-p_restart:
-
-! Flush any held-up interrupts.
-! This reenables interrupts, so the current interrupt handler may reenter.
-! This does not matter, because the current handler is about to exit and no
-! other handlers can reenter since flushing is only done when k_reenter == 0.
-
- cmp _held_head,#0 ! do fast test to usually avoid function call
- jz p_over_call_unhold
- call _unhold ! this is rare so overhead is acceptable
-p_over_call_unhold:
- mov si,_proc_ptr
- lldt P_LDT_SEL(si) ! enable segment descriptors for task
- lea ax,P_STACKTOP(si) ! arrange for next interrupt
- mov _tss+TSS2_S_SP0,ax ! to save state in process table
- mov sp,si ! assumes P_STACKBASE == 0
-p1_restart:
- decb _k_reenter
- pop es
- pop ds
- popa
- add sp,#2 ! skip return adr
- iret ! continue process
-
-
-!*===========================================================================*
-!* exception handlers *
-!*===========================================================================*
-_divide_error:
- push #DIVIDE_VECTOR
- jmp p_exception
-
-_single_step_exception:
- push #DEBUG_VECTOR
- jmp p_exception
-
-_nmi:
- push #NMI_VECTOR
- jmp p_exception
-
-_breakpoint_exception:
- push #BREAKPOINT_VECTOR
- jmp p_exception
-
-_overflow:
- push #OVERFLOW_VECTOR
- jmp p_exception
-
-_bounds_check:
- push #BOUNDS_VECTOR
- jmp p_exception
-
-_inval_opcode:
- push #INVAL_OP_VECTOR
- jmp p_exception
-
-_copr_not_available:
- push #COPROC_NOT_VECTOR
- jmp p_exception
-
-_double_fault:
- push #DOUBLE_FAULT_VECTOR
- jmp errexception
-
-_copr_seg_overrun:
- push #COPROC_SEG_VECTOR
- jmp p_exception
-
-_inval_tss:
- push #INVAL_TSS_VECTOR
- jmp errexception
-
-_segment_not_present:
- push #SEG_NOT_VECTOR
- jmp errexception
-
-_stack_exception:
- push #STACK_FAULT_VECTOR
- jmp errexception
-
-_general_protection:
- push #PROTECTION_VECTOR
- jmp errexception
-
-
-!*===========================================================================*
-!* p_exception *
-!*===========================================================================*
-! This is called for all exceptions which do not push an error code.
-
-p_exception:
- sseg pop ds_ex_number
- call p_save
- jmp p1_exception
-
-
-!*===========================================================================*
-!* errexception *
-!*===========================================================================*
-! This is called for all exceptions which push an error code.
-
-errexception:
- sseg pop ds_ex_number
- sseg pop trap_errno
- call p_save
-p1_exception: ! Common for all exceptions.
- push ds_ex_number
- call _exception
- add sp,#2
- cli
- ret
-
-
-!*===========================================================================*
-!* data *
-!*===========================================================================*
-
- .data
-begdata:
- .data2 0x526F ! this must be the first data entry (magic #)
-
- .bss
-begbss:
-k_stack:
- .space K_STACK_BYTES ! kernel stack
-k_stktop: ! top of kernel stack
- .comm ds_ex_number, 2
- .comm trap_errno, 2
* Oct 10, 2004 require BOTH for kernel sys_call() (Jorrit N. Herder)
* (to protect kernel tasks from being blocked)
* Sep 25, 2004 generalized notify() function (Jorrit N. Herder)
- * Sep 23, 2004 removed MM sig check in mini_rec() (Jorrit N. Herder)
+ * Sep 23, 2004 removed PM sig check in mini_rec() (Jorrit N. Herder)
* Aug 19, 2004 generalized ready()/unready() (Jorrit N. Herder)
* Aug 18, 2004 added notify() function (Jorrit N. Herder)
* May 01, 2004 check p_sendmask in mini_send() (Jorrit N. Herder)
/* Calls directed to the kernel may only be sendrec(), because tasks always
* reply and may not block if the caller doesn't do receive(). Users also
- * may only use sendrec() to protect the MM and FS.
+ * may only use sendrec() to protect the process manager and file system.
*/
if ((iskernel(src_dst) || isuserp(caller_ptr)) && function != BOTH) {
result = ECALLDENIED; /* BOTH was required */
* May 01, 2004 new p_sendmask to protect syscalls (Jorrit N. Herder)
*/
#include <minix/com.h>
+#include "protect.h"
#include "const.h"
struct proc {
#if (CHIP == INTEL)
reg_t p_ldt_sel; /* selector in gdt giving ldt base and limit*/
- struct segdesc_s p_ldt[4]; /* local descriptors for code and data */
- /* 4 is LDT_SIZE - avoid include protect.h */
+ struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */
#endif /* (CHIP == INTEL) */
#if (CHIP == M68000)
#define isalivep(p) ((p)->p_type > P_NONE)
#define isrxhardware(n) ((n) == ANY || (n) == HARDWARE)
#define iskernel(n) ((n) == CLOCK || (n) == SYSTASK)
-#define issysentn(n) ((n) == FS_PROC_NR || (n) == MM_PROC_NR)
+#define issysentn(n) ((n) == FS_PROC_NR || (n) == PM_PROC_NR)
#define issysentp(p) (issysentn((p)->p_nr))
#define isreservedp(p) ((p)->p_type == P_RESERVED)
#define isemptyp(p) ((p)->p_type == P_NONE)
/* Set up tables for protected mode.
* All GDT slots are allocated at compile time.
*/
-
- extern int etext, end;
-#define code_bytes ((vir_bytes) &etext) /* Size of code segment. */
-#define data_bytes ((vir_bytes) &end) /* Size of data segment. */
struct gate_table_s *gtp;
struct desctableptr_s *dtp;
unsigned ldt_index;
* (u32_t *) dtp->base = vir2phys(idt);
/* Build segment descriptors for tasks and interrupt handlers. */
- init_codeseg(&gdt[CS_INDEX], code_base, code_bytes, INTR_PRIVILEGE);
- init_dataseg(&gdt[DS_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
+ init_codeseg(&gdt[CS_INDEX], kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE);
+ init_dataseg(&gdt[DS_INDEX], kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE);
init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE);
/* Build scratch descriptors for functions in klib88. */
phys_bytes base;
struct segdesc_s *segdp;
- if (!protected_mode) {
+ if (! machine.protected) {
base = hclick_to_physb(seg);
} else {
segdp = &gdt[seg >> 3];
* address, for use by a driver doing memory I/O in the A0000 - DFFFF range.
*/
#if _WORD_SIZE == 2
- if (!protected_mode) {
+ if (! machine.protected) {
*seg = phys / HCLICK_SIZE;
*off = phys % HCLICK_SIZE;
} else {
*/
pp->p_reg.psw |= 0x3000;
}
+
+
+/*==========================================================================*
+ * alloc_segments *
+ *==========================================================================*/
+PUBLIC void alloc_segments(rp)
+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.
+ * Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here.
+ */
+ phys_bytes code_bytes;
+ phys_bytes data_bytes;
+ int privilege;
+
+ if (machine.protected) {
+ 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)
+ code_bytes = data_bytes; /* common I&D, poor protect */
+ else
+ code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT;
+ privilege = (isidlep(rp) || istaskp(rp)) ?
+ TASK_PRIVILEGE : USER_PRIVILEGE;
+ init_codeseg(&rp->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],
+ (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);
+ }
+}
+
+
#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 */
-#define LDT_SIZE 4 /* contains CS, DS and two extras */
+#define LDT_SIZE (2 + NR_REMOTE_SEGS) /* CS, DS and remote segments */
/* Fixed global descriptors. 1 to 7 are prescribed by the BIOS. */
#define GDT_INDEX 1 /* GDT descriptor */
_PROTOTYPE( void stop_sequence, (struct timer *tp) );
_PROTOTYPE( void shutdown, (struct timer *tp) );
-/* memory.c */
-_PROTOTYPE( void mem_init, (void) );
-_PROTOTYPE( void alloc_segments, (struct proc *rp) );
-
/* misc.c */
_PROTOTYPE( void panic, (_CONST char *s, int n) );
_PROTOTYPE( void reset, (void) );
_PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) );
+_PROTOTYPE( void read_tsc, (unsigned long *low, unsigned long *high) );
/* mpx*.s */
_PROTOTYPE( void idle_task, (void) );
_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) );
#endif /* (CHIP == INTEL) */
allow_all_mask \
deny(1, USER_PROC_NR)
-#define MM_SENDMASK \
+#define PM_SENDMASK \
deny_all_mask \
allow(1, IS_PROC_NR) /* output diagnostics */ \
allow(1, SYSTASK) \
allow((NR_CTRLRS >= 3), CTRLR(2)) \
allow((NR_CTRLRS >= 4), CTRLR(3)) \
allow(1, INIT_PROC_NR) \
- allow(1, MM_PROC_NR) /* cooperates with memory manager */ \
+ allow(1, PM_PROC_NR) /* cooperates with process manager */ \
allow(1, USER_PROC_NR) /* reply to system calls */
#endif
#define INIT_SENDMASK \
deny_all_mask \
allow(1, FS_PROC_NR) /* init makes system calls to FS and MM */ \
- allow(1, MM_PROC_NR)
+ allow(1, PM_PROC_NR)
#define USER_PROC_SENDMASK \
deny_all_mask \
allow(1, FS_PROC_NR) /* users can only make system calls */ \
- allow(1, MM_PROC_NR) \
+ allow(1, PM_PROC_NR) \
allow(1, IS_PROC_NR) \
allow(ENABLE_TASKSERVER, TS_PROC_NR)
#include "kernel.h"
#include "protect.h"
+#include "proc.h"
/* Environment strings passed by loader. */
PRIVATE char k_environ[128*sizeof(char *)];
+FORWARD _PROTOTYPE( void mem_init, (void) );
/*==========================================================================*
* cstart *
*/
register char *envp;
unsigned mon_start;
+ extern int etext, end;
+
+ /* 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.protected = 1;
+#endif
/* Record where the kernel and the monitor are. */
- code_base = seg2phys(cs);
- data_base = seg2phys(ds);
+ 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();
/* Copy the boot parameters to kernel memory. */
- mon_params = seg2phys(mds) + parmoff;
- mon_parmsize = MAX(parmsize,sizeof(k_environ));
- if (parmsize > sizeof k_environ - 2) parmsize = sizeof k_environ - 2;
- phys_copy(mon_params, vir2phys(k_environ), (phys_bytes) parmsize);
+ kinfo.params_base = seg2phys(mds) + parmoff;
+ kinfo.params_size = MAX(parmsize,sizeof(k_environ)-2);
+ phys_copy(kinfo.params_base, vir2phys(k_environ), kinfo.params_size);
- /* Type of VDU: */
- envp = getkenv("video");
- if (kstrcmp(envp, "ega") == 0) ega = TRUE;
- if (kstrcmp(envp, "vga") == 0) vga = ega = TRUE;
+ /* Record miscellaneous information for user-space servers. */
+ kstrncpy(kinfo.version, OS_RELEASE "." OS_VERSION, 6);
+ kinfo.proc_addr = (vir_bytes) proc;
+ kinfo.kmem_base = vir2phys(0);
+ kinfo.kmem_size = (phys_bytes) &end;
/* Processor? */
- processor = katoi(getkenv("processor")); /* 86, 186, 286, 386, ... */
+ machine.processor=katoi(getkenv("processor")); /* 86, 186, 286, 386, ... */
+
+ /* Decide if mode is protected for older machines. */
+#if _WORD_SIZE == 2
+ machine.protected = machine.processor >= 286;
+#endif
+ if (! machine.protected) mon_return = 0;
/* XT, AT or MCA bus? */
envp = getkenv("bus");
if (envp == NIL_PTR || kstrcmp(envp, "at") == 0) {
- pc_at = TRUE;
- } else
- if (kstrcmp(envp, "mca") == 0) {
- pc_at = ps_mca = TRUE;
+ machine.pc_at = TRUE; /* PC-AT compatible hardware */
+ } else if (kstrcmp(envp, "mca") == 0) {
+ machine.pc_at = machine.ps_mca = TRUE; /* PS/2 with micro channel */
}
- /* Decide if mode is protected. */
+ /* Type of VDU: */
+ envp = getkenv("video"); /* EGA or VGA video unit */
+ if (kstrcmp(envp, "ega") == 0) machine.vdu_ega = TRUE;
+ if (kstrcmp(envp, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
+
+ /* Initialize free memory list from size passed by boot monitor. */
+ mem_init();
+
+ /* Return to assembler code to switch to protected mode (if 286),
+ * reload selectors and call main().
+ */
+}
+
+
+
+/* In real mode only 1M can be addressed, and in 16-bit protected we can go
+ * no further than we can count in clicks. (The 286 is further limited by
+ * its 24 bit address bus, but we can assume in that case that no more than
+ * 16M memory is reported by the BIOS.)
+ */
+#define MAX_REAL 0x00100000L
+#define MAX_16BIT (0xFFF0L << CLICK_SHIFT)
+
+/*=========================================================================*
+ * mem_init *
+ *=========================================================================*/
+PRIVATE void mem_init()
+{
+/* Initialize the free memory list from the 'memory' boot variable. Translate
+ * the byte offsets and sizes in this list to clicks, properly truncated. Also
+ * make sure that we don't exceed the maximum address space of the 286 or the
+ * 8086, i.e. when running in 16-bit protected mode or real mode.
+ */
+ long base, size, limit;
+ char *s, *end; /* use to parse boot variable */
+ int i;
+ struct memory *memp;
#if _WORD_SIZE == 2
- protected_mode = processor >= 286;
- if (!protected_mode) mon_return = 0;
+ unsigned long max_address;
#endif
- /* Return to assembler code to switch to protected mode (if 286), reload
- * selectors and call main().
+ /* The available memory is determined by MINIX' boot loader as a list of
+ * (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
+ * in boot.s. The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
+ * b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1
+ * and b2:s2 are combined if the memory is adjacent.
*/
+ s = getkenv("memory"); /* get memory boot variable */
+ for (i = 0; i < NR_MEMS; i++) {
+ memp = &mem[i]; /* result is stored here */
+ base = size = 0;
+ if (*s != 0) { /* end of boot variable */
+ /* Expect base to be read (end != s) and ':' as next char. */
+ base = kstrtoul(s, &end, 0x10); /* get number */
+ if (end != s && *end == ':') s = ++end; /* skip ':' */
+ else *s=0; /* fake end for next; should not happen */
+ /* Expect size to be read and skip ',', unless at end. */
+ size = kstrtoul(s, &end, 0x10); /* get number */
+ if (end != s && *end == ',') s = ++end; /* skip ',' */
+ else if (end != s && *end == 0) s = end; /* end found */
+ else *s=0; /* fake end for next; should not happen */
+ }
+ limit = base + size;
+#if _WORD_SIZE == 2
+ max_address = kinfo.protected ? MAX_16BIT : MAX_REAL;
+ if (limit > max_address) limit = max_address;
+#endif
+ base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
+ limit &= ~(long)(CLICK_SIZE-1);
+ if (limit <= base) continue;
+ memp->base = base >> CLICK_SHIFT;
+ memp->size = (limit - base) >> CLICK_SHIFT;
+ }
}
* umap_bios: map virtual address in BIOS_SEG to physical
* numap_local: umap_local D segment from proc nr instead of pointer
* virtual_copy: copy bytes from one virtual address to another
- * vir_copy: copy bytes from one process to another
* generic_handler: interrupt handler for user-level device drivers
*
* Changes:
+ * Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder)
* Oct 29, 2004 new clear_proc() function (Jorrit N. Herder)
* Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder)
* Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
* Sep 10, 2004 system call functions in library (Jorrit N. Herder)
- * 2003/2004 various new syscalls (see syslib.h) (Jorrit N. Herder)
+ * 2004 to 2005 various new syscalls (see syslib.h) (Jorrit N. Herder)
*/
#include "kernel.h"
#include <minix/callnr.h>
#include "sendmask.h"
#if (CHIP == INTEL)
+#include <ibm/memory.h>
#include "protect.h"
#endif
-FORWARD _PROTOTYPE( void initialize, (void));
-
-/* Declaration of the call vector that defines the mapping of system calls to
- * handler functions. The order of the do_call handler functions must match
- * the SYS_CALL numbering defined in <minix/com.h>.
- */
-PUBLIC _PROTOTYPE (int (*call_vec[]), (message *m_ptr) ) = {
- do_times, /* 0: get uptime and process CPU time consumption */
- do_xit, /* 1: informs kernel that a process has exited */
- do_unused, /* 2: unused */
- do_sigctl, /* 3: MM signal control (incl. POSIX style handling) */
- do_fork, /* 4: informs kernel that a process has forked */
- do_newmap, /* 5: allows MM to set up a process memory map */
- do_copy, /* 6: copy a block of data between processes */
- do_exec, /* 7: sets program counter and stack pointer after EXEC */
- do_unused, /* 8: unused */
- do_abort, /* 9: MM or FS cannot go on; abort MINIX */
- do_kill, /* 10: cause a signal to be sent via MM */
- do_umap, /* 11: compute the physical address for a virtual address */
- do_unused, /* 12: returns the next free chunk of physical memory */
- do_trace, /* 13: request a trace operation */
- do_vcopy, /* 14: request a series of data blocks to be copied */
- do_signalrm, /* 15: schedule an alarm that causes an alarm signal */
- do_syncalrm, /* 16: schedule an alarm that sends a notification message */
- do_flagalrm, /* 17: schedule an alarm that sets a timeout flag to 1 */
- do_unused, /* 18: unused */
- do_svrctl, /* 19: handles miscelleneous kernel control functions */
- do_sdevio, /* 20: device I/O: phys_insb, _insw, _outsb, _outsw */
- do_unused, /* 21: unused */
- do_getinfo, /* 22: request some kind of system information */
- do_devio, /* 23: device I/O: inb, inw, inl, outb, outw, outl */
- do_vdevio, /* 24: device I/O: vector with in[b|w|l], out[b|w|l] */
- do_irqctl, /* 25: request an interrupt control operation */
- do_kmalloc, /* 26: request allocation of (DMA) buffer in mem chunk */
- do_iopenable, /* 27: allow a user process to use I/O instructions */
- do_phys2seg, /* 28: do a phys addr to segment selector/ offset conversion */
- do_exit, /* 29: an server or driver requests to be aborted */
- do_vircopy, /* 30: copy from process to process (virtual addressing) */
- do_physcopy, /* 31: copy from anywhere to anywhere (physical addressing) */
-};
-
-/* Check if system call table is correct. This should not fail. No space is
- * allocated here, because the dummy is declared extern. If the call vector
- * is unbalanced, the array size will be negative and this won't compile.
+/* Declaration of the call vector that defines the mapping of system calls
+ * to handler functions. The vector is initialized in sys_init() with map(),
+ * which makes sure the system call numbers are ok. No space is allocated,
+ * because the dummy is declared extern. If an illegal call is given, the
+ * array size will be negative and this won't compile.
*/
-extern int dummy[sizeof(call_vec)==NR_SYS_CALLS*sizeof(call_vec[0]) ? 1 : -1];
+PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr);
-/* Some system task variables. */
-PRIVATE message m; /* used to receive requests */
+#define map(call_nr, handler) \
+ {extern int dummy[NR_SYS_CALLS > (unsigned) (call_nr) ? 1 : -1];} \
+ call_vec[(call_nr)] = (handler)
+
+FORWARD _PROTOTYPE( void initialize, (void));
/*===========================================================================*
PUBLIC void sys_task()
{
/* Main entry point of sys_task. Get the message and dispatch on type. */
-
+ static message m;
register int result;
/* Initialize the system task. */
tmr_inittimer(&(rp->p_syncalrm));
tmr_inittimer(&(rp->p_flagalrm));
}
+
+ /* Initialize the call vector to a safe default handler. Some system calls
+ * may be disabled or nonexistant. Then explicitely map known calls to their
+ * handler functions. This is done with a macro that gives a compile error
+ * if an illegal call number is used. The ordering is not important here.
+ */
+ for (i=0; i<NR_SYS_CALLS; i++) {
+ call_vec[i] = do_unused;
+ }
+
+ /* Process management. */
+ map(SYS_FORK, do_fork); /* informs kernel that a process has forked */
+ map(SYS_XIT, do_xit); /* informs kernel that a process has exited */
+ map(SYS_NEWMAP, do_newmap); /* allows PM to set up a process memory map */
+ map(SYS_EXEC, do_exec); /* sets program counter and stack pointer after EXEC */
+ map(SYS_TRACE, do_trace); /* request a trace operation */
+
+ /* Signal handling. */
+ map(SYS_KILL, do_kill); /* cause a process to be signaled */
+ map(SYS_GETSIG, do_getsig); /* PM checks for pending signals */
+ map(SYS_ENDSIG, do_endsig); /* PM finished processing signal */
+ map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */
+ map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */
+
+ /* Clock functionality. */
+ map(SYS_TIMES, do_times); /* get uptime and process times */
+ map(SYS_SIGNALRM, do_signalrm); /* causes an alarm signal */
+ map(SYS_SYNCALRM, do_syncalrm); /* send a notification message */
+ map(SYS_FLAGALRM, do_flagalrm); /* set a timeout flag to 1 */
+
+ /* 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 */
+
+ /* Server and driver control. */
+ map(SYS_KMALLOC, do_kmalloc); /* request chunk of free memory */
+ map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
+ map(SYS_IOPENABLE, do_iopenable); /* enable CPU I/O protection bits */
+ map(SYS_SVRCTL, do_svrctl); /* kernel control functions */
+ map(SYS_EXIT, do_exit); /* exit a system process*/
+
+ /* Copying. */
+ map(SYS_UMAP, do_umap); /* map virtual to physical address */
+ map(SYS_VIRCOPY, do_vircopy); /* use virtual addressing */
+ map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */
+ map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */
+
+ /* Miscellaneous. */
+ map(SYS_ABORT, do_abort); /* abort MINIX */
+ map(SYS_GETINFO, do_getinfo); /* request system information */
+ map(SYS_RANDOM, do_random); /* request kernel random data */
}
/*===========================================================================*
PUBLIC int generic_handler(hook)
irq_hook_t *hook;
{
+/* This function handles hardware interrupt in a simpel and generic way. All
+ * interrupts are transformed into messages to a driver. The IRQ line will be
+ * reenabled if the policy says so.
+ */
+ irq_policy_t policy = irqtab[hook->irq].policy;
+ int proc_nr = irqtab[hook->irq].proc_nr;
+
+#if DEAD_CODE
/* This function handles hardware interrupt in a generic way, according to
* the policy set with SYS_IRQCTL. This is rather complicated since different
* devices require different actions. Options are (1) do nothing, (2a) read a
* read, or (3) write a value to a port. Finally, the policy may or may not
* reenable IRQs. A notification is sent in all cases.
*/
- irq_policy_t policy = irqtab[hook->irq].policy;
- int proc_nr = irqtab[hook->irq].proc_nr;
long port = irqtab[hook->irq].port;
phys_bytes addr = irqtab[hook->irq].addr;
long mask_val = irqtab[hook->irq].mask_val;
default: /* do nothing */ ; /* wrong type flags */
}
}
+#endif /* DEAD_CODE */
/* Almost done, send a HARD_INT notification to allow further processing
* and possibly reenable interrupts - this depends on the policy given.
* TTY wanting to cause SIGINT upon getting a DEL
* CLOCK wanting to cause SIGALRM when timer expires
* FS also uses this to send a signal, via the SYS_KILL message. Signals are
- * handled by sending a message to MM. This central function handles the
- * signals and makes sure the MM gets them by sending a notification. The
- * process being signaled is blocked while MM has not finished all signals
+ * handled by sending a message to PM. This central function handles the
+ * signals and makes sure the PM gets them by sending a notification. The
+ * process being signaled is blocked while PM has not finished all signals
* for it. These signals are counted in p_pendcount, and the SIG_PENDING
* flag is kept nonzero while there are some. It is not sufficient to ready
- * the process when MM is informed, because MM can block waiting for FS to
+ * the process when PM is informed, because PM can block waiting for FS to
* do a core dump.
*/
register struct proc *rp, *mmp;
return; /* another signal already pending */
if (rp->p_flags == 0) lock_unready(rp);
rp->p_flags |= PENDING | SIG_PENDING;
- notify(MM_PROC_NR, KSIG_PENDING);
+ notify(PM_PROC_NR, KSIG_PENDING);
}
vir_bytes vir_addr; /* virtual address in BIOS segment */
vir_bytes bytes; /* # of bytes to be copied */
{
-/* Calculate the physical memory address at the BIOS. */
+/* Calculate the physical memory address at the BIOS. Note: currently, BIOS
+ * 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.
+ */
phys_bytes phys_addr;
- phys_addr = (phys_bytes) vir_addr; /* no check currently! */
+ /* Check all acceptable ranges. */
+ if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= BIOS_MEM_END)
+ return (phys_bytes) vir_addr;
+ else if (vir_addr >= UPPER_MEM_BEGIN && vir_addr + bytes <= UPPER_MEM_END)
+ return (phys_bytes) vir_addr;
- return phys_addr;
+ kprintf("Warning, error in umap_bios, virtual address 0x%x\n", vir_addr);
+ return 0;
}
/*===========================================================================*
vir_bytes bytes; /* # of bytes to be copied */
{
/* Calculate the physical memory address for a given virtual address. */
- phys_bytes phys_addr;
+ struct far_mem *fm;
- phys_addr = (phys_bytes) 0; /* no yet supported currently! */
+ if (bytes <= 0) return( (phys_bytes) 0);
+ if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0);
- return phys_addr;
+ fm = &rp->p_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);
}
/*==========================================================================*
vir_bytes bytes; /* # of bytes to copy */
{
/* Copy bytes from virtual address src_addr to virtual address dst_addr.
- * Virtual addresses can be in LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
+ * Virtual addresses can be in ABS, LOCAL_SEG, REMOTE_SEG, or BIOS_SEG.
*/
struct vir_addr *vir_addr[2]; /* virtual source and destination address */
phys_bytes phys_addr[2]; /* absolute source and destination */
phys_addr[i] = umap_bios( proc_addr(vir_addr[i]->proc_nr),
vir_addr[i]->offset, bytes );
break;
+ case PHYS_SEG:
+ phys_addr[i] = vir_addr[i]->offset;
+ break;
default:
kprintf("v_cp: Unknown segment type: %d\n",
vir_addr[i]->segment & SEGMENT_TYPE);
}
/* Check if mapping succeeded. */
- if (phys_addr[i] <= 0) {
+ if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) {
kprintf("v_cp: Mapping failed ... phys <= 0\n", NO_ARG);
return(EFAULT);
}
_PROTOTYPE( int do_newmap, (message *m_ptr) );
_PROTOTYPE( int do_xit, (message *m_ptr) );
-_PROTOTYPE( int do_vircopy, (message *m_ptr) ); /* copying */
-_PROTOTYPE( int do_physcopy, (message *m_ptr) );
+_PROTOTYPE( int do_copy, (message *m_ptr) ); /* copying */
+#define do_vircopy do_copy
+#define do_physcopy do_copy
+_PROTOTYPE( int do_vcopy, (message *m_ptr) );
+#define do_virvcopy do_vcopy
_PROTOTYPE( int do_umap, (message *m_ptr) );
-_PROTOTYPE( int do_vcopy, (message *m_ptr) );
-_PROTOTYPE( int do_copy, (message *m_ptr) );
_PROTOTYPE( int do_unused, (message *m_ptr) ); /* miscellaneous */
_PROTOTYPE( int do_abort, (message *m_ptr) );
-_PROTOTYPE( int do_times, (message *m_ptr) );
_PROTOTYPE( int do_getinfo, (message *m_ptr) );
+_PROTOTYPE( int do_random, (message *m_ptr) );
_PROTOTYPE( int do_exit, (message *m_ptr) ); /* server control */
_PROTOTYPE( int do_svrctl, (message *m_ptr) );
_PROTOTYPE( int do_kmalloc, (message *m_ptr) );
_PROTOTYPE( int do_iopenable, (message *m_ptr) );
-_PROTOTYPE( int do_phys2seg, (message *m_ptr) );
+_PROTOTYPE( int do_segctl, (message *m_ptr) );
_PROTOTYPE( int do_devio, (message *m_ptr) ); /* device I/O */
_PROTOTYPE( int do_vdevio, (message *m_ptr) );
_PROTOTYPE( int do_irqctl, (message *m_ptr) ); /* interrupt control */
_PROTOTYPE( int do_kill, (message *m_ptr) ); /* signal handling */
-_PROTOTYPE( int do_sigctl, (message *m_ptr) );
+_PROTOTYPE( int do_getsig, (message *m_ptr) );
+_PROTOTYPE( int do_endsig, (message *m_ptr) );
+_PROTOTYPE( int do_sigsend, (message *m_ptr) );
+_PROTOTYPE( int do_sigreturn, (message *m_ptr) );
-_PROTOTYPE( int do_setalarm, (message *m_ptr) ); /* alarm functions */
+_PROTOTYPE( int do_times, (message *m_ptr) ); /* clock functions */
+_PROTOTYPE( int do_setalarm, (message *m_ptr) );
#define do_flagalrm do_setalarm
#define do_signalrm do_setalarm
#define do_syncalrm do_setalarm
#endif
#if ENABLE_K_DEBUGGING /* debugging */
+#error Kernel debugging routines are not implemented.
#else
#endif
LDFLAGS = -i
SYS = alarms.o copying.o debugging.o devio.o irqctl.o proctl.o \
- srvrctl.o misc.o sigctl.o tracing.o \
- do_copy.o do_vcopy.o
+ sysctl.o misc.o sigctl.o tracing.o \
# What to make.
all build: $(SYS)
misc.o: $a $b $i/unistd.h
proctl.o: $a $b $k/sendmask.h $k/protect.h $i/signal.h
sigctl.o: $a $b $i/signal.h $s/sigcontext.h
-srvrctl.o: $a $b $s/svrctl.h $k/sendmask.h
+sysctl.o: $a $b $s/svrctl.h $k/sendmask.h
tracing.o: $a $b $s/ptrace.h
-do_copy.o: $a $b
-do_vcopy.o: $a $b
-
/* The system call implemented in this file:
- * m_type: SYS_VIRCOPY
+ * m_type: SYS_VIRCOPY, SYS_PHYSCOPY
*
* The parameters for this system call are:
* m5_c1: CP_SRC_SPACE
#include "../kernel.h"
#include "../system.h"
+#include <minix/type.h>
/*===========================================================================*
- * do_vircopy *
+ * do_copy *
*===========================================================================*/
-PUBLIC int do_vircopy(m_ptr)
+PUBLIC int do_copy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
-/* Handle sys_vircopy(). Copy data by using virtual addressing. */
+/* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or
+ * physical addressing.
+ */
struct vir_addr vir_addr[2]; /* virtual source and destination address */
vir_bytes bytes; /* number of bytes to copy */
int i;
/* Check if process number was given implictly with SELF and is valid. */
if (vir_addr[i].proc_nr == SELF) vir_addr[i].proc_nr = m_ptr->m_source;
- if (! isokprocn(vir_addr[i].proc_nr)) {
- kprintf("do_vircopy: illegal proc nr\n",NO_ARG);
+ if (! isokprocn(vir_addr[i].proc_nr) && vir_addr[i].segment != PHYS_SEG) {
+ kprintf("do_vircopy: illegal proc nr, while not phys addr\n",NO_ARG);
return(EINVAL);
}
- /* Copying from or to special segments can only done by the owner. */
- if ((vir_addr[i].segment & SEGMENT_TYPE) != LOCAL_SEG &&
- vir_addr[i].proc_nr != m_ptr->m_source) {
- kprintf("do_vircopy: special seg permission denied\n", NO_ARG);
- return(EPERM);
- }
+ /* Check if physical addressing is used without SYS_PHYSCOPY. */
+ if ((vir_addr[i].segment & SEGMENT_TYPE) == PHYS_SEG &&
+ m_ptr->m_type != SYS_PHYSCOPY) return(EPERM);
}
/* Check for overflow. This would happen for 64K segments and 16-bit
- * vir_bytes. Especially copying by the MM on do_fork() is affected.
+ * vir_bytes. Especially copying by the PM on do_fork() is affected.
*/
if (bytes != (vir_bytes) bytes) {
kprintf("do_vircopy: overflow\n", NO_ARG);
}
-/* The system call implemented in this file:
- * m_type: SYS_PHYSCOPY
- *
- * The parameters for this system call are:
- * m5_l1: CP_SRC_ADDR (physical source address)
- * m5_l2: CP_DST_ADDR (physical destination address)
- * m5_l3: CP_NR_BYTES (number of bytes to copy)
- *
- * Author:
- * Jorrit N. Herder <jnherder@cs.vu.nl>
- */
+/* Buffer to hold copy request vector from user. */
+PRIVATE struct vir_cp_req vir_cp_req[VCOPY_VEC_SIZE];
/*===========================================================================*
- * do_physcopy *
+ * do_vcopy *
*===========================================================================*/
-PUBLIC int do_physcopy(m_ptr)
+PUBLIC int do_vcopy(m_ptr)
register message *m_ptr; /* pointer to request message */
{
-/* Handle sys_physcopy(). Copy data by using physical addressing. */
-
- phys_bytes src_phys, dst_phys, bytes;
-
- /* Dismember the command message. */
- src_phys = (phys_bytes) m_ptr->CP_SRC_ADDR;
- dst_phys = (phys_bytes) m_ptr->CP_DST_ADDR;
- bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
-
- /* Do some checks and copy the data. */
- if (src_phys == 0 || dst_phys == 0) return(EFAULT);
- phys_copy(src_phys, dst_phys, bytes);
- return(OK);
+/* Handle sys_virvcopy(). Handle virtual copy requests from vector. */
+ int nr_req;
+ int caller_pid;
+ vir_bytes caller_vir;
+ phys_bytes caller_phys;
+ phys_bytes kernel_phys;
+ phys_bytes bytes;
+ int i,s;
+
+ /* Check if request vector size is ok. */
+ nr_req = (unsigned) m_ptr->VCP_VEC_SIZE;
+ if (nr_req > VCOPY_VEC_SIZE) return(EINVAL);
+ bytes = nr_req * sizeof(struct vir_cp_req);
+
+ /* Calculate physical addresses and copy (port,value)-pairs from user. */
+ caller_pid = (int) m_ptr->m_source;
+ caller_vir = (vir_bytes) m_ptr->VCP_VEC_ADDR;
+ caller_phys = umap_local(proc_addr(caller_pid), D, caller_vir, bytes);
+ if (0 == caller_phys) return(EFAULT);
+ kernel_phys = vir2phys(vir_cp_req);
+ phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
+
+ /* Assume vector with requests is correct. Try to copy everything. */
+ for (i=0; i<nr_req; i++) {
+ s = virtual_copy(&vir_cp_req[i].src, &vir_cp_req[i].dst,
+ vir_cp_req[i].count);
+ if (s != OK) break;
+ }
+ return(s);
}
+++ /dev/null
-/* The system call implemented in this file:
- * m_type: SYS_COPY
- *
- * The parameters for this system call are:
- * m5_c1: CP_SRC_SPACE
- * m5_i1: CP_SRC_PROC_NR
- * m5_l1: CP_SRC_ADDR
- * m5_c2: CP_DST_SPACE
- * m5_i2: CP_DST_PROC_NR
- * m5_l2: CP_DST_ADDR
- * m5_l3: CP_NR_BYTES
- */
-
-#include "../kernel.h"
-#include "../system.h"
-
-/*===========================================================================*
- * do_copy *
- *===========================================================================*/
-PUBLIC int do_copy(m_ptr)
-register message *m_ptr; /* pointer to request message */
-{
-/* Handle sys_copy(). Copy data by using virtual or physical addressing. */
-
- int src_proc, dst_proc, src_space, dst_space;
- vir_bytes src_vir, dst_vir;
- phys_bytes src_phys, dst_phys, bytes;
-
- /* Dismember the command message. */
- src_proc = m_ptr->CP_SRC_PROC_NR;
- dst_proc = m_ptr->CP_DST_PROC_NR;
- src_space = m_ptr->CP_SRC_SPACE;
- dst_space = m_ptr->CP_DST_SPACE;
- src_vir = (vir_bytes) m_ptr->CP_SRC_ADDR;
- dst_vir = (vir_bytes) m_ptr->CP_DST_ADDR;
- bytes = (phys_bytes) m_ptr->CP_NR_BYTES;
-
- /* Check if process number was given implicitly with SELF. */
- if (src_proc == SELF) src_proc = m_ptr->m_source;
- if (dst_proc == SELF) dst_proc = m_ptr->m_source;
-
- /* Compute the source and destination addresses and do the copy. */
- if (src_proc == ABS) {
- src_phys = (phys_bytes) m_ptr->CP_SRC_ADDR;
- } else {
- if (bytes != (vir_bytes) bytes) {
- /* This would happen for 64K segments and 16-bit vir_bytes.
- * It would happen a lot for do_fork except MM uses ABS
- * copies for that case.
- */
- panic("overflow in count in do_copy", NO_NUM);
- }
- src_phys = umap_local(proc_addr(src_proc), src_space, src_vir,
- (vir_bytes) bytes);
- }
-
- if (dst_proc == ABS) {
- dst_phys = (phys_bytes) m_ptr->CP_DST_ADDR;
- } else {
- dst_phys = umap_local(proc_addr(dst_proc), dst_space, dst_vir,
- (vir_bytes) bytes);
- }
-
- if (src_phys == 0 || dst_phys == 0) return(EFAULT);
- phys_copy(src_phys, dst_phys, bytes);
- return(OK);
-}
-
-
+++ /dev/null
-/* The system call implemented in this file:
- * m_type: SYS_VCOPY
- *
- * The parameters for this system call are:
- * m1_i1: VCP_SRC_PROC (source process number)
- * m1_i2: VCP_DST_PROC (destination process number)
- * m1_i3: VCP_VEC_SIZE (vector size)
- * m1_p1: VCP_VEC_ADDR (pointer to vector)
- *
- * Author:
- * Jorrit N. Herder <jnherder@cs.vu.nl>
- */
-
-#include "../kernel.h"
-#include "../system.h"
-
-/*===========================================================================*
- * do_vcopy *
- *===========================================================================*/
-PUBLIC int do_vcopy(m_ptr)
-register message *m_ptr; /* pointer to request message */
-{
-/* Handle sys_vcopy(). Copy multiple blocks of memory */
-
- int src_proc, dst_proc, vect_s, i;
- vir_bytes src_vir, dst_vir, vect_addr;
- phys_bytes src_phys, dst_phys, bytes;
- cpvec_t cpvec_table[CPVEC_NR];
-
- /* Dismember the command message. */
- src_proc = m_ptr->VCP_SRC_PROC;
- dst_proc = m_ptr->VCP_DST_PROC;
- vect_s = m_ptr->VCP_VEC_SIZE;
- vect_addr = (vir_bytes)m_ptr->VCP_VEC_ADDR;
-
- if (vect_s > CPVEC_NR) return EDOM;
-
- src_phys= numap_local(m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
- if (!src_phys) return EFAULT;
- phys_copy(src_phys, vir2phys(cpvec_table),
- (phys_bytes) (vect_s * sizeof(cpvec_t)));
-
- for (i = 0; i < vect_s; i++) {
- src_vir= cpvec_table[i].cpv_src;
- dst_vir= cpvec_table[i].cpv_dst;
- bytes= cpvec_table[i].cpv_size;
- src_phys = numap_local(src_proc,src_vir,(vir_bytes)bytes);
- dst_phys = numap_local(dst_proc,dst_vir,(vir_bytes)bytes);
- if (src_phys == 0 || dst_phys == 0) return(EFAULT);
- phys_copy(src_phys, dst_phys, bytes);
- }
- return(OK);
-}
-
-
/* Dismember the request message. */
int irq = m_ptr->IRQ_VECTOR; /* which IRQ vector */
int policy = m_ptr->IRQ_POLICY; /* policy field with flags */
+ int proc_nr = m_ptr->IRQ_PROC_NR; /* process number to forward to */
+#if DEAD_CODE
long port = m_ptr->IRQ_PORT; /* port to read or write */
vir_bytes vir_addr = m_ptr->IRQ_VIR_ADDR; /* address at caller */
phys_bytes phys_addr = 0; /* calculate physical address */
long mask_val = m_ptr->IRQ_MASK_VAL; /* mask or value to be written */
- int proc_nr = m_ptr->IRQ_PROC_NR; /* process number to forward to */
+#endif
/* Check if IRQ line is acceptable. */
if ((unsigned) irq >= NR_IRQ_VECTORS) {
kprintf("ST: notify: invalid proc_nr: %d\n", proc_nr);
return(EINVAL);
}
+#if DEAD_CODE
if (policy & IRQ_READ_PORT) { /* get phys_addr at caller */
switch(policy & (IRQ_BYTE|IRQ_WORD|IRQ_LONG)) {
case IRQ_BYTE: phys_addr=numap_local(proc_nr,vir_addr,sizeof( u8_t));
}
if (phys_addr==0) return(EFAULT); /* invalid address */
}
+#endif
/* Arguments seem to be OK, register them in the IRQ table. */
irqtab[irq].policy = policy; /* policy for interrupts */
irqtab[irq].proc_nr = proc_nr; /* process number to notify */
+#if DEAD_CODE
irqtab[irq].port = port; /* port to read or write */
irqtab[irq].addr = phys_addr; /* address to store status */
irqtab[irq].mask_val = mask_val; /* strobe mask or value */
+#endif
put_irq_handler(&irqtab[irq].hook, irq, generic_handler);
}
break;
}
+/*===========================================================================*
+ * do_random *
+ *===========================================================================*/
+PUBLIC int do_random(m)
+message *m; /* pointer to request message */
+{
+ return(ENOSYS); /* no yet implemented */
+}
+
+
/* The system call implemented in this file:
* m_type: SYS_ABORT
*
message *m_ptr; /* pointer to request message */
{
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
- * MM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
+ * PM (normal abort or panic) or FS (panic), or TTY (a CTRL-ALT-DEL or ESC
* after debugging dumps).
*/
register struct proc *rp;
if (how == RBT_MONITOR) {
/* The monitor is to run user specified instructions. */
len = m_ptr->ABRT_MON_LEN + 1;
- assert(len <= mon_parmsize);
+ assert(len <= kinfo.params_size);
src_phys = numap_local(m_ptr->ABRT_MON_PROC,
(vir_bytes) m_ptr->ABRT_MON_ADDR, len);
assert(src_phys != 0);
- phys_copy(src_phys, mon_params, (phys_bytes) len);
+ phys_copy(src_phys, kinfo.params_base, (phys_bytes) len);
}
prepare_shutdown(how);
return(OK); /* pro-forma (really EDISASTER) */
/* Set source address and length based on request type. */
switch (m_ptr->I_REQUEST) {
- case GET_KENVIRON: {
- struct kenviron kenv;
- extern int end;
-
- kenv.pc_at = pc_at; kenv.ps_mca = ps_mca;
- kenv.processor = processor; kenv.protected = protected_mode;
- kenv.ega = ega; kenv.vga = vga;
-
- kenv.proc_addr = (vir_bytes) proc;
- kenv.params_base = mon_params;
- kenv.params_size = mon_parmsize;
- kenv.kmem_base = vir2phys(0);
- kenv.kmem_size = vir2phys(&end) - vir2phys(0) + 1;
- kenv.bootfs_base = proc_addr(MEMORY)->p_farmem[0].mem_phys;
- kenv.bootfs_size = proc_addr(MEMORY)->p_farmem[0].mem_len;
- length = sizeof(struct kenviron);
- src_phys = vir2phys(&kenv);
+ case GET_MACHINE: {
+ length = sizeof(struct machine);
+ src_phys = vir2phys(&machine);
+ break;
+ }
+ case GET_KINFO: {
+ length = sizeof(struct kinfo);
+ src_phys = vir2phys(&kinfo);
break;
}
case GET_IMAGE: {
break;
}
case GET_MONPARAMS: {
- src_phys = mon_params; /* already is a physical address! */
- length = mon_parmsize;
+ src_phys = kinfo.params_base; /* already is a physical address! */
+ length = kinfo.params_size;
break;
}
case GET_PROCNR: {
- length = sizeof(int);
if (m_ptr->I_KEY_LEN == 0) { /* get own process nr */
+#if DEAD_CODE
+ /* GET_PROCNR functionality will be moved to the Process Manager! */
kprintf("GET_PROCNR (own) from %d\n", m_ptr->m_source);
+#endif
src_phys = vir2phys(&proc_nr);
+ length = sizeof(int);
} else { /* lookup nr by name */
int proc_found = FALSE;
struct proc *pp;
char key[8]; /* storage for process name to lookup */
- kprintf("GET_PROCNR (others) from %d\n", m_ptr->m_source);
+#if DEAD_CODE
+ /* GET_PROCNR functionality will be moved to the Process Manager! */
+ kprintf("GET_PROCNR (by name) from %d\n", m_ptr->m_source);
+#endif
proc_nr = m_ptr->m_source; /* only caller can request copy */
if (m_ptr->I_KEY_LEN > sizeof(key)) return(EINVAL);
if (vir_copy(proc_nr, (vir_bytes) m_ptr->I_KEY_PTR, SYSTASK,
for (pp=BEG_PROC_ADDR; pp<END_PROC_ADDR; pp++) {
if (kstrncmp(pp->p_name, key, m_ptr->I_KEY_LEN) == 0) {
src_phys = vir2phys(&(pp->p_nr));
+ length = sizeof(int);
proc_found = TRUE;
break;
}
* The parameters for this system call are:
* m1_i1: PR_PROC_NR (child's process table slot)
* m1_i2: PR_PPROC_NR (parent, process that forked)
- * m1_i3: PR_PID (child pid received from MM)
+ * m1_i3: PR_PID (child pid received from PM)
*/
#include "../kernel.h"
PUBLIC int do_newmap(m_ptr)
message *m_ptr; /* pointer to request message */
{
-/* Handle sys_newmap(). Fetch the memory map from MM. */
+/* Handle sys_newmap(). Fetch the memory map from PM. */
register struct proc *rp;
phys_bytes src_phys;
- int caller; /* whose space has the new map (usually MM) */
+ int caller; /* whose space has the new map (usually PM) */
int k; /* process whose map is to be loaded */
int old_flags; /* value of flags before modification */
- struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
+ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */
- /* Extract message parameters and copy new memory map from MM. */
+ /* Extract message parameters and copy new memory map from PM. */
caller = m_ptr->m_source;
k = m_ptr->PR_PROC_NR;
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
if (!isokprocn(k)) return(EINVAL);
rp = proc_addr(k); /* ptr to entry of user getting new map */
- /* Copy the map from MM. */
+ /* Copy the map from PM. */
src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr,
sizeof(rp->p_memmap));
assert(src_phys != 0);
(LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0]));
#endif
rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */
- rp->p_flags &= ~RECEIVING; /* MM does not reply to EXEC call */
+ rp->p_flags &= ~RECEIVING; /* PM does not reply to EXEC call */
if (rp->p_flags == 0) lock_ready(rp);
/* Save command name for debugging, ps(1) output, etc. */
PUBLIC int do_xit(m_ptr)
message *m_ptr; /* pointer to request message */
{
-/* Handle sys_exit. A user process has exited (the MM sent the request).
+/* Handle sys_exit. A user process has exited (the PM sent the request).
*/
register struct proc *rp, *rc;
struct proc *np, *xp;
if (! isokprocn(exit_proc_nr)) return(EINVAL);
rc = proc_addr(exit_proc_nr);
- /* If this is a user process and the MM passed in a valid parent process,
+ /* If this is a user process and the PM passed in a valid parent process,
* accumulate the child times at the parent.
*/
if (isuserp(rc) && isokprocn(m_ptr->PR_PPROC_NR)) {
* and resets important process table fields.
*/
clear_proc(exit_proc_nr);
- return(OK); /* tell MM that cleanup succeeded */
+ return(OK); /* tell PM that cleanup succeeded */
}
#include <sys/sigcontext.h>
INIT_ASSERT
-/*===========================================================================*
- * do_sigctl *
- *===========================================================================*/
-PUBLIC int do_sigctl(m_ptr)
+/* PM is ready to accept signals and repeatedly does a system call to get
+ * one. Find a process with pending signals. If no signals are available,
+ * return NONE in the process number field.
+ */
+PUBLIC int do_getsig(m_ptr)
message *m_ptr; /* pointer to request message */
{
- /* Only the MM and FS are allowed to use signal control operations. */
- if (m_ptr->m_source != MM_PROC_NR && m_ptr->m_source != FS_PROC_NR)
- return(EPERM);
-
- /* Now see what request we got. The supported requests are S_GETSIG,
- * S_ENDSIG, S_SENDSIG, S_SIGRETURN, and S_KILL. Unsupported requests
- * result in an EINVAL error.
- */
- switch(m_ptr->SIG_REQUEST) {
-
- /* MM is ready to accept signals and repeatedly does a system call to get
- * one. Find a process with pending signals. If no signals are available,
- * return NONE in the process number field.
- */
- case S_GETSIG: {
-
- register struct proc *rp;
-
- /* Find the next process with pending signals. */
- for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
- if (rp->p_flags & PENDING) {
- m_ptr->SIG_PROC = proc_number(rp);
- m_ptr->SIG_MAP = rp->p_pending;
- sigemptyset(&rp->p_pending); /* ball is in MM's court */
- rp->p_flags &= ~PENDING; /* blocked by SIG_PENDING */
- return(OK);
- }
- }
-
- /* No process with pending signals was found. */
- m_ptr->SIG_PROC = NONE;
- return(OK);
+ register struct proc *rp;
+
+ /* Find the next process with pending signals. */
+ for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) {
+ if (rp->p_flags & PENDING) {
+ m_ptr->SIG_PROC = proc_number(rp);
+ m_ptr->SIG_MAP = rp->p_pending;
+ sigemptyset(&rp->p_pending); /* ball is in PM's court */
+ rp->p_flags &= ~PENDING; /* blocked by SIG_PENDING */
+ return(OK);
+ }
}
- /* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a
- * call to cause_sig by a task
- */
- case S_ENDSIG: {
+ /* No process with pending signals was found. */
+ m_ptr->SIG_PROC = NONE;
+ return(OK);
+}
- register struct proc *rp;
+PUBLIC int do_endsig(m_ptr)
+message *m_ptr; /* pointer to request message */
+{
+/* Finish up after a kernel type signal, caused by a SYS_KILL message or a
+ * call to cause_sig by a task. This is called by the PM after processing a
+ * signal it got with SYS_GETSIG.
+ */
+ register struct proc *rp;
- rp = proc_addr(m_ptr->SIG_PROC);
- if (isemptyp(rp)) return(EINVAL); /* process already dead? */
- assert(isuserp(rp));
+ rp = proc_addr(m_ptr->SIG_PROC);
+ if (isemptyp(rp)) return(EINVAL); /* process already dead? */
- /* MM has finished one KSIG. Perhaps process is ready now? */
- if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
- && (rp->p_flags &= ~SIG_PENDING) == 0)
- lock_ready(rp);
- return(OK);
- }
+ /* PM has finished one kernel signal. Perhaps process is ready now? */
+ if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
+ && (rp->p_flags &= ~SIG_PENDING) == 0)
+ lock_ready(rp);
+ return(OK);
+}
- /* Handle sys_sendsig, POSIX-style signal handling.
- */
- case S_SENDSIG: {
+PUBLIC int do_sigsend(m_ptr)
+message *m_ptr; /* pointer to request message */
+{
+/* Handle sys_sigsend, POSIX-style signal handling. */
struct sigmsg smsg;
register struct proc *rp;
assert(isuserp(rp));
/* Get the sigmsg structure into our address space. */
- src_phys = umap_local(proc_addr(MM_PROC_NR), D, (vir_bytes)
+ src_phys = umap_local(proc_addr(PM_PROC_NR), D, (vir_bytes)
m_ptr->SIG_CTXT_PTR, (vir_bytes) sizeof(struct sigmsg));
assert(src_phys != 0);
phys_copy(src_phys,vir2phys(&smsg),(phys_bytes) sizeof(struct sigmsg));
rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
return(OK);
- }
-
- /* POSIX style signals require sys_sigreturn to put things in order before
- * the signalled process can resume execution
- */
- case S_SIGRETURN: {
+}
+PUBLIC int do_sigreturn(m_ptr)
+message *m_ptr; /* pointer to request message */
+{
+/* POSIX style signals require sys_sigreturn to put things in order before
+ * the signalled process can resume execution
+ */
struct sigcontext sc;
register struct proc *rp;
phys_bytes src_phys;
/* Restore the registers. */
kmemcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
-
return(OK);
- }
-
- /* Handle sys_kill(). Cause a signal to be sent to a process via MM.
- * Note that this has nothing to do with the kill(2) system call, this
- * is how the FS (and possibly other servers) get access to cause_sig.
- */
- case S_KILL: {
- cause_sig(m_ptr->SIG_PROC, m_ptr->SIG_NUMBER);
- return(OK);
- }
- default:
- return(EINVAL);
- }
}
-
+/*===========================================================================*
+ * do_sigctl *
+ *===========================================================================*/
PUBLIC int do_kill(m_ptr)
message *m_ptr; /* pointer to request message */
{
-/* Handle sys_kill(). Cause a signal to be sent to a process via MM.
+/* Handle sys_kill(). Cause a signal to be sent to a process via PM.
* Note that this has nothing to do with the kill (2) system call, this
* is how the FS (and possibly other servers) get access to cause_sig.
*/
argp = (vir_bytes) m_ptr->CTL_ARG_PTR;
rp = proc_addr(proc_nr);
- /* Check if the MM privileges are super user. */
+ /* Check if the PM privileges are super user. */
if (!priv || !isuserp(rp))
return(EPERM);
rp->p_type = P_SERVER;
rp->p_sendmask = ALLOW_ALL_MASK;
send_mask_allow(proc_addr(RTL8139)->p_sendmask, proc_nr);
- send_mask_allow(proc_addr(MM_PROC_NR)->p_sendmask, proc_nr);
+ send_mask_allow(proc_addr(PM_PROC_NR)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(FS_PROC_NR)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(IS_PROC_NR)->p_sendmask, proc_nr);
send_mask_allow(proc_addr(CLOCK)->p_sendmask, proc_nr);
}
/* The system call implemented in this file:
- * m_type: SYS_MEMCTL
+ * m_type: SYS_SEGCTL
*
* The parameters for this system call are:
* m4_l3: SEG_PHYS (physical base address)
/*===========================================================================*
- * do_phys2seg *
+ * do_segctl *
*===========================================================================*/
-PUBLIC int do_phys2seg(m_ptr)
+PUBLIC int do_segctl(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Return a segment selector and offset that can be used to reach a physical
*/
u16_t selector;
vir_bytes offset;
+ int i, index;
register struct proc *rp;
phys_bytes phys = (phys_bytes) m_ptr->SEG_PHYS;
vir_bytes size = (vir_bytes) m_ptr->SEG_SIZE;
int result;
- kprintf("Using Experimental LDT selector for video memory\n", NO_ARG);
+ /* First check if there is a slot available for this segment. */
+ rp = proc_addr(m_ptr->m_source);
+ index = -1;
+ for (i=0; i < NR_REMOTE_SEGS; i++) {
+ if (! rp->p_farmem[i].in_use) {
+ index = i;
+ rp->p_farmem[i].in_use = TRUE;
+ rp->p_farmem[i].mem_phys = phys;
+ rp->p_farmem[i].mem_len = size;
+ break;
+ }
+ }
+ if (index < 0) return(ENOSPC);
+
- if (!protected_mode) {
+ if (! machine.protected) {
selector = phys / HCLICK_SIZE;
offset = phys % HCLICK_SIZE;
result = OK;
* instead of bytes are used.
*/
if (size < BYTE_GRAN_MAX) {
- rp = proc_addr(m_ptr->m_source);
- init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys, size,
+ init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys, size,
USER_PRIVILEGE);
- selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
+ selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
offset = 0;
result = OK;
} else {
-#if ENABLE_USERPRIV && ENABLE_LOOSELDT
- rp = proc_addr(m_ptr->m_source);
- init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX], phys & ~0xFFFF, 0,
+ init_dataseg(&rp->p_ldt[EXTRA_LDT_INDEX+i], phys & ~0xFFFF, 0,
USER_PRIVILEGE);
- selector = (EXTRA_LDT_INDEX * 0x08) | (1 * 0x04) | USER_PRIVILEGE;
+ selector = ((EXTRA_LDT_INDEX+i)*0x08) | (1*0x04) | USER_PRIVILEGE;
offset = phys & 0xFFFF;
result = OK;
-#else
- result = E2BIG; /* allow settings only */
-#endif
}
}
+ /* Request successfully done. Now return the result. */
+ m_ptr->SEG_INDEX = index | REMOTE_SEG;
m_ptr->SEG_SELECT = selector;
m_ptr->SEG_OFFSET = offset;
return(result);
* T_EXIT exit
* T_STEP set trace bit
*
- * The T_OK and T_EXIT commands are handled completely by the memory manager,
+ * The T_OK and T_EXIT commands are handled completely by the process manager,
* all others come here.
*/
{ CLOCK, clock_task, P_TASK, PPRI_TASK, CLOCK_STACK, CLOCK_SENDMASK, "CLOCK" },
{ SYSTASK, sys_task, P_TASK, PPRI_TASK, SYS_STACK, SYSTEM_SENDMASK, "SYS" },
{ HARDWARE, 0, P_TASK, PPRI_TASK, HARDWARE_STACK,HARDWARE_SENDMASK,"HARDWAR" },
- { MM_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, MM_SENDMASK, "MM" },
+ { PM_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, PM_SENDMASK, "PM" },
{ FS_PROC_NR, 0, P_SERVER, PPRI_NORMAL, 0, FS_SENDMASK, "FS" },
{ IS_PROC_NR, 0, P_SYSTEM, PPRI_HIGHER, 0, IS_SENDMASK, "IS" },
{ TTY, 0, P_SYSTEM, PPRI_HIGHER, 0, TTY_SENDMASK, "TTY" },
typedef _PROTOTYPE( int (*rdwt_t), (message *m_ptr) );
typedef _PROTOTYPE( void (*watchdog_t), (void) );
-/* This is used within the kernel to handle virtual copying. */
-struct vir_addr {
- int proc_nr;
- int segment;
- vir_bytes offset;
-};
-
/* Type accepted by kprintf(). This is a hack to accept both integers and
* char pointers in the same argument.
*/
$(LIBSYS)(sys_times.o) \
$(LIBSYS)(sys_getuptm.o) \
$(LIBSYS)(sys_abort.o) \
- $(LIBSYS)(sys_copy.o) \
$(LIBSYS)(sys_exec.o) \
$(LIBSYS)(sys_fork.o) \
$(LIBSYS)(sys_kill.o) \
$(LIBSYS)(sys_newmap.o) \
- $(LIBSYS)(sys_sigctl.o) \
+ $(LIBSYS)(sys_sigsend.o) \
+ $(LIBSYS)(sys_sigret.o) \
+ $(LIBSYS)(sys_endsig.o) \
+ $(LIBSYS)(sys_getsig.o) \
$(LIBSYS)(sys_svrctl.o) \
$(LIBSYS)(sys_trace.o) \
$(LIBSYS)(sys_xit.o) \
$(LIBSYS)(sys_kmalloc.o) \
$(LIBSYS)(sys_irqctl.o) \
$(LIBSYS)(sys_eniop.o) \
- $(LIBSYS)(sys_ph2sg.o) \
+ $(LIBSYS)(sys_segctl.o) \
$(LIBSYS)(sys_umap.o) \
$(LIBSYS)(sys_exit.o) \
$(LIBSYS)(sys_physcp.o) \
$(LIBSYS)(sys_abort.o): sys_abort.c
$(CC1) sys_abort.c
-$(LIBSYS)(sys_copy.o): sys_copy.c
- $(CC1) sys_copy.c
-
$(LIBSYS)(sys_exec.o): sys_exec.c
$(CC1) sys_exec.c
$(LIBSYS)(sys_eniop.o): sys_eniop.c
$(CC1) sys_eniop.c
-$(LIBSYS)(sys_ph2sg.o): sys_ph2sg.c
- $(CC1) sys_ph2sg.c
+$(LIBSYS)(sys_segctl.o): sys_segctl.c
+ $(CC1) sys_segctl.c
$(LIBSYS)(sys_umap.o): sys_umap.c
$(CC1) sys_umap.c
$(LIBSYS)(sys_exit.o): sys_exit.c
$(CC1) sys_exit.c
-$(LIBSYS)(sys_sigctl.o): sys_sigctl.c
- $(CC1) sys_sigctl.c
+$(LIBSYS)(sys_getsig.o): sys_getsig.c
+ $(CC1) sys_getsig.c
+
+$(LIBSYS)(sys_endsig.o): sys_endsig.c
+ $(CC1) sys_endsig.c
+
+$(LIBSYS)(sys_sigsend.o): sys_sigsend.c
+ $(CC1) sys_sigsend.c
+
+$(LIBSYS)(sys_sigret.o): sys_sigret.c
+ $(CC1) sys_sigret.c
$(LIBSYS)(sys_physcp.o): sys_physcp.c
$(CC1) sys_physcp.c
+++ /dev/null
-#include "syslib.h"
-
-PUBLIC int sys_copy(src_proc, src_seg, src_vir,
- dst_proc, dst_seg, dst_vir, bytes)
-int src_proc; /* source process */
-int src_seg; /* source segment: T, D, or S */
-phys_bytes src_vir; /* source virtual address (phys addr for ABS)*/
-int dst_proc; /* dest process */
-int dst_seg; /* dest segment: T, D, or S */
-phys_bytes dst_vir; /* dest virtual address (phys addr for ABS) */
-phys_bytes bytes; /* how many bytes */
-{
-/* Transfer a block of data. The source and destination can each either be a
- * process number, SELF (to set own process number), or ABS (to indicate the
- * use of an absolute memory address).
- */
-
- message copy_mess;
-
- if (bytes == 0L) return(OK);
- copy_mess.CP_SRC_SPACE = src_seg;
- copy_mess.CP_SRC_PROC_NR = src_proc;
- copy_mess.CP_SRC_ADDR = (long) src_vir;
-
- copy_mess.CP_DST_SPACE = dst_seg;
- copy_mess.CP_DST_PROC_NR = dst_proc;
- copy_mess.CP_DST_ADDR = (long) dst_vir;
-
- copy_mess.CP_NR_BYTES = (long) bytes;
- return(_taskcall(SYSTASK, SYS_COPY, ©_mess));
-}
#include "syslib.h"
-PUBLIC int sys_endsig(proc)
-int proc;
+/*===========================================================================*
+ * sys_endsig *
+ *===========================================================================*/
+PUBLIC int sys_endsig(proc_nr)
+int proc_nr; /* process number */
{
- message m;
+ message m;
+ int result;
- m.m1_i1 = proc;
- return(_taskcall(SYSTASK, SYS_ENDSIG, &m));
+ m.SIG_PROC = proc_nr;
+ result = _taskcall(SYSTASK, SYS_ENDSIG, &m);
+ return(result);
}
+
+++ /dev/null
-#include "syslib.h"
-
-PUBLIC int sys_getmap(proc, ptr)
-int proc; /* process whose map is to be fetched */
-struct mem_map *ptr; /* pointer to new map */
-{
-/* Want to know map of a process, ask the kernel. */
-
- message m;
-
- m.m1_i1 = proc;
- m.m1_p1 = (char *) ptr;
- return(_taskcall(SYSTASK, SYS_GETMAP, &m));
-}
--- /dev/null
+#include "syslib.h"
+
+/*===========================================================================*
+ * sys_getsig *
+ *===========================================================================*/
+PUBLIC int sys_getsig(k_proc_nr, k_sig_map)
+int *k_proc_nr; /* return process number here */
+sigset_t *k_sig_map; /* return signal map here */
+{
+ message m;
+ int result;
+
+ result = _taskcall(SYSTASK, SYS_GETSIG, &m);
+ *k_proc_nr = m.SIG_PROC;
+ *k_sig_map = (sigset_t) m.SIG_MAP;
+ return(result);
+}
+
+++ /dev/null
-#include "syslib.h"
-
-PUBLIC int sys_oldsig(proc, sig, sighandler)
-int proc; /* process to be signaled */
-int sig; /* signal number: 1 to _NSIG */
-sighandler_t sighandler; /* pointer to signal handler in user space */
-{
-/* A proc has to be signaled. Tell the kernel. This function is obsolete. */
-
- message m;
-
- m.m6_i1 = proc;
- m.m6_i2 = sig;
- m.m6_f1 = sighandler;
- return(_taskcall(SYSTASK, SYS_OLDSIG, &m));
-}
#include "syslib.h"
-PUBLIC int sys_physcopy(src_phys, dst_phys, bytes)
-phys_bytes src_phys; /* source physical address */
-phys_bytes dst_phys; /* destination physical address */
+PUBLIC int sys_physcopy(src_proc, src_seg, src_vir,
+ dst_proc, dst_seg, dst_vir, bytes)
+int src_proc; /* source process */
+int src_seg; /* source memory segment */
+vir_bytes src_vir; /* source virtual address */
+int dst_proc; /* destination process */
+int dst_seg; /* destination memory segment */
+vir_bytes dst_vir; /* destination virtual address */
phys_bytes bytes; /* how many bytes */
{
-/* Transfer a block of data. This uses absolute memory addresses only. Use
- * sys_umap to convert a virtual address into a physical address if needed.
+/* Transfer a block of data. The source and destination can each either be a
+ * process number or SELF (to indicate own process number). Virtual addresses
+ * are offsets within LOCAL_SEG (text, stack, data), REMOTE_SEG, or BIOS_SEG.
+ * Physicall addressing is also possible with PHYS_SEG.
*/
+
message copy_mess;
if (bytes == 0L) return(OK);
- copy_mess.CP_SRC_ADDR = (long) src_phys;
- copy_mess.CP_DST_ADDR = (long) dst_phys;
+ copy_mess.CP_SRC_PROC_NR = src_proc;
+ copy_mess.CP_SRC_SPACE = src_seg;
+ copy_mess.CP_SRC_ADDR = (long) src_vir;
+ copy_mess.CP_DST_PROC_NR = dst_proc;
+ copy_mess.CP_DST_SPACE = dst_seg;
+ copy_mess.CP_DST_ADDR = (long) dst_vir;
copy_mess.CP_NR_BYTES = (long) bytes;
return(_taskcall(SYSTASK, SYS_PHYSCOPY, ©_mess));
}
#include "syslib.h"
/*===========================================================================*
- * sys_phys2seg *
+ * sys_segctl *
*===========================================================================*/
-PUBLIC int sys_phys2seg(seg, off, phys, size)
+PUBLIC int sys_segctl(index, seg, off, phys, size)
+int *index; /* return index of remote segment */
u16_t *seg; /* return segment selector here */
vir_bytes *off; /* return offset in segment here */
phys_bytes phys; /* physical address to convert */
int s;
m.SEG_PHYS = phys;
m.SEG_SIZE = size;
- s = _taskcall(SYSTASK, SYS_PHYS2SEG, &m);
+ s = _taskcall(SYSTASK, SYS_SEGCTL, &m);
+ *index = (int) m.SEG_INDEX;
*seg = (u16_t) m.SEG_SELECT;
*off = (vir_bytes) m.SEG_OFFSET;
return s;
+++ /dev/null
-#include "syslib.h"
-
-PUBLIC int sys_sendsig(proc, smp)
-int proc;
-struct sigmsg *smp;
-{
- message m;
-
- m.m1_i1 = proc;
- m.m1_p1 = (char *) smp;
- return(_taskcall(SYSTASK, SYS_SENDSIG, &m));
-}
+++ /dev/null
-#include "syslib.h"
-
-/*===========================================================================*
- * sys_sigctl *
- *===========================================================================*/
-PUBLIC int sys_sigctl(request, proc_nr, sig_ctxt, flags, k_proc_nr, k_sig_map)
-int request; /* control operation requested */
-int proc_nr; /* for which process */
-struct sigmsg *sig_ctxt; /* POSIX style handling */
-int flags; /* flags for POSIX handling */
-int *k_proc_nr; /* return process number here */
-sigset_t *k_sig_map; /* return signal map here */
-{
- message m;
- int result;
-
- m.m_type = SYS_SIGCTL;
- m.SIG_REQUEST = request;
- m.SIG_PROC = proc_nr;
- m.SIG_FLAGS = flags;
- m.SIG_CTXT_PTR = (char *) sig_ctxt;
- result = _taskcall(SYSTASK, SYS_SIGCTL, &m);
- if (request == S_GETSIG && k_proc_nr != 0 && k_sig_map != 0) {
- *k_proc_nr = m.SIG_PROC;
- *k_sig_map = (sigset_t) m.SIG_MAP;
- }
- return(result);
-}
-
#include "syslib.h"
-PUBLIC int sys_sigreturn(proc, scp, flags)
-int proc;
-vir_bytes scp;
-int flags;
+/*===========================================================================*
+ * sys_sigreturn *
+ *===========================================================================*/
+PUBLIC int sys_sigreturn(proc_nr, sig_ctxt, flags)
+int proc_nr; /* for which process */
+struct sigmsg *sig_ctxt; /* POSIX style handling */
+int flags; /* flags for POSIX handling */
{
- message m;
+ message m;
+ int result;
- m.m1_i1 = proc;
- m.m1_i2 = flags;
- m.m1_p1 = (char *) scp;
- return(_taskcall(SYSTASK, SYS_SIGRETURN, &m));
+ m.SIG_PROC = proc_nr;
+ m.SIG_CTXT_PTR = (char *) sig_ctxt;
+ m.SIG_FLAGS = flags;
+ result = _taskcall(SYSTASK, SYS_SIGRETURN, &m);
+ return(result);
}
+
--- /dev/null
+#include "syslib.h"
+
+/*===========================================================================*
+ * sys_sigsend *
+ *===========================================================================*/
+PUBLIC int sys_sigsend(proc_nr, sig_ctxt)
+int proc_nr; /* for which process */
+struct sigmsg *sig_ctxt; /* POSIX style handling */
+{
+ message m;
+ int result;
+
+ m.SIG_PROC = proc_nr;
+ m.SIG_CTXT_PTR = (char *) sig_ctxt;
+ result = _taskcall(SYSTASK, SYS_SIGSEND, &m);
+ return(result);
+}
+
+++ /dev/null
-#include "syslib.h"
-
-/*===========================================================================*
- * sys_vidcopy *
- *===========================================================================*/
-PUBLIC int sys_vidcopy(request, src_mem, src_vid, dst_vid, count)
-int request; /* MEM_VID_COPY or VID_VID_COPY */
-u16_t *src_mem; /* source address in memory */
-unsigned src_vid; /* source address in video memory */
-unsigned dst_vid; /* destination address in video */
-unsigned count; /* number of words to copy */
-{
-/* Console wants to display something on the screen. */
- message m;
- m.VID_REQUEST = request;
- m.VID_SRC_ADDR = src_mem;
- m.VID_SRC_OFFSET = src_vid;
- m.VID_DST_OFFSET = dst_vid;
- m.VID_CP_COUNT = count;
- return(_taskcall(SYSTASK, SYS_VIDCOPY, &m));
-}
-
phys_bytes bytes; /* how many bytes */
{
/* Transfer a block of data. The source and destination can each either be a
- * process number or SELF (to set own process number). The virtual address is
- * in the data segment (D).
+ * process number or SELF (to indicate own process number). Virtual addresses
+ * are offsets within LOCAL_SEG (text, stack, data), REMOTE_SEG, or BIOS_SEG.
*/
message copy_mess;
int *proc_nr; /* store process number here */
char *proc_name; /* lookup process by name */
{
- struct proc proc;
+ static struct proc proc;
message m;
int s;
if (proc_name != NULL) { /* lookup by name */
m.I_PROC_NR = SELF;
m.I_KEY_LEN = SELF;
m.I_VAL_PTR = (char *) &proc;
+ m.I_VAL_LEN = 0;
if ((s=_taskcall(SYSTASK, SYS_GETINFO, &m)) != OK)
return(s);
*proc_nr = proc.p_nr;
/* First obtain the machine ID to see if we can read the CMOS clock. Only
* for PS_386 and PC_AT this is possible. Otherwise, return an error.
*/
- sys_vircopy(SELF, BIOS_SEG, (vir_bytes) ADR_MACHINE_ID,
- SELF, D, (vir_bytes) &mach_id, LEN_MACHINE_ID);
+ sys_vircopy(SELF, BIOS_SEG, (vir_bytes) MACHINE_ID_ADDR,
+ SELF, D, (vir_bytes) &mach_id, MACHINE_ID_SIZE);
if (mach_id != PS_386_MACHINE && mach_id != PC_AT_MACHINE) {
printf("IS: Machine ID unknown. ID byte = %02x.\n", mach_id);
return(EFAULT);
register struct fproc *rfp;
/* Only MM may do the SETSID call directly. */
- if (who != MM_PROC_NR) return(ENOSYS);
+ if (who != PM_PROC_NR) return(ENOSYS);
/* Make the process a session leader with no controlling tty. */
rfp = &fproc[m_in.slot1];
if (sendrec(MEMORY, &m_out) != OK || m_out.REP_STATUS != OK)
panic("Can't set RAM disk size", NO_NUM);
- /* Tell MM the RAM disk size, and wait for it to come "on-line". */
+ /* Tell PM the RAM disk size, and wait for it to come "on-line". */
m_out.MEM_CHUNK_SIZE = ((long) ram_size_kb * 1024) >> CLICK_SHIFT;
- if (sendrec(MM_PROC_NR, &m_out) != OK)
- panic("FS can't sync up with MM", NO_NUM);
+ if (sendrec(PM_PROC_NR, &m_out) != OK)
+ panic("FS can't sync up with PM", NO_NUM);
#if ENABLE_CACHE2
/* The RAM disk is a second level block cache while not otherwise used. */
struct super_block *sp;
struct inode dummy;
- /* Only MM may make this call directly. */
- if (who != MM_PROC_NR) return(EGENERIC);
+ /* Only PM may make this call directly. */
+ if (who != PM_PROC_NR) return(EGENERIC);
/* Do exit processing for all leftover processes and servers. */
for (i = 0; i < NR_PROCS; i++) { m_in.slot1 = i; do_exit(); }
register struct fproc *cp;
int i;
- /* Only MM may make this call directly. */
- if (who != MM_PROC_NR) return(EGENERIC);
+ /* Only PM may make this call directly. */
+ if (who != PM_PROC_NR) return(EGENERIC);
/* Copy the parent's fproc struct to the child. */
fproc[m_in.child] = fproc[m_in.parent];
register int i;
long bitmap;
- /* Only MM may make this call directly. */
- if (who != MM_PROC_NR) return(EGENERIC);
+ /* Only PM may make this call directly. */
+ if (who != PM_PROC_NR) return(EGENERIC);
/* The array of FD_CLOEXEC bits is in the fp_cloexec bit map. */
fp = &fproc[m_in.slot1]; /* get_filp() needs 'fp' */
register struct inode *rip;
dev_t dev;
- /* Only MM may do the EXIT call directly. */
- if (who != MM_PROC_NR) return(EGENERIC);
+ /* Only PM may do the EXIT call directly. */
+ if (who != PM_PROC_NR) return(EGENERIC);
/* Nevertheless, pretend that the call came from the user. */
fp = &fproc[m_in.slot1]; /* get_filp() needs 'fp' */
register struct fproc *tfp;
- /* Only MM may make this call directly. */
- if (who != MM_PROC_NR) return(EGENERIC);
+ /* Only PM may make this call directly. */
+ if (who != PM_PROC_NR) return(EGENERIC);
tfp = &fproc[m_in.slot1];
if (call_nr == SETUID) {
dev_t dev;
message mess;
- if (who > MM_PROC_NR) return(EPERM);
+ if (who > PM_PROC_NR) return(EPERM);
proc_nr = m_in.pro;
if (proc_nr < 0 || proc_nr >= NR_PROCS) panic("unpause err 1", proc_nr);
rfp = &fproc[proc_nr];
int block_size;
/* MM loads segments by putting funny things in upper 10 bits of 'fd'. */
- if (who == MM_PROC_NR && (m_in.fd & (~BYTE)) ) {
+ if (who == PM_PROC_NR && (m_in.fd & (~BYTE)) ) {
usr = m_in.fd >> 7;
seg = (m_in.fd >> 5) & 03;
m_in.fd &= 037; /* get rid of user and segment bits */
int r;
register struct fproc *rfp;
- if (who == MM_PROC_NR) {
+ if (who == PM_PROC_NR) {
rfp = &fproc[m_in.slot1];
put_inode(fp->fp_rootdir);
dup_inode(fp->fp_rootdir = rfp->fp_rootdir);
PRIVATE sr_fd_t sr_fd_table[FD_NR];
PRIVATE mq_t *repl_queue, *repl_queue_tail;
PRIVATE cpvec_t cpvec[CPVEC_NR];
+PRIVATE struct vir_cp_req vir_cp_req[CPVEC_NR];
PUBLIC void sr_init()
{
{
size= (vir_bytes)acc->acc_length;
- cpvec[i].cpv_src= (vir_bytes)src;
- cpvec[i].cpv_dst= (vir_bytes)ptr2acc_data(acc);
- cpvec[i].cpv_size= size;
+ vir_cp_req[i].count= size;
+ vir_cp_req[i].src.proc_nr = proc;
+ vir_cp_req[i].src.segment = D;
+ vir_cp_req[i].src.offset = (vir_bytes) src;
+ vir_cp_req[i].dst.proc_nr = this_proc;
+ vir_cp_req[i].dst.segment = D;
+ vir_cp_req[i].dst.offset = (vir_bytes) ptr2acc_data(acc);
src += size;
acc= acc->acc_next;
if (i == CPVEC_NR || acc == NULL)
{
- mess.m_type= SYS_VCOPY;
- mess.m1_i1= proc;
- mess.m1_i2= this_proc;
- mess.m1_i3= i;
- mess.m1_p1= (char *)cpvec;
+ mess.m_type= SYS_VIRVCOPY;
+ mess.VCP_VEC_SIZE = i;
+ mess.VCP_VEC_ADDR = (char *) vir_cp_req;
if (sendrec(SYSTASK, &mess) <0)
ip_panic(("unable to sendrec"));
if (mess.m_type <0)
if (size)
{
- cpvec[i].cpv_src= (vir_bytes)ptr2acc_data(acc);
- cpvec[i].cpv_dst= (vir_bytes)dest;
- cpvec[i].cpv_size= size;
+ vir_cp_req[i].src.proc_nr = this_proc;
+ vir_cp_req[i].src.segment = D;
+ vir_cp_req[i].src.offset= (vir_bytes)ptr2acc_data(acc);
+ vir_cp_req[i].dst.proc_nr = proc;
+ vir_cp_req[i].dst.segment = D;
+ vir_cp_req[i].dst.offset= (vir_bytes)dest;
+ vir_cp_req[i].count= size;
i++;
}
if (i == CPVEC_NR || acc == NULL)
{
- mess.m_type= SYS_VCOPY;
- mess.m1_i1= this_proc;
- mess.m1_i2= proc;
- mess.m1_i3= i;
- mess.m1_p1= (char *)cpvec;
+ mess.m_type= SYS_VIRVCOPY;
+ mess.VCP_VEC_SIZE = i;
+ mess.VCP_VEC_ADDR = (char *) vir_cp_req;
if (sendrec(SYSTASK, &mess) <0)
ip_panic(("unable to sendrec"));
if (mess.m_type <0)
m= m->mq_next;
continue;
}
-assert(m->mq_mess.m_source != MM_PROC_NR);
+assert(m->mq_mess.m_source != PM_PROC_NR);
assert(m->mq_mess.m_type == REVIVE);
result= send(m->mq_mess.m_source, &m->mq_mess);
if (result != OK)
repl_queue= NULL;
if (m_cancel)
{
-assert(m_cancel->mq_mess.m_source != MM_PROC_NR);
+assert(m_cancel->mq_mess.m_source != PM_PROC_NR);
assert(m_cancel->mq_mess.m_type == REVIVE);
result= send(m_cancel->mq_mess.m_source, &m_cancel->mq_mess);
if (result != OK)
FORWARD _PROTOTYPE( void diagnostics_dmp, (void) );
FORWARD _PROTOTYPE( void sched_dmp, (void) );
FORWARD _PROTOTYPE( void monparams_dmp, (void) );
-FORWARD _PROTOTYPE( void kenviron_dmp, (void) );
+FORWARD _PROTOTYPE( void kenv_dmp, (void) );
FORWARD _PROTOTYPE( void memchunks_dmp, (void) );
/* Some global data that is shared among several dumping procedures.
case F6: irqtab_dmp(); break;
case F7: kmessages_dmp(); break;
case F9: diagnostics_dmp(); break;
- case F10: kenviron_dmp(); break;
+ case F10: kenv_dmp(); break;
case F11: memchunks_dmp(); break;
case F12: sched_dmp(); break;
default:
{
struct proc *rdy_head[NR_SCHED_QUEUES];
char *types[] = {"task","higher","high","normal","low","lower","user","idle"};
- struct kenviron kenviron;
+ struct kinfo kinfo;
register struct proc *rp;
vir_bytes ptr_diff;
int r;
return;
}
/* Then obtain kernel addresses to correct pointer information. */
- if ((r = sys_getkenviron(&kenviron)) != OK) {
+ if ((r = sys_getkinfo(&kinfo)) != OK) {
report("warning: couldn't get kernel addresses", r);
return;
}
/* Update all pointers. Nasty pointer algorithmic ... */
- ptr_diff = (vir_bytes) proc - (vir_bytes) kenviron.proc_addr;
+ ptr_diff = (vir_bytes) proc - (vir_bytes) kinfo.proc_addr;
for (r=0;r<NR_SCHED_QUEUES; r++)
if (rdy_head[r] != NIL_PROC)
rdy_head[r] =
}
/*===========================================================================*
- * kenviron_dmp *
+ * kenv_dmp *
*===========================================================================*/
-PRIVATE void kenviron_dmp()
+PRIVATE void kenv_dmp()
{
- struct kenviron kenv;
+ struct kinfo kinfo;
+ struct machine machine;
int r;
- if ((r = sys_getkenviron(&kenv)) != OK) {
- report("warning: couldn't get copy of kernel env", r);
+ if ((r = sys_getkinfo(&kinfo)) != OK) {
+ report("warning: couldn't get copy of kernel info struct", r);
+ return;
+ }
+ if ((r = sys_getmachine(&machine)) != OK) {
+ report("warning: couldn't get copy of kernel machine struct", r);
return;
}
- printf("Dump of kernel variables based on the environment set by the boot loader.\n");
- printf("- pc_at: %3d\n", kenv.pc_at);
- printf("- ps_mca: %3d\n", kenv.ps_mca);
- printf("- processor: %3d\n", kenv.processor);
- printf("- protected: %3d\n", kenv.protected);
- printf("- ega: %3d\n", kenv.ega);
- printf("- vga: %3d\n", kenv.vga);
- printf("- params_base:%5u\n", kenv.params_base);
- printf("- params_size:%5u\n", kenv.params_size);
- printf("- kmem_base:%5u\n", kenv.kmem_base);
- printf("- kmem_size:%5u\n", kenv.kmem_size);
- printf("- bootfs_base:%5u\n", kenv.bootfs_base);
- printf("- bootfs_size:%5u\n", kenv.bootfs_size);
+ printf("Dump of kinfo and machine structures.\n\n");
+ printf("Machine structure:\n");
+ 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.protected);
+ printf("- vdu_ega: %3d\n", machine.vdu_ega);
+ printf("- vdu_vga: %3d\n\n", machine.vdu_vga);
+ printf("Kernel info structure:\n");
+ printf("- code_base: %5u\n", kinfo.code_base);
+ printf("- code_size: %5u\n", kinfo.code_size);
+ printf("- data_base: %5u\n", kinfo.data_base);
+ printf("- data_size: %5u\n", kinfo.data_size);
+ printf("- proc_addr: %5u\n", kinfo.proc_addr);
+ printf("- kmem_base: %5u\n", kinfo.kmem_base);
+ printf("- kmem_size: %5u\n", kinfo.kmem_size);
+ printf("- bootdev_base: %5u\n", kinfo.bootdev_base);
+ printf("- bootdev_size: %5u\n", kinfo.bootdev_size);
+ printf("- params_base: %5u\n", kinfo.params_base);
+ printf("- params_size: %5u\n", kinfo.params_size);
+ printf("- version: %.6s\n", kinfo.version);
printf("\n");
}
src = (vir_bytes) m_in.exec_name;
dst = (vir_bytes) name_buf;
r = sys_datacopy(who, (vir_bytes) src,
- MM_PROC_NR, (vir_bytes) dst, (phys_bytes) m_in.exec_len);
+ PM_PROC_NR, (vir_bytes) dst, (phys_bytes) m_in.exec_len);
if (r != OK) return(r); /* file name not in user data segment */
/* Fetch the stack from the user before destroying the old core image. */
src = (vir_bytes) m_in.stack_ptr;
dst = (vir_bytes) mbuf;
r = sys_datacopy(who, (vir_bytes) src,
- MM_PROC_NR, (vir_bytes) dst, (phys_bytes)stk_bytes);
+ PM_PROC_NR, (vir_bytes) dst, (phys_bytes)stk_bytes);
if (r != OK) return(EACCES); /* can't fetch stack (e.g. bad virtual addr) */
vsp -= stk_bytes;
patch_ptr(mbuf, vsp);
src = (vir_bytes) mbuf;
- r = sys_datacopy(MM_PROC_NR, (vir_bytes) src,
+ r = sys_datacopy(PM_PROC_NR, (vir_bytes) src,
who, (vir_bytes) vsp, (phys_bytes)stk_bytes);
if (r != OK) panic("do_exec stack copy err on", who);
while (bytes > 0) {
count = MIN(bytes, (phys_bytes) sizeof(zero));
- if (sys_copy(MM_PROC_NR, D, (phys_bytes) zero,
- ABS, 0, base, count) != OK) {
+ if (sys_physcopy(PM_PROC_NR, D, (phys_bytes) zero,
+ NONE, PHYS_SEG, base, count) != OK) {
panic("new_mem can't zero", NO_NUM);
}
base += count;
/* Create a copy of the parent's core image for the child. */
child_abs = (phys_bytes) child_base << CLICK_SHIFT;
parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
- i = sys_physcopy(parent_abs, child_abs, prog_bytes);
+ i = sys_abscopy(parent_abs, child_abs, prog_bytes);
if (i < 0) panic("do_fork can't copy", i);
/* Find a slot in 'mproc' for the child process. A slot must exist. */
/* Process slot of caller. Misuse MM's own process slot if the kernel is
* calling. The can happen in case of pending kernel signals.
*/
- mp = &mproc[who < 0 ? MM_PROC_NR : who];
+ mp = &mproc[who < 0 ? PM_PROC_NR : who];
}
case RBT_MONITOR:
if (m_in.reboot_size >= sizeof(monitor_code)) return(EINVAL);
if (sys_datacopy(who, (vir_bytes) m_in.reboot_code,
- MM_PROC_NR, (vir_bytes) monitor_code,
+ PM_PROC_NR, (vir_bytes) monitor_code,
(phys_bytes) (m_in.reboot_size+1)) != OK) return(EFAULT);
if (monitor_code[m_in.reboot_size] != 0) return(EINVAL);
break;
check_sig(-1, SIGKILL); /* kill all processes except init */
tell_fs(REBOOT,0,0,0); /* tell FS to prepare for shutdown */
- sys_abort(m_in.reboot_flag, MM_PROC_NR, monitor_code, m_in.reboot_size);
+ sys_abort(m_in.reboot_flag, PM_PROC_NR, monitor_code, m_in.reboot_size);
sys_exit(0);
}
/* Binary compatibility check. */
if (req == SYSGETENV) {
+#if DEAD_CODE
+ printf("SYSGETENV by %d (fix!)\n", who);
+#endif
req = MMGETPARAM;
}
if (mp->mp_effuid != SUPER_USER) return(EPERM);
if (sys_datacopy(who, (phys_bytes) ptr,
- MM_PROC_NR, (phys_bytes) &swapon,
+ PM_PROC_NR, (phys_bytes) &swapon,
(phys_bytes) sizeof(swapon)) != OK) return(EFAULT);
return(swap_on(swapon.file, swapon.offset, swapon.size)); }
if (m_in.sig_nr < 1 || m_in.sig_nr > _NSIG) return (EINVAL);
svp = &mp->mp_sigact[m_in.sig_nr];
if ((struct sigaction *) m_in.sig_osa != (struct sigaction *) NULL) {
- r = sys_datacopy(MM_PROC_NR,(vir_bytes) svp,
+ r = sys_datacopy(PM_PROC_NR,(vir_bytes) svp,
who, (vir_bytes) m_in.sig_osa, (phys_bytes) sizeof(svec));
if (r != OK) return(r);
}
/* Read in the sigaction structure. */
r = sys_datacopy(who, (vir_bytes) m_in.sig_nsa,
- MM_PROC_NR, (vir_bytes) &svec, (phys_bytes) sizeof(svec));
+ PM_PROC_NR, (vir_bytes) &svec, (phys_bytes) sizeof(svec));
if (r != OK) return(r);
if (svec.sa_handler == SIG_IGN) {
rmp->mp_sigact[signo].sa_handler = SIG_DFL;
}
- sys_sendsig(slot, &sm);
+ sys_sigsend(slot, &sm);
sigdelset(&rmp->mp_sigpending, signo);
/* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc.,
* release it.
if (access(name_buf, mask) < 0) return(-errno);
/* The file is accessible but might not be readable. Make it readable. */
- tell_fs(SETUID, MM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER);
+ tell_fs(SETUID, PM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER);
/* Open the file and fstat it. Restore the ids early to handle errors. */
fd = open(name_buf, O_RDONLY | O_NONBLOCK);
save_errno = errno; /* open might fail, e.g. from ENFILE */
- tell_fs(SETUID, MM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid);
+ tell_fs(SETUID, PM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid);
if (fd < 0) return(-save_errno);
if (fstat(fd, s_buf) < 0) panic("allowed: fstat failed", NO_NUM);