Various fixes and improvements.

- fixed bug that caused IDLE to panic (irq hook inconsistency);
- kprintf() now accepts multiple arguments; moved to utility.c;
- prepare_shutdown() signals system processes with SIGKSTOP;
- phys_fill() renamed to phys_memset(), argument order changed;
- kmemset() removed in favor of phys_kmemset();
- kstrncpy() removed in favor of phys_copy();
- katoi, kstrncmp replaced by normal library procedure again;
- rm_irq_handler() interface changed (simply pass hook pointer);
This commit is contained in:
Jorrit Herder 2005-07-20 15:25:38 +00:00
parent f8af4da472
commit c0718054e9
19 changed files with 243 additions and 318 deletions

View file

@ -14,7 +14,7 @@ CFLAGS = -I$i
LDFLAGS = -i
HEAD = mpx.o
OBJS = start.o protect.o klibc.o klib.o table.o main.o proc.o \
OBJS = start.o protect.o klib.o table.o main.o proc.o \
i8259.o exception.o system.o clock.o utility.o debug.o
SYSTEM = system.a
LIBS = -ltimers

View file

@ -53,7 +53,7 @@
* a system server is notified and a copy of the buffer can be retrieved to
* display the message. The buffers size can safely be reduced.
*/
#define KMESS_BUF_SIZE 128
#define KMESS_BUF_SIZE 256
/* Buffer to gather randomness. This is used to generate a random stream by
* the MEMORY driver when reading from /dev/random.

View file

@ -120,35 +120,35 @@ check_runqueues(char *when)
for (q=0; q < NR_SCHED_QUEUES; q++) {
if(rdy_head[q] && !rdy_tail[q]) {
kprintf("head but no tail: %s", (karg_t) when);
kprintf("head but no tail: %s", when);
panic("scheduling error", NO_NUM);
}
if(!rdy_head[q] && rdy_tail[q]) {
kprintf("tail but no head: %s", (karg_t) when);
kprintf("tail but no head: %s", when);
panic("scheduling error", NO_NUM);
}
if(rdy_tail[q] && rdy_tail[q]->p_nextready != NIL_PROC) {
kprintf("tail and tail->next not null; %s", (karg_t) when);
kprintf("tail and tail->next not null; %s", when);
panic("scheduling error", NO_NUM);
}
for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
if (!xp->p_ready) {
kprintf("scheduling error: unready on runq: %s\n", (karg_t) when);
kprintf("scheduling error: unready on runq: %s\n", when);
panic("found unready process on run queue", NO_NUM);
}
if(xp->p_priority != q) {
kprintf("scheduling error: wrong priority: %s\n", (karg_t) when);
kprintf("scheduling error: wrong priority: %s\n", when);
panic("wrong priority", NO_NUM);
}
if(xp->p_found) {
kprintf("scheduling error: double scheduling: %s\n", (karg_t) when);
kprintf("scheduling error: double scheduling: %s\n", when);
panic("proc more than once on scheduling queue", NO_NUM);
}
xp->p_found = 1;
if(xp->p_nextready == NIL_PROC && rdy_tail[q] != xp) {
kprintf("scheduling error: last element not tail: %s\n", (karg_t) when);
kprintf("scheduling error: last element not tail: %s\n", when);
panic("scheduling error", NO_NUM);
}
if(l++ > PROCLIMIT) panic("loop in schedule queue?", NO_NUM);
@ -157,7 +157,7 @@ check_runqueues(char *when)
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
if(! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
kprintf("scheduling error: ready not on queue: %s\n", (karg_t) when);
kprintf("scheduling error: ready not on queue: %s\n", when);
panic("ready proc not on scheduling queue", NO_NUM);
if(l++ > PROCLIMIT) { panic("loop in proc.t?", NO_NUM); }
}

View file

@ -65,13 +65,12 @@ unsigned vec_nr;
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));
kprintf("process number %d ", proc_nr(saved_proc));
kprintf("(%s), ", saved_proc->p_name);
kprintf("pc = %d:", (unsigned) saved_proc->p_reg.cs);
kprintf("0x%x\n", (unsigned) saved_proc->p_reg.pc);
kprintf("\n%s\n", ep->msg);
kprintf("k_reenter = %d ", k_reenter);
kprintf("process %d (%s)", proc_nr(saved_proc), saved_proc->p_name);
kprintf("pc = %d:0x%x", (unsigned) saved_proc->p_reg.cs,
(unsigned) saved_proc->p_reg.pc);
kernel_exception = TRUE; /* directly shutdown */
panic("exception in a kernel task", NO_NUM);
}

