CC = exec cc
CFLAGS = -I$i
LDFLAGS = -i
-LIBS = -lsys -lsysutil -ltimers
+LIBS = -lsysutil -lsys -ltimers
OBJ = at_wini.o
LIBDRIVER = $d/libdriver/driver.o $d/libdriver/drvlib.o
#include <minix/keymap.h>
#include <sys/ioc_disk.h>
+
#if ENABLE_AT_WINI
#define ATAPI_DEBUG 0 /* To debug ATAPI code. */
CC = exec cc
CFLAGS = -I$i
LDFLAGS = -i
-LIBS = -lsys -lsysutil
+LIBS = -lsysutil -lsys
OBJECTS = driver.o drvlib.o
#include "drvlib.h"
#include <unistd.h>
+
/* Extended partition? */
#define ext_part(s) ((s) == 0x05 || (s) == 0x0F)
/* Reply to the writer if all output is finished or if an error occured. */
if (tp->tty_outleft == 0 || result != OK) {
+ /* REVIVE is not possible. I/O on memory mapped consoles finishes. */
tty_reply(tp->tty_outrepcode, tp->tty_outcaller, tp->tty_outproc,
tp->tty_outcum);
tp->tty_outcum = 0;
int try;
{
/* Process characters from the circular keyboard buffer. */
-
char buf[3];
int scode;
unsigned ch;
+#define NEW_REVIVE 1
/* This file contains the tesminal driver, both for the IBM console and regular
* ASCII terminals. It handles only the device-independent part of a TTY, the
* device dependent parts are in console.c, rs232.c, etc. This file contains
* DEV_OPEN: a tty line has been opened
* DEV_CLOSE: a tty line has been closed
* DEV_SELECT: start select notification request
- * DEV_SELECT_CAN: cancel select notification
+ * DEV_STATUS: FS wants to know status for SELECT or REVIVE
* CANCEL: terminate a previous incomplete system call immediately
*
* m_type TTY_LINE PROC_NR COUNT TTY_SPEK TTY_FLAGS ADDRESS
* |-------------+---------+---------+---------+---------+---------+---------|
* | DEV_CLOSE |minor dev| proc nr | | | | |
* |-------------+---------+---------+---------+---------+---------+---------|
+ * | DEV_STATUS | | | | | | |
+ * |-------------+---------+---------+---------+---------+---------+---------|
* | CANCEL |minor dev| proc nr | | | | |
* ---------------------------------------------------------------------------
*
FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr) );
FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr) );
FORWARD _PROTOTYPE( void do_select, (tty_t *tp, message *m_ptr) );
+FORWARD _PROTOTYPE( void do_status, (message *m_ptr) );
FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp) );
FORWARD _PROTOTYPE( int tty_echo, (tty_t *tp, int ch) );
FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch) );
sigset_t sigset = (sigset_t) tty_mess.NOTIFY_ARG;
if (sigismember(&sigset, SIGKSTOP)) {
cons_stop(); /* switch to primary console */
-#if DEAD_CODE
if (irq_hook_id != -1) {
sys_irqdisable(&irq_hook_id);
sys_irqrmpolicy(KEYBOARD_IRQ, &irq_hook_id);
}
-#endif
}
if (sigismember(&sigset, SIGTERM)) cons_stop();
if (sigismember(&sigset, SIGKMESS)) do_new_kmess(&tty_mess);
; /* do nothing; end switch */
}
- /* Only device requests should get to this point.
- * Check the minor device number.
+ /* Only device requests should get to this point. All requests,
+ * except DEV_STATUS, have a minor device number. Check this
+ * exception and get the minor device number otherwise.
*/
+ if (tty_mess.m_type == DEV_STATUS) {
+ do_status(&tty_mess);
+ continue;
+ }
line = tty_mess.TTY_LINE;
if ((line - CONS_MINOR) < NR_CONS) {
tp = tty_addr(line - CONS_MINOR);
}
+/*===========================================================================*
+ * do_status *
+ *===========================================================================*/
+PRIVATE void do_status(m_ptr)
+message *m_ptr;
+{
+ register struct tty *tp;
+ int event_found;
+ int status;
+ int ops;
+
+ /* Check for select or revive events on any of the ttys. If we found an,
+ * event return a single status message for it. The FS will make another
+ * call to see if there is more.
+ */
+ event_found = 0;
+ for (tp = FIRST_TTY; tp < END_TTY; tp++) {
+ if ((ops = select_try(tp, tp->tty_select_ops)) &&
+ tp->tty_select_proc == m_ptr->m_source) {
+
+ /* I/O for a selected minor device is ready. */
+ m_ptr->m_type = DEV_IO_READY;
+ m_ptr->DEV_MINOR = tp->tty_index;
+ m_ptr->DEV_SEL_OPS = ops;
+
+ tp->tty_select_ops &= ~ops; /* unmark select event */
+ event_found = 1;
+ break;
+ }
+ else if (tp->tty_inrevived && tp->tty_incaller == m_ptr->m_source) {
+
+ /* Suspended request finished. Send a REVIVE. */
+ m_ptr->m_type = DEV_REVIVE;
+ m_ptr->REP_PROC_NR = tp->tty_inproc;
+ m_ptr->REP_STATUS = tp->tty_incum;
+
+ tp->tty_inleft = tp->tty_incum = 0;
+ tp->tty_inrevived = 0; /* unmark revive event */
+ event_found = 1;
+ break;
+ }
+ else if (tp->tty_outrevived && tp->tty_outcaller == m_ptr->m_source) {
+
+ /* Suspended request finished. Send a REVIVE. */
+ m_ptr->m_type = DEV_REVIVE;
+ m_ptr->REP_PROC_NR = tp->tty_outproc;
+ m_ptr->REP_STATUS = tp->tty_outcum;
+
+ tp->tty_outcum = 0;
+ tp->tty_outrevived = 0; /* unmark revive event */
+ event_found = 1;
+ break;
+ }
+ }
+
+ if (! event_found) {
+ /* No events of interest were found. Return an empty message. */
+ m_ptr->m_type = DEV_NO_STATUS;
+ }
+
+ /* Almost done. Send back the reply message to the caller. */
+ if ((status = send(m_ptr->m_source, m_ptr)) != OK) {
+ panic("TTY","send in do_status failed, status\n", status);
+ }
+}
+
+
/*===========================================================================*
* do_read *
*===========================================================================*/
{
int ready_ops = 0;
- /* special case. if line is hung up, no operations will block.
+ /* Special case. If line is hung up, no operations will block.
* (and it can be seen as an exceptional condition.)
*/
if (tp->tty_termios.c_ospeed == B0) {
PUBLIC int select_retry(struct tty *tp)
{
+#if DEAD_CODE
int ops;
if((ops = select_try(tp, tp->tty_select_ops))) {
message m;
notify(tp->tty_select_proc, &m);
tp->tty_select_ops &= ~ops;
}
+#else
+ if (select_try(tp, tp->tty_select_ops))
+ alert(tp->tty_select_proc);
+#endif
return OK;
}
/* Reply if enough bytes are available. */
if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
+#if NEW_REVIVE
+ if (tp->tty_inrepcode == REVIVE) {
+ alert(tp->tty_incaller);
+ tp->tty_inrevived = 1;
+ } else {
+ tty_reply(tp->tty_inrepcode, tp->tty_incaller,
+ tp->tty_inproc, tp->tty_incum);
+ tp->tty_inleft = tp->tty_incum = 0;
+ }
+#else
tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
tp->tty_incum);
tp->tty_inleft = tp->tty_incum = 0;
+#endif
}
}
/* Usually reply to the reader, possibly even if incum == 0 (EOF). */
if (tp->tty_inleft == 0) {
+#if NEW_REVIVE
+ if (tp->tty_inrepcode == REVIVE) {
+ alert(tp->tty_incaller);
+ tp->tty_inrevived = 1;
+ } else {
+ tty_reply(tp->tty_inrepcode, tp->tty_incaller,
+ tp->tty_inproc, tp->tty_incum);
+ tp->tty_inleft = tp->tty_incum = 0;
+ }
+#else
tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
tp->tty_incum);
tp->tty_inleft = tp->tty_incum = 0;
+#endif
}
}
int status; /* reply code */
{
/* Send a reply to a process that wanted to read or write data. */
-
message tty_mess;
tty_mess.m_type = code;
tty_mess.REP_PROC_NR = proc_nr;
tty_mess.REP_STATUS = status;
+
if ((status = send(replyee, &tty_mess)) != OK) {
panic("TTY","tty_reply failed, status\n", status);
}
/* Information about incomplete I/O requests is stored here. */
char tty_inrepcode; /* reply code, TASK_REPLY or REVIVE */
+ char tty_inrevived; /* set to 1 if revive callback is pending */
char tty_incaller; /* process that made the call (usually FS) */
char tty_inproc; /* process that wants to read from tty */
vir_bytes tty_in_vir; /* virtual address where data is to go */
int tty_inleft; /* how many chars are still needed */
int tty_incum; /* # chars input so far */
char tty_outrepcode; /* reply code, TASK_REPLY or REVIVE */
+ char tty_outrevived; /* set to 1 if revive callback is pending */
char tty_outcaller; /* process that made the call (usually FS) */
char tty_outproc; /* process that wants to write to tty */
vir_bytes tty_out_vir; /* virtual address where data comes from */
_PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr,
int status) );
_PROTOTYPE( int tty_devnop, (struct tty *tp, int try) );
+_PROTOTYPE( int select_try, (struct tty *tp, int ops) );
_PROTOTYPE( int select_retry, (struct tty *tp) );
/* rs232.c */
* Directly sending it to TTY only displays the output. Sending it to the
* log driver will cause the diagnostics to be buffered and displayed.
*/
-#define PRINTF_PROC LOG_PROC_NR /* TTY or LOG_PROC_NR */
+#define PRINTF_PROC TTY /* TTY or LOG_PROC_NR */
/* NR_CONS, NR_RS_LINES, and NR_PTYS determine the number of terminals the
* system can handle.
*/
if ((next_timeout <= realtime) || (proc_ptr->p_sched_ticks <= 0)) {
prev_ptr = proc_ptr; /* store running process */
- lock_alert(HARDWARE, CLOCK); /* send notification */
+ lock_notify(HARDWARE, CLOCK); /* send notification */
}
return(1); /* reenable interrupts */
}
/* Buffer to gather randomness. This is used to generate a random stream by
* the MEMORY driver when reading from /dev/random.
*/
-#define RANDOM_ELEMENTS 64
+#define RANDOM_ELEMENTS 32
/* This section contains defines for valuable system resources that are used
#define VDEVIO_BUF_SIZE 64 /* max elements per VDEVIO request */
#define VCOPY_VEC_SIZE 16 /* max elements per VCOPY request */
-#if TEMP_CODE
-/* How many buffers for notification messages should there be? */
-#define NR_NOTIFY_BUFS 32
-#endif
/* How many bytes for the kernel stack. Space allocated in mpx.s. */
#define K_STACK_BYTES 1024
EXTERN int sched_ticks; /* keep track of quantum usage */
EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */
-#if TEMP_CODE
-/* Declare buffer space and a bit map for notification messages. */
-EXTERN struct notification notify_buffer[NR_NOTIFY_BUFS];
-EXTERN bitchunk_t notify_bitmap[BITMAP_CHUNKS(NR_NOTIFY_BUFS)];
-#endif
-
#if (CHIP == INTEL)
#define SEND 1 /* 0 0 0 1 : blocking send */
#define RECEIVE 2 /* 0 0 1 0 : blocking receive */
#define SENDREC 3 /* 0 0 1 1 : SEND + RECEIVE */
-#define ALERT 4 /* 0 1 0 0 : nonblocking notify */
+#define NOTIFY 4 /* 0 1 0 0 : nonblocking notify */
#define ECHO 8 /* 1 0 0 0 : echo a message */
-#define NOTIFY 16 /* 1 0 0 0 0 : temp */
-
/* The following bit masks determine what checks that should be done. */
#define CHECK_PTR 0x0B /* 1 0 1 1 : validate message buffer */
#define CHECK_DST 0x05 /* 0 1 0 1 : validate message destination */
/*==========================================================================*
* prepare_shutdown *
*==========================================================================*/
-PUBLIC void prepare_shutdown(tp)
-timer_t *tp;
+PUBLIC void prepare_shutdown(how)
+int how;
{
-/* This function prepares to shutdown MINIX. It is called by a watchdog
- * timer if this is a normal abort so that the sys_abort() call can return
- * first. The timer structure passes the shutdown status as an argument.
- */
+/* This function prepares to shutdown MINIX. */
register struct proc *rp;
static timer_t shutdown_timer;
- int how = tmr_arg(tp)->ta_int;
message m;
/* Show debugging dumps on panics. Make sure that the TTY task is still
* lock_sched: a process has run too long; schedule another one
*
* Changes:
- * , 2005 better protection in sys_call() (Jorrit N. Herder)
+ * Jul 25, 2005 better protection in sys_call() (Jorrit N. Herder)
* May 26, 2005 optimized message passing functions (Jorrit N. Herder)
* May 24, 2005 new, queued NOTIFY system call (Jorrit N. Herder)
* Oct 28, 2004 new, non-blocking SEND and RECEIVE (Jorrit N. Herder)
message *m_ptr, unsigned flags) );
FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src,
message *m_ptr, unsigned flags) );
-FORWARD _PROTOTYPE( int mini_alert, (struct proc *caller_ptr, int dst) );
-FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst,
- message *m_ptr ) );
+FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst) );
FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
FORWARD _PROTOTYPE( void pick_proc, (void) );
-#if TEMP_CODE
-#define BuildOldMess(m,n) \
- (m).NOTIFY_SOURCE = (n)->n_source, \
- (m).NOTIFY_TYPE = (n)->n_type, \
- (m).NOTIFY_FLAGS = (n)->n_flags, \
- (m).NOTIFY_ARG = (n)->n_arg;
-#endif
-
#define BuildMess(m_ptr, src, dst_ptr) \
(m_ptr)->m_source = (src); \
(m_ptr)->m_type = NOTIFY_FROM(src); \
*/
switch(function) {
case SENDREC:
- caller_ptr->p_priv->s_flags |= SENDREC_BUSY;
+ /* A flag is set so that notifications cannot interrupt SENDREC. */
+ priv(caller_ptr)->s_flags |= SENDREC_BUSY;
/* fall through */
case SEND:
result = mini_send(caller_ptr, src_dst, m_ptr, flags);
break; /* done, or SEND failed */
} /* fall through for SENDREC */
case RECEIVE:
- if(function == RECEIVE)
- caller_ptr->p_priv->s_flags &= ~SENDREC_BUSY;
+ if (function == RECEIVE)
+ priv(caller_ptr)->s_flags &= ~SENDREC_BUSY;
result = mini_receive(caller_ptr, src_dst, m_ptr, flags);
break;
- case ALERT:
- result = mini_alert(caller_ptr, src_dst);
- break;
case NOTIFY:
- result = mini_notify(caller_ptr, src_dst, m_ptr);
+ result = mini_notify(caller_ptr, src_dst);
break;
case ECHO:
CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, caller_ptr, m_ptr);
if (!(caller_ptr->p_rts_flags & SENDING)) {
/* Check if there are pending notifications, except for SENDREC. */
- if (! (caller_ptr->p_priv->s_flags & SENDREC_BUSY)) {
+ if (! (priv(caller_ptr)->s_flags & SENDREC_BUSY)) {
map = &priv(caller_ptr)->s_notify_pending;
for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) {
CopyMess(src_proc_nr, proc_addr(HARDWARE), &m, caller_ptr, m_ptr);
return(OK); /* report success */
}
-
-#if TEMP_CODE
- ntf_q_pp = &caller_ptr->p_ntf_q; /* get pointer pointer */
- while (*ntf_q_pp != NULL) {
- if (src == ANY || src == (*ntf_q_pp)->n_source) {
- /* Found notification. Assemble and copy message. */
- BuildOldMess(m, *ntf_q_pp);
- if (m.m_source == HARDWARE) {
- m.NOTIFY_ARG = caller_ptr->p_priv->s_int_pending;
- caller_ptr->p_priv->s_int_pending = 0;
- }
- CopyMess((*ntf_q_pp)->n_source, proc_addr(HARDWARE), &m,
- caller_ptr, m_ptr);
- /* Remove notification from queue and bit map. */
- bit_nr = (int) (*ntf_q_pp - ¬ify_buffer[0]);
- *ntf_q_pp = (*ntf_q_pp)->n_next;/* remove from queue */
- free_bit(bit_nr, notify_bitmap, NR_NOTIFY_BUFS);
- return(OK); /* report success */
- }
- ntf_q_pp = &(*ntf_q_pp)->n_next; /* proceed to next */
- }
}
-#endif
/* Check caller queue. Use pointer pointers to keep code simple. */
xpp = &caller_ptr->p_caller_q;
while (*xpp != NIL_PROC) {
- if (src == ANY || src == proc_nr(*xpp)) {
+ if (src == ANY || src == proc_nr(*xpp)) {
/* Found acceptable message. Copy it and update status. */
CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr);
if (((*xpp)->p_rts_flags &= ~SENDING) == 0) ready(*xpp);
}
xpp = &(*xpp)->p_q_link; /* proceed to next */
}
-
}
/* No suitable message is available or the caller couldn't send in SENDREC.
/*===========================================================================*
- * mini_alert *
+ * mini_notify *
*===========================================================================*/
-PRIVATE int mini_alert(caller_ptr, dst)
+PRIVATE int mini_notify(caller_ptr, dst)
register struct proc *caller_ptr; /* sender of the notification */
int dst; /* which process to notify */
{
* can be both sending and receiving during a SENDREC system call.
*/
if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING &&
- !(dst_ptr->p_priv->s_flags & SENDREC_BUSY) &&
+ ! (priv(dst_ptr)->s_flags & SENDREC_BUSY) &&
(dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
/* Destination is indeed waiting for a message. Assemble a notification
}
-/*===========================================================================*
- * mini_notify *
- *===========================================================================*/
-PRIVATE int mini_notify(caller_ptr, dst, m_ptr)
-register struct proc *caller_ptr; /* process trying to notify */
-int dst; /* which process to notify */
-message *m_ptr; /* pointer to message buffer */
-{
- register struct proc *dst_ptr = proc_addr(dst);
- register struct notification *ntf_p ;
- register struct notification **ntf_q_pp;
- int ntf_index;
- message ntf_mess;
-
- /* Check to see if target is blocked waiting for this message. A process
- * can be both sending and receiving during a SENDREC system call.
- */
- if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING &&
- (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) {
-
- /* Destination is indeed waiting for this message. Check if the source
- * is HARDWARE; this is a special case that gets the map of pending
- * interrupts as an argument. Then deliver the notification message.
- */
- if (proc_nr(caller_ptr) == HARDWARE) {
- m_ptr->NOTIFY_ARG = priv(dst_ptr)->s_int_pending;
- priv(dst_ptr)->s_int_pending = 0;
- }
-
- CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr, dst_ptr, dst_ptr->p_messbuf);
- dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */
- if (dst_ptr->p_rts_flags == 0) ready(dst_ptr);
- return(OK);
- }
-
- /* Destination is not ready. Add the notification to the pending queue.
- * Get pointer to notification message. Don't copy if already in kernel.
- */
- if (! iskernelp(caller_ptr)) {
- CopyMess(proc_nr(caller_ptr), caller_ptr, m_ptr,
- proc_addr(HARDWARE), &ntf_mess);
- m_ptr = &ntf_mess;
- }
-
- /* Enqueue the message. Existing notifications with the same source
- * and type are overwritten with newer ones. New notifications that
- * are not yet on the list are added to the end.
- */
- ntf_q_pp = &dst_ptr->p_ntf_q;
- while (*ntf_q_pp != NULL) {
- /* Replace notifications with same source and type. */
- if ((*ntf_q_pp)->n_type == m_ptr->NOTIFY_TYPE &&
- (*ntf_q_pp)->n_source == proc_nr(caller_ptr)) {
- (*ntf_q_pp)->n_flags = m_ptr->NOTIFY_FLAGS;
- (*ntf_q_pp)->n_arg = m_ptr->NOTIFY_ARG;
- return(OK);
- }
- ntf_q_pp = &(*ntf_q_pp)->n_next;
- }
-
- /* Add to end of queue (found above). Get a free notification buffer. */
- if ((ntf_index = alloc_bit(notify_bitmap, NR_NOTIFY_BUFS)) < 0)
- return(ENOSPC);
- ntf_p = ¬ify_buffer[ntf_index]; /* get pointer to buffer */
- ntf_p->n_source = proc_nr(caller_ptr);/* store notification data */
- ntf_p->n_type = m_ptr->NOTIFY_TYPE;
- ntf_p->n_flags = m_ptr->NOTIFY_FLAGS;
- ntf_p->n_arg = m_ptr->NOTIFY_ARG;
- *ntf_q_pp = ntf_p; /* add to end of queue */
- ntf_p->n_next = NULL; /* mark new end of queue */
- return(OK);
-}
-
/*==========================================================================*
* lock_notify *
*==========================================================================*/
-PUBLIC int lock_alert(src, dst)
+PUBLIC int lock_notify(src, dst)
int src; /* sender of the notification */
int dst; /* who is to be notified */
{
/* Exception or interrupt occurred, thus already locked. */
if (k_reenter >= 0) {
- result = mini_alert(proc_addr(src), dst);
+ result = mini_notify(proc_addr(src), dst);
}
/* Call from task level, locking is required. */
else {
- lock(0, "alert");
- result = mini_alert(proc_addr(src), dst);
+ lock(0, "notify");
+ result = mini_notify(proc_addr(src), dst);
unlock(0);
}
return(result);
/* main.c */
_PROTOTYPE( void main, (void) );
-_PROTOTYPE( void prepare_shutdown, (struct timer *tp) );
+_PROTOTYPE( void prepare_shutdown, (int how) );
/* utility.c */
_PROTOTYPE( void kprintf, (const char *fmt, ...) );
_PROTOTYPE( void panic, (_CONST char *s, int n) );
-_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) );
/* proc.c */
_PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) );
-_PROTOTYPE( int lock_alert, (int src, int dst) );
+_PROTOTYPE( int lock_notify, (int src, int dst) );
_PROTOTYPE( int lock_send, (int dst, message *m_ptr) );
_PROTOTYPE( void lock_ready, (struct proc *rp) );
_PROTOTYPE( void lock_sched, (struct proc *rp) );
* the lowest bytes because the highest bytes won't differ that much.
*/
int r_next;
- unsigned long tsc_high;
+ unsigned long tsc_high, tsc_low;
/* On machines with the RDTSC (cycle counter read instruction - pentium
* and up), use that for high-resolution raw entropy gathering. Otherwise,
*/
source %= RANDOM_SOURCES;
r_next= krandom.bin[source].r_next;
- if(machine.processor > 486 && 0)
- read_tsc(&tsc_high, &krandom.bin[source].r_buf[r_next]);
- else
- krandom.bin[source].r_buf[r_next] = read_clock();
- if (krandom.bin[source].r_size < RANDOM_ELEMENTS)
+ if(machine.processor > 486) {
+ read_tsc(&tsc_high, &tsc_low);
+ krandom.bin[source].r_buf[r_next] = tsc_low;
+ } else {
+ krandom.bin[source].r_buf[r_next] = read_clock();
+ }
+ if (krandom.bin[source].r_size < RANDOM_ELEMENTS) {
krandom.bin[source].r_size ++;
+ }
krandom.bin[source].r_next = (r_next + 1 ) % RANDOM_ELEMENTS;
}
priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->irq);
/* Build notification message and return. */
- lock_alert(HARDWARE, hook->proc_nr);
+ lock_notify(HARDWARE, hook->proc_nr);
return(hook->policy & IRQ_REENABLE);
}
rp = proc_addr(proc_nr);
sigaddset(&priv(rp)->s_sig_pending, sig_nr);
- lock_alert(SYSTEM, proc_nr);
+ lock_notify(SYSTEM, proc_nr);
}
* or ESC after debugging dumps).
*/
int how = m_ptr->ABRT_HOW;
- timer_t *tp;
/* See if the monitor is to run the specified instructions. */
if (how == RBT_MONITOR) {
phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
}
- /* Set a watchdog timer to shut down, so that this call returns first.
- * The timer will expire at the next clock tick, which can be any moment.
- * The CLOCK task is only scheduled when the SYSTEM task is done, though.
- */
- tp = &priv(proc_addr(KERNEL))->s_alarm_timer;
- tmr_arg(tp)->ta_int = how; /* pass status as timer argument */
- set_timer(tp, get_uptime(), prepare_shutdown);
+ /* Now prepare to shutdown MINIX. */
+ prepare_shutdown(how);
return(OK); /* pro-forma (really EDISASTER) */
}
* alarm. The process number is stored in timer argument 'ta_int'. Notify that
* process with a notification message from CLOCK.
*/
- lock_alert(CLOCK, tmr_arg(tp)->ta_int);
+ lock_notify(CLOCK, tmr_arg(tp)->ta_int);
}
#endif /* USE_SETALARM */
phys_clicks size; /* size of memory chunk */
};
-typedef unsigned long notify_mask_t; /* bit mask for notifications */
-typedef short notify_type_t; /* notification type */
-typedef char notify_flags_t; /* notification flags */
-typedef int notify_arg_t; /* notification argument */
-
-struct notification {
- proc_nr_t n_source; /* sender of notification */
- notify_type_t n_type; /* notification type */
- notify_arg_t n_arg; /* notification argument */
- notify_flags_t n_flags; /* notification flags */
- struct notification* n_next; /* pointer to next notification */
-};
-
/* The kernel outputs diagnostic messages in a circular buffer. */
struct kmessages {
int km_next; /* next index to write */
struct {
int r_next; /* next index to write */
int r_size; /* number of random elements */
- unsigned long r_buf[RANDOM_ELEMENTS]; /* buffer for random info */
+ unsigned short r_buf[RANDOM_ELEMENTS]; /* buffer for random info */
} bin[RANDOM_SOURCES];
};
{
/* The system has run aground of a fatal kernel error. Terminate execution. */
static int panicking = 0;
- timer_t *tp;
if (panicking ++) return; /* prevent recursive panics */
if (mess != NULL) {
kprintf("\n",NO_NUM);
}
- /* Make a direct call to shutdown. Interface requires to pass the shutdown
- * status by means of a timer.
- */
- tp = &priv(proc_addr(KERNEL))->s_alarm_timer;
- tmr_arg(tp)->ta_int = RBT_PANIC;
- prepare_shutdown(tp);
+ /* Abort MINIX. */
+ prepare_shutdown(RBT_PANIC);
}
}
-
-#if TEMP_CODE
-
-/*===========================================================================*
- * free_bit *
- *===========================================================================*/
-PUBLIC void free_bit(bit_nr, bitmap, nr_bits)
-bit_t bit_nr;
-bitchunk_t *bitmap;
-bit_t nr_bits;
-{
- bitchunk_t *chunk;
- if (bit_nr >= nr_bits) {
- kprintf("Warning, free_bit: %d illegal index\n", bit_nr);
- return;
- }
- chunk = &bitmap[(bit_nr/BITCHUNK_BITS)];
- *chunk &= ~(1 << (bit_nr % BITCHUNK_BITS));
-}
-
-/*===========================================================================*
- * alloc_bit *
- *===========================================================================*/
-PUBLIC int alloc_bit(bitmap, nr_bits)
-bitchunk_t *bitmap;
-bit_t nr_bits;
-{
- bitchunk_t *chunk;
- int nr_chunks;
- int bit_nr;
- int i;
-
- /* Iterate over the words in block. */
- nr_chunks = BITMAP_CHUNKS(nr_bits);
- for (chunk = &bitmap[0]; chunk < &bitmap[nr_chunks]; chunk++) {
-
- /* Does this chunk contain a free bit? */
- if (*chunk == (bitchunk_t) ~0) continue;
-
- /* Get bit number from the start of the bit map. */
- for (i = 0; (*chunk & (1 << i)) != 0; ++i) {}
- bit_nr = (chunk - &bitmap[0]) * BITCHUNK_BITS + i;
-
- /* Don't allocate bits beyond the end of the map. */
- if (bit_nr >= nr_bits) break;
-
- *chunk |= 1 << bit_nr % BITCHUNK_BITS;
- return(bit_nr);
-
- }
- return(-1);
-}
-
-#endif
! See src/kernel/ipc.h for C definitions
SEND = 1
RECEIVE = 2
-SENDREC = 3 + 32 ! flags 0x20 to request fresh answer
+SENDREC = 3
NOTIFY = 16
ALERT = 4
ECHO = 8
/* A server must occasionally print some message. It uses a simple version of
* printf() found in the system lib that calls kputc() to output characters.
* Printing is done with a call to the kernel, and not by going through FS.
- * This way system messages end up in the kernel messages buffer and can be
- * reviewed at a later time.
*
* This routine can only be used by servers and device drivers. The kernel
* must define its own kputc(). Note that the log driver also defines its own
message m;
if ((c == 0 && buf_count > 0) || buf_count == sizeof(print_buf)) {
- /* Send the buffer to the system task, or, if this process is not a
- * server yet, to standard error.
- */
+
+ /* Send the buffer to the PRINTF_PROC driver. */
m.DIAG_BUF_COUNT = buf_count;
m.DIAG_PRINT_BUF = print_buf;
m.DIAG_PROC_NR = SELF;
m.m_type = DIAGNOSTICS;
- if (_sendrec(PRINTF_PROC, &m) != 0) {
- m.m1_i1 = 2;
- m.m1_i2 = buf_count;
- m.m1_p1 = print_buf;
- m.m_type = WRITE;
- (void) _sendrec(FS, &m);
- }
+ (void) _sendrec(PRINTF_PROC, &m);
buf_count = 0;
+
+ /* If the output fails, e.g., due to an ELOCKED, do not retry output
+ * at the FS as if this were a normal user-land printf(). This may
+ * result in even worse problems.
+ */
+ }
+ if (c != 0) {
+
+ /* Append a single character to the output buffer. */
+ print_buf[buf_count++] = c;
}
- if (c != 0) print_buf[buf_count++] = c;
}