* ticks. Disabling the alarm is not needed, because a static flag is used
* and a leftover timeout cannot do any harm.
*/
- static int timeout_flag = 0; /* must be static, not cancelled */
+ static int timeout_flag; /* must be static, not cancelled */
int s;
timeout_flag = 0;
sys_flagalrm(TIMEOUT_TICKS, &timeout_flag);
#include "../drivers.h"
#include "../libdriver/driver.h"
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
#include <sys/ioc_memory.h>
#define NR_DEVS 7 /* number of minor devices */
PRIVATE int m_device; /* current device */
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 };
+PRIVATE struct memory mem[NR_MEMS]; /* physical memory chunks */
+FORWARD _PROTOTYPE( int alloc_mem, (phys_bytes size, phys_bytes *base) );
+FORWARD _PROTOTYPE( char *m_name, (void) );
FORWARD _PROTOTYPE( struct device *m_prepare, (int device) );
FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position,
iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( void m_init, (void) );
FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) );
-FORWARD _PROTOTYPE( char *m_name, (void) );
-
/* Entry points to this driver. */
PRIVATE struct driver m_dtab = {
PRIVATE char random[RANDOM_BUF_SIZE];
+#define click_to_round_k(n) \
+ ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024))
+
+
/*===========================================================================*
* main *
*===========================================================================*/
PUBLIC void main(void)
{
- m_init();
- driver_task(&m_dtab);
+ m_init(); /* initialize the memory driver */
+ driver_task(&m_dtab); /* start driver's main loop */
}
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, or /dev/boot. */
- int device;
+/* Read or write one the driver's minor devices. */
phys_bytes mem_phys, user_phys;
int seg;
unsigned count, left, chunk;
int s;
/* Get minor device number and check for /dev/null. */
- device = m_device;
- dv = &m_geom[device];
+ dv = &m_geom[m_device];
dv_size = cv64ul(dv->dv_size);
while (nr_req > 0) {
count = iov->iov_size;
user_vir = iov->iov_addr;
- switch (device) {
+ switch (m_device) {
/* No copying; ignore request. */
case NULL_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];
+ seg = m_seg[m_device];
if (opcode == DEV_GATHER) { /* copy actual data */
sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count);
PRIVATE void m_init()
{
/* Initialize this task. All minor devices are initialized one by one. */
- int i,s;
-
- /* Print welcome message. */
- printf("MEMORY: user-level memory (RAM, etc.) driver is alive\n");
+ int i, s;
- /* Get kernel info for memory addresses of kernel and boot device. */
+ /* Get memory addresses from the kernel. */
+ if (OK != (s=sys_getmemchunks(&mem))) {
+ server_panic("MEM","Couldn't get memory chunks.",s);
+ }
if (OK != (s=sys_getkinfo(&kinfo))) {
server_panic("MEM","Couldn't get kernel information.",s);
}
}
}
- psinfo.proc = kinfo.proc_addr;
-
/* Initialize /dev/random and /dev/zero. */
for (i=0; i<ZERO_BUF_SIZE; i++) {
zero[i] = '\0';
#error /* memory limit not set up */
#endif /* !(CHIP == M68000) */
#endif /* !(CHIP == INTEL) */
+
+ /* Initialization succeeded. Print welcome message. */
+ printf("User-space memory driver (RAM disk, etc.) has been initialized.\n");
}
* m_ioctl *
*===========================================================================*/
PRIVATE int m_ioctl(dp, m_ptr)
-struct driver *dp;
-message *m_ptr; /* pointer to read or write message */
+struct driver *dp; /* pointer to driver structure */
+message *m_ptr; /* pointer to control message */
{
-/* Set parameters for the RAM disk. */
-
+/* I/O controls for the memory driver. Currently there is one I/O control:
+ * - MIOCRAMSIZE: to set the size of the RAM disk.
+ */
struct device *dv;
-
if ((dv = m_prepare(m_ptr->DEVICE)) == NIL_DEV) return(ENXIO);
switch (m_ptr->REQUEST) {
case MIOCRAMSIZE: {
/* FS wants to create a new RAM disk with the given size. */
- unsigned long ramdev_size;
+ phys_bytes ramdev_size;
phys_bytes ramdev_base;
int s;
/* Try to allocate a piece of memory for the RAM disk. */
ramdev_size = m_ptr->POSITION;
+ if (OK != (s=alloc_mem(ramdev_size, &ramdev_base)))
+ server_panic("MEM","Couldn't allocate kernel memory", s);
+ dv->dv_base = cvul64(ramdev_base);
+ dv->dv_size = cvul64(ramdev_size);
+ printf("Test MEM: base 0x%06x, size 0x%06x\n", dv->dv_base, dv->dv_size);
+
if (OK != (s=sys_kmalloc(ramdev_size, &ramdev_base)))
server_panic("MEM","Couldn't allocate kernel memory", s);
dv->dv_base = cvul64(ramdev_base);
dv->dv_size = cvul64(ramdev_size);
+ printf("Real MEM: base 0x%06x, size 0x%06x\n", dv->dv_base, dv->dv_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
- * server??? (Note that psinfo is global; psinfo.proc is set in m_init.)
- * This requires changes to ioctl as well.
- */
- case MIOCSPSINFO: {
- /* MM or FS set the address of their process table. */
- phys_bytes psinfo_phys;
-
- if (m_ptr->PROC_NR == PM_PROC_NR) {
- psinfo.mproc = (vir_bytes) m_ptr->ADDRESS;
- } else if (m_ptr->PROC_NR == FS_PROC_NR) {
- psinfo.fproc = (vir_bytes) m_ptr->ADDRESS;
- } else {
- return(EPERM);
- }
- break;
- }
- case MIOCGPSINFO: {
- /* The ps program wants the process table addresses. */
- if (sys_datacopy(SELF, (vir_bytes) &psinfo,
- m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
- sizeof(psinfo)) != OK) return(EFAULT);
break;
}
entry->heads = 64;
entry->sectors = 32;
}
+
+/*===========================================================================*
+ * malloc_mem *
+ *===========================================================================*/
+PRIVATE int alloc_mem(chunk_size, chunk_base)
+phys_bytes chunk_size; /* number of bytes requested */
+phys_bytes *chunk_base; /* base of memory area found */
+{
+/* Request a piece of memory from one of the free memory chunks. */
+ phys_clicks tot_clicks;
+ struct memory *memp;
+
+ tot_clicks = (chunk_size+ CLICK_SIZE-1) >> CLICK_SHIFT;
+ memp = &mem[NR_MEMS];
+ while ((--memp)->size < tot_clicks) {
+ if (memp == mem) {
+ return(ENOMEM);
+ }
+ }
+ memp->size -= tot_clicks;
+ *chunk_base = (memp->base + memp->size) << CLICK_SHIFT;
+ return(OK);
+}
+
#include <net/gen/ether.h>
#include <net/gen/eth_io.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioc_memory.h>
+#include "../../kernel/type.h"
+
#if __minix_vmd
#include "config.h"
#include "timer.h"
{
size_t rx_bufsize, tx_bufsize, tot_bufsize;
phys_bytes buf;
- int i;
+ static struct memory chunk;
+ int fd, s, i;
/* Allocate receive and transmit buffers */
tx_bufsize= ETH_MAX_PACK_SIZE_TAGGED;
#if __minix_vmd
buf= (phys_bytes)kalloc_dma_128K(tot_bufsize, FALSE /* not low */);
#else
+
/* Now try to allocate a kernel memory buffer. */
+ chunk.size = tot_bufsize;
+#if DEAD_CODE
+ fd = open("/dev/mem", O_RDONLY);
+ if (fd <0) {
+ printf("RTL8139: warning, couldn't open: %d\n", fd);
+ } else {
+ if (OK != (s=ioctl(fd, MIOCGETCHUNK, &chunk)))
+ printf("RTL8139: ioctl failed: %d\n", s);
+ else
+ printf("RTL8139: %uK buffer from mem at 0x06%x\n",
+ chunk.size, chunk.base);
+ }
+ close(fd);
+#endif
+
if (OK != (i=sys_kmalloc(tot_bufsize, &buf)))
server_panic("RTL8139","Couldn't allocate kernel buffer",i);
+ printf("RTL8139: real %uK buffer at 0x%06x\n", tot_bufsize, buf);
#endif
for (i= 0; i<N_TX_BUF; i++)
{
if (!(rl_inb(port, RL_BMCR) & MII_CTRL_RST))
break;
} while (! timeout);
- sys_flagalrm(0, &timeout);
+ sys_flagalrm(0, &timeout); /* for correctness */
if (rl_inb(port, RL_BMCR) & MII_CTRL_RST)
server_panic("rtl8139","reset PHY failed to complete", NO_NUM);
#endif
if (!(rl_inb(port, RL_CR) & RL_CR_RST))
break;
} while (! timeout);
- sys_flagalrm(0, &timeout);
+ sys_flagalrm(0, &timeout); /* for correctness */
if (rl_inb(port, RL_CR) & RL_CR_RST)
server_panic("rtl8139","reset failed to complete", NO_NUM);
if (!(rl_inb(port, RL_CR) & RL_CR_RE))
break;
} while (! timeout);
- sys_flagalrm(0, &timeout);
+ sys_flagalrm(0, &timeout); /* for correctness */
if (rl_inb(port, RL_CR) & RL_CR_RE)
server_panic("rtl8139","cannot disable receiver", NO_NUM);
if (!(rl_inb(port, RL_CR) & RL_CR_TE))
break;
} while (! timeout);
- sys_flagalrm(0, &timeout);
+ sys_flagalrm(0, &timeout); /* for correctness */
if (rl_inb(port, RL_CR) & RL_CR_TE)
{
server_panic("rtl8139","cannot disable transmitter",
if (inb_reg3(dep, 1) & 1)
break;
} while (! timeout);
- sys_flagalrm(0, &timeout);
+ sys_flagalrm(0, &timeout); /* for correctness */
if (!(inb_reg3(dep, 1) & 1))
server_panic("set_ee_word","device remains busy", NO_NUM);
}
#include <minix/ioctl.h>
#define MIOCRAMSIZE _IOW('m', 3, u32_t)
-#define MIOCSPSINFO _IOW('m', 4, void *)
-#define MIOCGPSINFO _IOR('m', 5, struct psinfo)
-#define MIOCINT86 _IORW('m', 6, struct mio_int86)
-#define MIOCGLDT86 _IORW('m', 7, struct mio_ldt86)
-#define MIOCSLDT86 _IOW('m', 8, struct mio_ldt86)
#endif /* _S_I_MEMORY_H */
/* How many IRQ hooks are there in total. */
#define NR_IRQ_HOOKS 16
+/* How many notification buffers (12B each) should there be? */
+#define NR_NOTIFY_BUFS 128
+
/* Program stack words and masks. */
#define INIT_PSW 0x0200 /* initial psw */
#define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */
-#define TRACEBIT 0x100 /* OR this with psw in proc[] for tracing */
+#define TRACEBIT 0x0100 /* OR this with psw in proc[] for tracing */
#define SETPSW(rp, new) /* permits only certain bits to be set */ \
((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
#define IF_MASK 0x00000200
#define clear_bit(mask, n) ((mask) &= ~(1 << (n)))
#define isset_bit(mask, n) ((mask) & (1 << (n)))
+/* Declare buffer space for notifications. */
+PRIVATE struct notification notify_buf[NR_NOTIFY_BUFS];
/*===========================================================================*
* lock_notify *
unsigned int notify_bit; /* bit for this notification */
/* Get notify bit and process pointer. */
- notify_bit = (unsigned int) (notify_type - NOTIFICATION);
+ notify_bit = (unsigned int) (notify_type & ~NOTIFICATION);
rp = proc_addr(proc_nr);
/* If this call would compete with other process-switching functions, put
* reply and may not block if the caller doesn't do receive(). Users also
* may only use sendrec() to protect the process manager and file system.
*/
+#if DEAD_CODE
if ((iskernel(src_dst) || isuserp(caller_ptr)) && function != BOTH) {
+#else
+ if (iskernel(src_dst) && function != BOTH) {
+#endif
result = ECALLDENIED; /* BOTH was required */
}
* priority of other messages.
*/
if (caller_ptr->p_ntf_blocked && isrxhardware(src)) {
- for (i=0; i<NR_NOTIFICATIONS; i++) {
+ for (i=0; i<NR_NOTIFY_TYPES; i++) {
if (isset_bit(caller_ptr->p_ntf_blocked, i)) {
m.m_source = HARDWARE;
- m.m_type = NOTIFICATION + i;
+ m.m_type = NOTIFICATION | i;
CopyMess(HARDWARE, proc_addr(HARDWARE), &m, caller_ptr, m_ptr);
clear_bit(caller_ptr->p_ntf_blocked, i);
return(OK);
if (switching) return;
rp = held_head;
do {
- for (i=0; i<NR_NOTIFICATIONS; i++) {
+ for (i=0; i<NR_NOTIFY_TYPES; i++) {
if (isset_bit(rp->p_ntf_held,i)) {
clear_bit(rp->p_ntf_held,i);
if (! rp->p_ntf_held) /* proceed to next in queue? */
#if DEAD_CODE
unlock(); /* reduce latency; held queue may change! */
#endif
- lock_notify(proc_number(rp), NOTIFICATION + i);
+ lock_notify(proc_number(rp), NOTIFICATION | i);
#if DEAD_CODE
lock(); /* protect the held queue again */
#endif
reg_t *p_stguard; /* stack guard word */
- int p_nr; /* number of this process (for fast access) */
+ proc_nr_t p_nr; /* number of this process (for fast access) */
notify_mask_t p_ntf_blocked; /* bit mask for blocked notifications */
notify_mask_t p_ntf_held; /* bit mask for held up notify() calls */
struct proc *p_ntf_nextheld; /* next in chain of held-up int processes */
+ struct notification *p_ntfq; /* queue of pending notifications */
+
int p_flags; /* SENDING, RECEIVING, etc. */
struct mem_map p_memmap[NR_LOCAL_SEGS]; /* local memory map (T, D, S) */
struct far_mem p_farmem[NR_REMOTE_SEGS]; /* remote memory map */
- short p_type; /* task, system, driver, server, user, idle */
- short p_priority; /* scheduling priority */
+ char p_type; /* task, system, driver, server, user, idle */
+ char p_priority; /* scheduling priority */
clock_t user_time; /* user time in ticks */
clock_t sys_time; /* sys time in ticks */
int r = OK;
irq_hook_t *hook_ptr;
- irq_hook_id = (unsigned) m_ptr->IRQ_HOOK_ID;
+ /* Hook identifiers start at 1 and end at NR_IRQ_HOOKS. */
+ irq_hook_id = (unsigned) m_ptr->IRQ_HOOK_ID - 1;
irq_vec = (unsigned) m_ptr->IRQ_VECTOR;
/* See what is requested and take needed actions. */
/* Enable or disable IRQs. This is straightforward. */
case IRQ_ENABLE:
case IRQ_DISABLE:
- if (irq_hook_id >= NR_IRQ_HOOKS) return(EINVAL);
+ if (irq_hook_id >= NR_IRQ_HOOKS ||
+ irq_hooks[irq_hook_id].proc_nr == NONE) return(EINVAL);
if (irq_hooks[irq_hook_id].proc_nr != m_ptr->m_source) return(EPERM);
if (m_ptr->IRQ_REQUEST == IRQ_ENABLE)
enable_irq(&irq_hooks[irq_hook_id]);
put_irq_handler(hook_ptr, irq_vec, generic_handler);
/* Return index of the IRQ hook in use. */
- m_ptr->IRQ_HOOK_ID = irq_hook_id;
+ m_ptr->IRQ_HOOK_ID = irq_hook_id + 1;
break;
case IRQ_RMPOLICY:
- if(irq_hook_id < 0 || irq_hook_id >= NR_IRQ_HOOKS ||
+ if (irq_hook_id >= NR_IRQ_HOOKS ||
irq_hooks[irq_hook_id].proc_nr == NONE) {
r = EINVAL;
} else {
- if(m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) {
+ if (m_ptr->m_source != irq_hooks[irq_hook_id].proc_nr) {
r = EPERM;
} else {
r = rm_irq_handler(irq_vec, irq_hooks[irq_hook_id].id);
*/
typedef long karg_t; /* use largest type here */
-typedef unsigned int notify_mask_t; /* bit mask for notifications */
+/* Process related types.
+ * A process number defines the index into the process table. With a signed
+ * short we can support up to 256 user processes and more kernel tasks than
+ * one can ever create.
+ */
+typedef int proc_nr_t; /* process table entry number */
typedef unsigned long send_mask_t; /* bit mask for sender */
struct system_image {
- int proc_nr; /* process number to use */
+ proc_nr_t proc_nr; /* process number to use */
task_t *initial_pc; /* start function for tasks */
int type; /* type of process */
int priority; /* scheduling priority */
phys_clicks size; /* size of memory chunk */
};
+typedef unsigned long notify_mask_t; /* bit mask for notifications */
+typedef char 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_fags; /* notification flags */
+ struct notification* n_next; /* pointer to next notification */
+};
#if (CHIP == INTEL)
typedef unsigned reg_t; /* machine register */
OBJECTS = \
$(LIBRARY)(__sigreturn.o) \
- $(LIBRARY)(_sendrec.o) \
+ $(LIBRARY)(_ipc.o) \
$(LIBRARY)(brksize.o) \
$(LIBRARY): $(OBJECTS)
$(LIBRARY)(__sigreturn.o): __sigreturn.s
$(CC1) __sigreturn.s
-$(LIBRARY)(_sendrec.o): _sendrec.s
- $(CC1) _sendrec.s
+$(LIBRARY)(_ipc.o): _ipc.s
+ $(CC1) _ipc.s
$(LIBRARY)(brksize.o): brksize.s
$(CC1) brksize.s
.sect .text; .sect .rom; .sect .data; .sect .bss
-.define __send, __receive, __sendrec
+.define __send, __nb_send, __receive, __nb_receive, __sendrec, __notify
! See ../h/com.h for C definitions
SEND = 1
RECEIVE = 2
BOTH = 3
+NOTIFY = 4
NB_SEND = 1 + 16 ! SEND | 0xF0
NB_RECEIVE = 2 + 16 ! RECEIVE | 0xF0
SYSVEC = 33
!*========================================================================*
! _send(), _nb_send(), _receive(), _nb_receive(), and _sendrec() all
! save ebp, but destroy eax and ecx.
-.define __send, __nb_send, __receive, __nb_receive, __sendrec
+.define __send, __nb_send, __receive, __nb_receive, __sendrec, __notify
.sect .text
__send:
push ebp
pop ebx
pop ebp
ret
+
+__notify:
+ push ebp
+ mov ebp, esp
+ push ebx
+ mov eax, SRCDEST(ebp) ! eax = dest-src
+ mov ebx, MESSAGE(ebp) ! ebx = message pointer
+ mov ecx, NOTIFY ! _notify(srcdest, ptr)
+ int SYSVEC ! trap to the kernel
+ pop ebx
+ pop ebp
+ ret
+
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("- notify_held: %8u\n", kinfo.notify_held);
+ printf("- notify_blocked:%8u\n", kinfo.notify_blocked);
+ printf("- notify_switch: %8u\n", kinfo.notify_switching);
+ printf("- notify_reenter:%8u\n", kinfo.notify_reenter);
+ printf("- notify_ok: %8u\n", kinfo.notify_ok);
+ printf("- notify_unhold: %8u\n", kinfo.notify_unhold);
+ printf("- hard_int: %8u\n", kinfo.notify_int);
+ printf("- hard_stop: %8u\n", kinfo.notify_stop);
+ printf("- sync_alarm: %8u\n", kinfo.notify_alarm);
+ printf("- ksig_pending: %8u\n", kinfo.notify_sig);
+ printf("- new_kmess: %8u\n", kinfo.notify_kmess);
+ printf("- nr_procs: %3u\n", kinfo.nr_procs);
+ printf("- nr_tasks: %3u\n", kinfo.nr_tasks);
printf("- version: %.6s\n", kinfo.version);
printf("\n");
}
/* misc.c */
_PROTOTYPE( int do_reboot, (void) );
_PROTOTYPE( int do_getsysinfo, (void) );
+_PROTOTYPE( int do_getprocnr, (void) );
_PROTOTYPE( int do_svrctl, (void) );
_PROTOTYPE( int do_mstats, (void) );
no_sys, /* 78 = cmostime */
do_getsysinfo, /* 79 = getsysinfo */
-#if ENABLE_MESSAGE_STATS
- do_mstats, /* 80 = mstats */
-#else
- no_sys,
-#endif
+ do_getprocnr, /* 80 = getprocnr */
no_sys, /* 81 = unused */
no_sys, /* 82 = unused */
};
@echo "Root privileges are required." >&2
@echo " " >&2
@echo "Usage:" >&2
+ @echo " make includes # Install include files" >&2
@echo " make libraries # Make system libraries" >&2
@echo " make programs # Compile and install all programs" >&2
@echo " make fresh # Make clean, libraries, and programs" >&2
# rebuild the program or system libraries
-programs:
+includes:
cd ../include && $(MAKE) install
+
+programs: includes
cd ../kernel && $(MAKE)
cd ../servers && $(MAKE) install
cd ../drivers && $(MAKE) install
-libraries:
+libraries: includes
cd ../lib && $(MAKE) install