View file

@ -123,29 +123,30 @@ irq_handler_t handler;
/*=========================================================================*
* rm_irq_handler *
*=========================================================================*/
PUBLIC int rm_irq_handler(irq, id)
int irq;
int id;
PUBLIC void rm_irq_handler(hook)
irq_hook_t *hook;
{
/* Unregister an interrupt handler. */
int irq = hook->irq;
int id = hook->id;
irq_hook_t **line;
if (irq < 0 || irq >= NR_IRQ_VECTORS) return(EINVAL);
if (irq < 0 || irq >= NR_IRQ_VECTORS)
panic("invalid call to rm_irq_handler", irq);
line = &irq_handlers[irq];
while (*line != NULL) {
if((*line)->id == id) {
(*line) = (*line)->next;
if(! irq_handlers[irq])
irq_use &= ~(1 << irq);
return(OK);
if(! irq_handlers[irq]) irq_use &= ~(1 << irq);
return;
}
line = &(*line)->next;
}
return(ENOENT);
/* When the handler is not found, normally return here. */
}
/*==========================================================================*
* intr_handle *
*==========================================================================*/

View file

@ -26,7 +26,7 @@
.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 _phys_fill ! zero data anywhere in memory
.define _phys_memset ! write pattern anywhere in memory
.define _mem_rdw ! copy one word from [segment:offset]
.define _reset ! reset the system
.define _idle_task ! task executed when there is no work
@ -440,25 +440,24 @@ pc_small:
ret
!*===========================================================================*
!* phys_fill *
!* phys_memset *
!*===========================================================================*
! PUBLIC void phys_fill(phys_bytes source, phys_bytes bytecount,
! unsigned long pattern);
! PUBLIC void phys_memset(phys_bytes source, unsigned long pattern,
! phys_bytes bytecount);
! Fill a block of physical memory with pattern.
.align 16
_phys_fill:
_phys_memset:
push ebp
mov ebp, esp
push esi
push ebx
push ds
mov esi, 8(ebp)
mov eax, 12(ebp)
mov eax, 16(ebp)
mov ebx, FLAT_DS_SELECTOR
mov ds, bx
mov ebx, 16(ebp)
mov ebx, 12(ebp)
shr eax, 2
fill_start:
mov (esi), ebx
@ -466,12 +465,12 @@ fill_start:
dec eax
jnz fill_start
! Any remaining bytes?
mov eax, 12(ebp)
mov eax, 16(ebp)
and eax, 3
remain_fill:
cmp eax, 0
jz fill_done
movb bl, 16(ebp)
movb bl, 12(ebp)
movb (esi), bl
add esi, 1
inc ebp

View file

@ -1,177 +0,0 @@
/* This file contains simplified versions of the standard libary functions for
* use with the kernel. This way the kernel sources remain separate from user
* sources and can easily be verified. Note that the functionality provided
* can be slightly different.
* March 2005, Jorrit N. Herder.
* Entrypoints into this file:
* kmemcpy: copy n bytes from pointer p1 to pointer p2
* kmemset: set n bytes to c starting at pointer p
* kprintf: printf for the kernel (see working below)
* kstrcmp: lexicographical comparison of two strings
* kstrncpy: copy string and pad or copy up to n chars
*
* This file contains the routines that take care of kernel messages, i.e.,
* diagnostic output within the kernel. Kernel messages are not directly
* displayed on the console, because this must be done by the PRINT driver.
* Instead, the kernel accumulates characters in a buffer and notifies the
* output driver when a new message is ready.
*/
#include "kernel.h"
#include <signal.h>
#include <minix/com.h>
#define isdigit(c) ((unsigned) ((c) - '0') < (unsigned) 10)
#define END_OF_KMESS -1
FORWARD _PROTOTYPE(void kputc, (int c));
/*=========================================================================*
* kmemcpy *
*=========================================================================*/
PUBLIC void *kmemcpy(void *s1, const void *s2, register size_t n)
{
register char *p1 = s1;
register const char *p2 = s2;
while (n-- > 0)
*p1++ = *p2++;
return s1;
}
/*=========================================================================*
* kmemset *
*=========================================================================*/
PUBLIC void *kmemset(void *s, register int c, register size_t n)
{
register char *s1 = s;
if (n++>0) { /* optimized for speed */
while (--n > 0)
*s1++ = c;
}
return s;
}
/*===========================================================================*
* kprintf *
*===========================================================================*/
PUBLIC void kprintf(fmt, arg)
const char *fmt; /* format string to be printed */
karg_t arg; /* argument for format string */
{
int c; /* next character in fmt */
unsigned long u; /* hold number argument */
int base; /* base of number arg */
int negative = 0; /* print minus sign */
static char x2c[] = "0123456789ABCDEF"; /* nr conversion table */
char ascii[8 * sizeof(long) / 3 + 2]; /* string for ascii number */
char *s = NULL; /* string to be printed */
while((c=*fmt++) != 0) {
if (c == '%') { /* expect format '%key' */
switch(c = *fmt++) { /* determine what to do */
/* Known keys are %d, %u, %x, %s, and %%. This is easily extended
* with number types like %b and %o by providing a different base.
* Number type keys don't set a string to 's', but use the general
* conversion after the switch statement.
*/
case 'd': /* output decimal */
u = arg < 0 ? -arg : arg;
if (arg < 0) negative = 1;
base = 10;
break;
case 'u': /* output unsigned long */
u = (unsigned long) arg;
base = 10;
break;
case 'x': /* output hexadecimal */
u = (unsigned long) arg;
base = 0x10;
break;
case 's': /* output string */
if ((s=(char *)arg) == NULL)
s = "(null)";
break;
case '%': /* output percent */
s = "%";
break;
/* Unrecognized key. */
default: /* echo back %key */
s = "%?";
s[1] = c; /* set unknown key */
}
/* Assume a number if no string is set. Convert to ascii. */
if (s == NULL) {
s = ascii + sizeof(ascii)-1;
*s = 0;
do { *--s = x2c[(u % base)]; } /* work backwards */
while ((u /= base) > 0);
}
/* This is where the actual output for format "%key" is done. */
if (negative) kputc('-'); /* print sign if negative */
while(*s != 0) { kputc(*s++); } /* print string/ number */
}
else {
kputc(c); /* print and continue */
}
}
kputc(END_OF_KMESS); /* terminate output */
}
/*===========================================================================*
* kputc *
*===========================================================================*/
PRIVATE void kputc(c)
int c; /* character to append */
{
/* Accumulate a single character for a kernel message. Send a notification
* the to PRINTF_PROC driver if an END_OF_KMESS is encountered.
*/
if (c != END_OF_KMESS) {
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
if (kmess.km_size < KMESS_BUF_SIZE)
kmess.km_size += 1;
kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
} else {
send_sig(PRINTF_PROC, SIGKMESS);
}
}
/*=========================================================================*
* kstrcmp *
*=========================================================================*/
int kstrcmp(register const char *s1, register const char *s2)
{
while (*s1 == *s2++)
if (*s1++ == '\0') return 0;
if (*s1 == '\0') return -1;
if (*--s2 == '\0') return 1;
return (unsigned char) *s1 - (unsigned char) *s2;
}
/*=========================================================================*
* kstrncpy *
*=========================================================================*/
PUBLIC char *kstrncpy(char *ret, register const char *s2, register ssize_t n)
{
register char *s1 = ret;
while((n-- > 0) && (*s1++ = *s2++)) /* copy up to n chars */
/* EMPTY */ ;
while(n-- > 0) /* possibly pad target */
*s1++ = '\0';
return ret;
}

View file

@ -14,6 +14,7 @@
*/
#include "kernel.h"
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <a.out.h>
#include <minix/callnr.h>
@ -24,6 +25,8 @@
FORWARD _PROTOTYPE( void announce, (void));
FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
#define SHUTDOWN_TICKS 5 /* time allowed to do cleanup */
/*===========================================================================*
* main *
@ -31,15 +34,14 @@ FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
PUBLIC void main()
{
/* Start the ball rolling. */
register struct proc *rp;
register struct priv *sp;
register int i,s;
struct system_image *ip; /* boot image pointer */
register struct proc *rp; /* process pointer */
register struct priv *sp; /* privilege structure pointer */
register int i, s;
int hdrindex; /* index to array of a.out headers */
phys_clicks text_base;
vir_clicks text_clicks;
vir_clicks data_clicks;
vir_clicks text_clicks, data_clicks;
reg_t ktsb; /* kernel task stack base */
struct system_image *ip; /* boot image pointer */
struct exec e_hdr; /* for a copy of an a.out header */
/* Initialize the interrupt controller. */
@ -73,9 +75,13 @@ PUBLIC void main()
for (i=0; i < NR_BOOT_PROCS; ++i) {
ip = &image[i]; /* process' attributes */
(void) init_proc(ip->proc_nr, NONE); /* initialize new process */
rp = proc_addr(ip->proc_nr); /* get process pointer */
kstrncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */
(void) init_proc(rp, NIL_SYS_PROC);
#if DEAD_CODE
(ip->flags & SYS_PROC) ?
NIL_SYS_PROC : NIL_PROC); /* initialize new process */
#endif
strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set name */
rp->p_name[P_NAME_LEN-1] = '\0'; /* just for safety */
rp->p_max_priority = ip->priority; /* max scheduling priority */
rp->p_priority = ip->priority; /* current priority */
@ -106,7 +112,7 @@ PUBLIC void main()
/* Convert addresses to clicks and build process memory map */
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 */
if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* common I&D */
data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
rp->p_memmap[T].mem_phys = text_base;
rp->p_memmap[T].mem_len = text_clicks;
@ -168,13 +174,13 @@ PUBLIC void main()
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.%s. Copyright 2001 Prentice-Hall, Inc.\n",
OS_RELEASE, OS_VERSION);
#if (CHIP == INTEL)
/* Real mode, or 16/32-bit protected mode? */
kprintf("Executing in %s mode\n\n",
machine.protected ? karg("32-bit protected") : karg("real"));
machine.protected ? "32-bit protected" : "real");
#endif
}
@ -189,6 +195,7 @@ int how; /* reason to shut down */
* sure it is only executed once. Unless a CPU exception occurred, the
*/
static timer_t shutdown_timer; /* timer for watchdog function */
register struct proc *rp;
message m;
/* Show debugging dumps on panics. Make sure that the TTY task is still
@ -201,21 +208,26 @@ int how; /* reason to shut down */
return; /* await sys_abort() from TTY */
}
/* Send signal to TTY so that it can switch to the primary console. */
send_sig(TTY, SIGKSTOP);
/* Allow processes to be scheduled to clean up, unless a CPU exception
* occurred. This is done by setting a timer. The timer argument passes
* the shutdown status.
/* Send a signal to all system processes that are still alive to inform
* them that the MINIX kernel is shutting down. A proper shutdown sequence
* should be implemented by a user-space server. This mechanism is useful
* as a backup in case of system panics, so that system processes can still
* run their shutdown code, e.g, to synchronize the FS or to let the TTY
* switch to the first console.
*/
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
if (kernel_exception) { /* set in exception() */
kprintf("\nAn exception occured; skipping stop sequence.\n", NO_NUM);
shutdown(&shutdown_timer); /* TTY isn't scheduled */
} else {
kprintf("\nNotifying system services about MINIX shutdown.\n", NO_NUM);
set_timer(&shutdown_timer, get_uptime(), shutdown);
for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
if (! isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && ! iskernelp(rp))
send_sig(proc_nr(rp), SIGKSTOP);
}
/* Notify system processes of the upcoming shutdown and allow them to be
* scheduled by setting a watchog timer that calls shutdown(). The timer
* argument passes the shutdown status.
*/
kprintf("Informed system about upcoming shutdown with SIGKSTOP signal.\n");
kprintf("Time for cleanup is allowed. MINIX will now be brought down.\n");
tmr_arg(&shutdown_timer)->ta_int = how; /* pass how in timer */
set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown);
}

View file

@ -61,7 +61,9 @@ struct priv {
EXTERN struct priv priv[NR_SYS_PROCS]; /* system properties table */
EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */
/* Unprivileged user processes all share the same privilege structure. */
/* Unprivileged user processes all share the same privilege structure.
* This id must be fixed because it is used to check send mask entries.
*/
#define USER_PRIV_ID 0
/* Make sure the system can boot. The following sanity check verifies that

View file

@ -88,6 +88,7 @@ struct proc {
#define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
#define NIL_PROC ((struct proc *) 0)
#define NIL_SYS_PROC ((struct proc *) 1)
#define cproc_addr(n) (&(proc + NR_TASKS)[(n)])
#define proc_addr(n) (pproc_addr + NR_TASKS)[(n)]
#define proc_nr(p) ((p)->p_nr)

View file

@ -15,24 +15,14 @@ _PROTOTYPE( unsigned long read_clock, (void) );
_PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) );
_PROTOTYPE( void reset_timer, (struct timer *tp) );
/* klibc.c */
_PROTOTYPE( void *kmemcpy, (void *s1, const void *s2, register size_t n));
_PROTOTYPE( void *kmemset, (void *s, register int c, register size_t n));
_PROTOTYPE( int kstrcmp, (register const char *s1, register const char *s2));
_PROTOTYPE( char *kstrncpy,
(char *s1, register const char *s2, register const ssize_t n));
#define karg(arg) (karg_t) (arg)
_PROTOTYPE( void kprintf, (const char *fmt, karg_t arg) );
/* main.c */
_PROTOTYPE( void main, (void) );
_PROTOTYPE( void prepare_shutdown, (int how) );
_PROTOTYPE( void stop_sequence, (struct timer *tp) );
/* utility.c */
_PROTOTYPE( void kprintf, (const char *fmt, ...) );
_PROTOTYPE( void panic, (_CONST char *s, int n) );
_PROTOTYPE( void safe_lock, (int c, char *v) );
_PROTOTYPE( void safe_unlock, (void) );
_PROTOTYPE( int alloc_bit, (bitchunk_t *map, bit_t nr_bits) );
_PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits) );
@ -51,8 +41,8 @@ _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds,
/* system.c */
_PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) );
_PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) );
_PROTOTYPE( int init_proc, (int proc_nr, int proto_nr) );
_PROTOTYPE( void clear_proc, (int proc_nr) );
_PROTOTYPE( int init_proc, (register struct proc *rc, struct proc *rp) );
_PROTOTYPE( void clear_proc, (register struct proc *rc) );
_PROTOTYPE( phys_bytes numap_local, (int proc_nr, vir_bytes vir_addr,
vir_bytes bytes) );
_PROTOTYPE( void sys_task, (void) );
@ -77,7 +67,7 @@ _PROTOTYPE( void intr_init, (int mine) );
_PROTOTYPE( void intr_handle, (irq_hook_t *hook) );
_PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq,
irq_handler_t handler) );
_PROTOTYPE( int rm_irq_handler, (int irq, int id) );
_PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook) );
/* klib*.s */
_PROTOTYPE( void int86, (void) );
@ -88,11 +78,12 @@ _PROTOTYPE( int disable_irq, (irq_hook_t *hook) );
_PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset) );
_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
phys_bytes count) );
_PROTOTYPE( void phys_fill, (phys_bytes source, phys_bytes count, unsigned long pattern) );
_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern,
phys_bytes count) );
_PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count));
_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count));
_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void reset, (void) );
_PROTOTYPE( void level0, (void (*func)(void)) );
_PROTOTYPE( void monitor, (void) );

View file

@ -12,6 +12,7 @@
#include "protect.h"
#include "proc.h"
#include <stdlib.h>
#include <string.h>
FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key));
@ -56,9 +57,9 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
/* Record miscellaneous information for user-space servers. */
kinfo.nr_procs = NR_PROCS;
kinfo.nr_tasks = NR_TASKS;
kstrncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release));
kinfo.release[sizeof(kinfo.release)-1] = '\0';
kstrncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version));
kinfo.version[sizeof(kinfo.version)-1] = '\0';
kinfo.proc_addr = (vir_bytes) proc;
kinfo.kmem_base = vir2phys(0);
@ -75,16 +76,16 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
/* XT, AT or MCA bus? */
value = get_value(params, "bus");
if (value == NIL_PTR || kstrcmp(value, "at") == 0) {
if (value == NIL_PTR || strcmp(value, "at") == 0) {
machine.pc_at = TRUE; /* PC-AT compatible hardware */
} else if (kstrcmp(value, "mca") == 0) {
} else if (strcmp(value, "mca") == 0) {
machine.pc_at = machine.ps_mca = TRUE; /* PS/2 with micro channel */
}
/* Type of VDU: */
value = get_value(params, "video"); /* EGA or VGA video unit */
if (kstrcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
if (kstrcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE;
if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE;
/* Return to assembler code to switch to protected mode (if 286),
* reload selectors and call main().

View file

@ -92,7 +92,7 @@ PUBLIC void sys_task()
if (result != EDONTREPLY) {
m.m_type = result; /* report status of call */
if (OK != lock_send(m.m_source, &m)) {
kprintf("Warning, SYSTASK couldn't reply to request from %d\n",
kprintf("Warning, SYSTASK couldn't reply to request from %d.\n",
m.m_source);
}
}
@ -171,34 +171,36 @@ PRIVATE void initialize(void)
/*===========================================================================*
* init_proc *
*===========================================================================*/
PUBLIC int init_proc(proc_nr, proto_nr)
int proc_nr; /* slot of process to initialize */
int proto_nr; /* prototype process to copy from */
PUBLIC int init_proc(rc, rp)
register struct proc *rc; /* new (child) process pointer */
struct proc *rp; /* prototype (parent) process */
{
register struct proc *rc, *rp;
register struct priv *sp;
register struct priv *sp; /* process' privilege structure */
int i;
/* Get a pointer to the process to initialize. */
rc = proc_addr(proc_nr);
/* If there is a prototype process to initialize from, use it. Otherwise,
* assume the caller will take care of initialization, but make sure that
* the new process gets a pointer to a system properties structure.
*/
if (isokprocn(proto_nr)) {
kprintf("INIT proc from prototype %d\n", proto_nr);
} else {
if (rp == NIL_PROC) { /* new user process */
kprintf("init_proc() for new user proc %d\n", proc_nr(rc));
sp = &priv[USER_PRIV_ID];
sp->s_proc_nr = ANY; /* misuse for users */
rc->p_priv = sp; /* assign to process */
return(OK);
} else if (rp == NIL_SYS_PROC) { /* new system process */
for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) {
if (sp->s_proc_nr == NONE) { /* found free slot */
sp->s_proc_nr = proc_nr; /* set association */
sp->s_proc_nr = proc_nr(rc); /* set association */
rc->p_priv = sp; /* assign to process */
return(OK);
}
}
kprintf("No free PRIV structure!\n", NO_NUM);
return(ENOSPC); /* out of resources */
} else { /* forked process */
kprintf("init_proc() from prototype %d\n", proc_nr(rp));
}
}
@ -206,26 +208,22 @@ int proto_nr; /* prototype process to copy from */
/*===========================================================================*
* clear_proc *
*===========================================================================*/
PUBLIC void clear_proc(proc_nr)
int proc_nr; /* slot of process to clean up */
PUBLIC void clear_proc(rc)
register struct proc *rc; /* slot of process to clean up */
{
register struct proc *rp, *rc;
register struct proc *rp; /* iterate over process table */
register struct proc **xpp; /* iterate over caller queue */
int i;
/* Get a pointer to the process that exited. */
rc = proc_addr(proc_nr);
/* Turn off any alarm timers at the clock. */
reset_timer(&priv(rc)->s_alarm_timer);
/* Make sure the exiting process is no longer scheduled. */
/* Make sure that the exiting process is no longer scheduled. */
if (rc->p_rts_flags == 0) lock_unready(rc);
/* If the process being terminated happens to be queued trying to send a
* message (e.g., the process was killed by a signal, rather than it doing
* an exit or it is forcibly shutdown in the stop sequence), then it must
* be removed from the message queues.
* a normal exit), then it must be removed from the message queues.
*/
if (rc->p_rts_flags & SENDING) {
/* Check all proc slots to see if the exiting process is queued. */
@ -245,26 +243,19 @@ int proc_nr; /* slot of process to clean up */
/* Check the table with IRQ hooks to see if hooks should be released. */
for (i=0; i < NR_IRQ_HOOKS; i++) {
if (irq_hooks[i].proc_nr == proc_nr)
irq_hooks[i].proc_nr = NONE;
if (irq_hooks[i].proc_nr == proc_nr(rc)) {
rm_irq_handler(&irq_hooks[i]); /* remove interrupt handler */
irq_hooks[i].proc_nr = NONE; /* mark hook as free */
}
}
#if TEMP_CODE
/* Check if there are pending notifications. Release the buffers. */
while (rc->p_ntf_q != NULL) {
i = (int) (rc->p_ntf_q - &notify_buffer[0]);
free_bit(i, notify_bitmap, NR_NOTIFY_BUFS);
rc->p_ntf_q = rc->p_ntf_q->n_next;
}
#endif
/* Now it is safe to release the process table slot. If this is a system
* process, also release its privilege structure. Further cleanup is not
* needed at this point. All important fields are reinitialized when the
* slots are assigned to another, new process.
*/
rc->p_rts_flags = SLOT_FREE;
if (priv(rp)->s_flags & SYS_PROC) priv(rp)->s_proc_nr = NONE;
if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE;
}

View file

@ -8,6 +8,7 @@
* m1_p3: PR_IP_PTR (new instruction pointer)
*/
#include "../system.h"
#include <string.h>
#include <signal.h>
#if USE_EXEC
@ -35,7 +36,7 @@ register message *m_ptr; /* pointer to request message */
#endif
#endif
#if (CHIP == INTEL) /* wipe extra LDT entries */
kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0,
phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 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 */
@ -50,7 +51,7 @@ register message *m_ptr; /* pointer to request message */
for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
*np = 0; /* mark end */
} else {
kstrncpy(rp->p_name, "<unset>", P_NAME_LEN);
strncpy(rp->p_name, "<unset>", P_NAME_LEN);
}
return(OK);
}

View file

@ -28,13 +28,13 @@ message *m_ptr; /* pointer to request message */
exit_proc_nr = m_ptr->PR_PROC_NR; /* get exiting process */
if (exit_proc_nr != SELF) { /* PM tries to exit self */
if (! isokprocn(exit_proc_nr)) return(EINVAL);
clear_proc(exit_proc_nr); /* exit a user process */
clear_proc(proc_addr(exit_proc_nr)); /* exit a user process */
return(OK); /* report back to PM */
}
}
/* The PM or some other system process requested to be exited. */
clear_proc(m_ptr->m_source);
clear_proc(proc_addr(m_ptr->m_source));
return(EDONTREPLY);
}
#endif /* USE_EXIT */

View file

@ -80,9 +80,9 @@ register message *m_ptr; /* pointer to request message */
return(EINVAL);
} else if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) {
return(EPERM);
} else {
r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id);
}
/* Remove the handler and return. */
rm_irq_handler(&irq_hooks[irq_hook_id]);
break;
default:

View file

@ -18,10 +18,10 @@ PUBLIC int do_memset(m_ptr)
register message *m_ptr;
{
/* Handle sys_memset(). */
unsigned long pat;
unsigned long p;
unsigned char c = m_ptr->MEM_CHAR;
pat = c | (c << 8) | (c << 16) | (c << 24);
phys_fill((phys_bytes) m_ptr->MEM_PTR, (phys_bytes) m_ptr->MEM_COUNT, pat);
p = c | (c << 8) | (c << 16) | (c << 24);
phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT);
return(OK);
}

View file

@ -3,11 +3,6 @@
typedef _PROTOTYPE( void task_t, (void) );
/* Type accepted by kprintf(). This is a hack to accept both integers and
* char pointers in the same argument.
*/
typedef long karg_t; /* use largest type here */
/* Process table and system property related types. */
typedef int proc_nr_t; /* process table entry number */
typedef short sys_id_t; /* system process index */

View file

@ -1,34 +1,143 @@
/* This file contains a collection of miscellaneous procedures:
* panic abort MINIX due to a fatal error
* panic: abort MINIX due to a fatal error
* kprintf: diagnostic output for the kernel
*
* Changes:
* simple printing to circular buffer (Jorrit N. Herder)
*
* This file contains the routines that take care of kernel messages, i.e.,
* diagnostic output within the kernel. Kernel messages are not directly
* displayed on the console, because this must be done by the PRINT driver.
* Instead, the kernel accumulates characters in a buffer and notifies the
* output driver when a new message is ready.
*/
#include "kernel.h"
#include "assert.h"
#include <unistd.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <signal.h>
#include <minix/com.h>
#define END_OF_KMESS -1
FORWARD _PROTOTYPE(void kputc, (int c));
/*===========================================================================*
* panic *
*===========================================================================*/
PUBLIC void panic(s,n)
_CONST char *s;
int n;
PUBLIC void panic(mess,nr)
_CONST char *mess;
int nr;
{
/* The system has run aground of a fatal kernel error. Terminate execution. */
static int panicking = 0;
if (panicking ++) return; /* prevent recursive panics */
if (s != NULL) {
kprintf("\nKernel panic: %s", karg(s));
if (n != NO_NUM) kprintf(" %d", n);
if (mess != NULL) {
kprintf("\nKernel panic: %s", mess);
if (nr != NO_NUM) kprintf(" %d", nr);
kprintf("\n",NO_NUM);
}
prepare_shutdown(RBT_PANIC);
}
/*===========================================================================*
* kprintf *
*===========================================================================*/
PUBLIC void kprintf(const char *fmt, ...) /* format to be printed */
{
int c; /* next character in fmt */
unsigned long u; /* hold number argument */
int base; /* base of number arg */
int negative = 0; /* print minus sign */
static char x2c[] = "0123456789ABCDEF"; /* nr conversion table */
char ascii[8 * sizeof(long) / 3 + 2]; /* string for ascii number */
char *s = NULL; /* string to be printed */
va_list argp; /* optional arguments */
va_start(argp, fmt); /* init variable arguments */
while((c=*fmt++) != 0) {
if (c == '%') { /* expect format '%key' */
switch(c = *fmt++) { /* determine what to do */
/* Known keys are %d, %u, %x, %s, and %%. This is easily extended
* with number types like %b and %o by providing a different base.
* Number type keys don't set a string to 's', but use the general
* conversion after the switch statement.
*/
case 'd': /* output decimal */
u = va_arg(argp, int);
if (u < 0) { negative = 1; u = -u; }
base = 10;
break;
case 'u': /* output unsigned long */
u = va_arg(argp, unsigned long);
base = 10;
break;
case 'x': /* output hexadecimal */
u = va_arg(argp, unsigned long);
base = 0x10;
break;
case 's': /* output string */
s = va_arg(argp, char *);
if (s == NULL) s = "(null)";
break;
case '%': /* output percent */
s = "%";
break;
/* Unrecognized key. */
default: /* echo back %key */
s = "%?";
s[1] = c; /* set unknown key */
}
/* Assume a number if no string is set. Convert to ascii. */
if (s == NULL) {
s = ascii + sizeof(ascii)-1;
*s = 0;
do { *--s = x2c[(u % base)]; } /* work backwards */
while ((u /= base) > 0);
}
/* This is where the actual output for format "%key" is done. */
if (negative) kputc('-'); /* print sign if negative */
while(*s != 0) { kputc(*s++); } /* print string/ number */
}
else {
kputc(c); /* print and continue */
}
}
kputc(END_OF_KMESS); /* terminate output */
va_end(argp); /* end variable arguments */
}
/*===========================================================================*
* kputc *
*===========================================================================*/
PRIVATE void kputc(c)
int c; /* character to append */
{
/* Accumulate a single character for a kernel message. Send a notification
* the to PRINTF_PROC driver if an END_OF_KMESS is encountered.
*/
if (c != END_OF_KMESS) {
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
if (kmess.km_size < KMESS_BUF_SIZE)
kmess.km_size += 1;
kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
} else {
send_sig(PRINTF_PROC, SIGKMESS);
}
}
#if TEMP_CODE