IOPL, VM, and serial debug output (disabled).
This commit is contained in:
parent
9528152f68
commit
9bee3f4b08
|
@ -44,6 +44,12 @@ EXTERN int irq_use; /* map of all in-use irq's */
|
|||
/* Miscellaneous. */
|
||||
EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */
|
||||
EXTERN int mon_return; /* true if we can return to monitor */
|
||||
EXTERN int do_serial_debug;
|
||||
|
||||
/* VM */
|
||||
EXTERN phys_bytes vm_base;
|
||||
EXTERN phys_bytes vm_size;
|
||||
EXTERN phys_bytes vm_mem_high;
|
||||
|
||||
/* Variables that are initialized elsewhere are just extern here. */
|
||||
extern struct boot_image image[]; /* system image processes */
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
.define _level0 ! call a function at level 0
|
||||
.define _read_tsc ! read the cycle counter (Pentium and up)
|
||||
.define _read_cpu_flags ! read the cpu flags
|
||||
.define _read_cr0 ! read cr0
|
||||
.define _write_cr0 ! write a value in cr0
|
||||
.define _write_cr3 ! write a value in cr3 (root of the page table)
|
||||
|
||||
! The routines only guarantee to preserve the registers the C compiler
|
||||
! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
|
||||
|
@ -572,3 +575,41 @@ _read_cpu_flags:
|
|||
popf
|
||||
ret
|
||||
|
||||
|
||||
!*===========================================================================*
|
||||
!* read_cr0 *
|
||||
!*===========================================================================*
|
||||
! PUBLIC unsigned long read_cr0(void);
|
||||
_read_cr0:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, cr0
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
!*===========================================================================*
|
||||
!* write_cr0 *
|
||||
!*===========================================================================*
|
||||
! PUBLIC void write_cr0(unsigned long value);
|
||||
_write_cr0:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, 8(ebp)
|
||||
mov cr0, eax
|
||||
jmp 0f ! A jump is required for some flags
|
||||
0:
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
!*===========================================================================*
|
||||
!* write_cr3 *
|
||||
!*===========================================================================*
|
||||
! PUBLIC void write_cr3(unsigned long value);
|
||||
_write_cr3:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, 8(ebp)
|
||||
mov cr3, eax
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ struct proc {
|
|||
struct priv *p_priv; /* system privileges structure */
|
||||
char p_rts_flags; /* SENDING, RECEIVING, etc. */
|
||||
|
||||
char p_misc_flags; /* Flags that do suspend the process */
|
||||
|
||||
char p_priority; /* current scheduling priority */
|
||||
char p_max_priority; /* maximum scheduling priority */
|
||||
char p_ticks_left; /* number of scheduling ticks left */
|
||||
|
@ -66,6 +68,9 @@ struct proc {
|
|||
#define P_STOP 0x40 /* set when process is being traced */
|
||||
#define NO_PRIV 0x80 /* keep forked system process from running */
|
||||
|
||||
/* Misc flags */
|
||||
#define MF_VM 0x01 /* Process uses VM */
|
||||
|
||||
/* Scheduling priorities for p_priority. Values must start at zero (highest
|
||||
* priority) and increment. Priorities of the processes in the boot image
|
||||
* can be set in table.c. IDLE must have a queue for itself, to prevent low
|
||||
|
|
|
@ -82,6 +82,9 @@ _PROTOTYPE( void reset, (void) );
|
|||
_PROTOTYPE( void level0, (void (*func)(void)) );
|
||||
_PROTOTYPE( void monitor, (void) );
|
||||
_PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) );
|
||||
_PROTOTYPE( unsigned long read_cr0, (void) );
|
||||
_PROTOTYPE( void write_cr0, (unsigned long value) );
|
||||
_PROTOTYPE( void write_cr3, (unsigned long value) );
|
||||
_PROTOTYPE( unsigned long read_cpu_flags, (void) );
|
||||
|
||||
/* mpx*.s */
|
||||
|
@ -142,6 +145,9 @@ _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) );
|
||||
|
||||
/* system/do_vm.c */
|
||||
_PROTOTYPE( void vm_map_default, (struct proc *pp) );
|
||||
|
||||
#endif /* (CHIP == INTEL) */
|
||||
|
||||
#if (CHIP == M68000)
|
||||
|
|
|
@ -75,7 +75,8 @@ PUBLIC void sys_task()
|
|||
caller_ptr = proc_addr(m.m_source);
|
||||
|
||||
/* See if the caller made a valid request and try to handle it. */
|
||||
if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr))) {
|
||||
if (! (priv(caller_ptr)->s_call_mask & (1<<call_nr)) &&
|
||||
m.m_type != SYS_IOPENABLE ) {
|
||||
kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);
|
||||
result = ECALLDENIED; /* illegal message type */
|
||||
} else if (call_nr >= NR_SYS_CALLS) { /* check call number */
|
||||
|
@ -152,6 +153,8 @@ PRIVATE void initialize(void)
|
|||
map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
|
||||
map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
|
||||
map(SYS_MEMSET, do_memset); /* write char to memory area */
|
||||
map(SYS_VM_SETBUF, do_vm_setbuf); /* PM passes buffer for page tables */
|
||||
map(SYS_VM_MAP, do_vm_map); /* Map/unmap physical (device) memory */
|
||||
|
||||
/* Copying. */
|
||||
map(SYS_UMAP, do_umap); /* map virtual to physical address */
|
||||
|
@ -167,6 +170,7 @@ PRIVATE void initialize(void)
|
|||
/* System control. */
|
||||
map(SYS_ABORT, do_abort); /* abort MINIX */
|
||||
map(SYS_GETINFO, do_getinfo); /* request system information */
|
||||
map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
@ -92,6 +92,9 @@ _PROTOTYPE( int do_memset, (message *m_ptr) );
|
|||
#define do_memset do_unused
|
||||
#endif
|
||||
|
||||
_PROTOTYPE( int do_vm_setbuf, (message *m_ptr) );
|
||||
_PROTOTYPE( int do_vm_map, (message *m_ptr) );
|
||||
|
||||
_PROTOTYPE( int do_abort, (message *m_ptr) );
|
||||
#if ! USE_ABORT
|
||||
#define do_abort do_unused
|
||||
|
@ -169,5 +172,7 @@ _PROTOTYPE( int do_setalarm, (message *m_ptr) );
|
|||
#define do_setalarm do_unused
|
||||
#endif
|
||||
|
||||
_PROTOTYPE( int do_iopenable, (message *m_ptr) );
|
||||
|
||||
#endif /* SYSTEM_H */
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@ OBJECTS = \
|
|||
$(SYSTEM)(do_sigreturn.o) \
|
||||
$(SYSTEM)(do_abort.o) \
|
||||
$(SYSTEM)(do_getinfo.o) \
|
||||
$(SYSTEM)(do_iopenable.o) \
|
||||
$(SYSTEM)(do_vm.o) \
|
||||
$(SYSTEM)(do_vm_setbuf.o) \
|
||||
|
||||
$(SYSTEM): $(OBJECTS)
|
||||
aal cr $@ *.o
|
||||
|
@ -138,3 +141,13 @@ $(SYSTEM)(do_privctl.o): do_privctl.c
|
|||
|
||||
$(SYSTEM)(do_segctl.o): do_segctl.c
|
||||
$(CC) do_segctl.c
|
||||
|
||||
$(SYSTEM)(do_iopenable.o): do_iopenable.c
|
||||
$(CC) do_iopenable.c
|
||||
|
||||
$(SYSTEM)(do_vm.o): do_vm.o
|
||||
do_vm.o: do_vm.c
|
||||
$(CC) do_vm.c
|
||||
|
||||
$(SYSTEM)(do_vm_setbuf.o): do_vm_setbuf.c
|
||||
$(CC) do_vm_setbuf.c
|
||||
|
|
|
@ -84,6 +84,10 @@ register struct proc *rc; /* slot of process to clean up */
|
|||
}
|
||||
}
|
||||
|
||||
/* Clean up virtual memory */
|
||||
if (rc->p_misc_flags & MF_VM)
|
||||
vm_map_default(rc);
|
||||
|
||||
/* 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
|
||||
|
|
33
kernel/system/do_iopenable.c
Normal file
33
kernel/system/do_iopenable.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* The system call implemented in this file:
|
||||
* m_type: SYS_IOPENABLE
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m2_i2: PROC_NR (process to give I/O Protection Level bits)
|
||||
*
|
||||
* Author:
|
||||
* Jorrit N. Herder <jnherder@cs.vu.nl>
|
||||
*/
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_iopenable *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_iopenable(m_ptr)
|
||||
register message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr;
|
||||
|
||||
#if 1 /* ENABLE_USERPRIV && ENABLE_USERIOPL */
|
||||
proc_nr= m_ptr->PROC_NR;
|
||||
if (proc_nr == SELF)
|
||||
proc_nr = m_ptr->m_source;
|
||||
enable_iop(proc_addr(proc_nr));
|
||||
return(OK);
|
||||
#else
|
||||
return(EPERM);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
245
kernel/system/do_vm.c
Normal file
245
kernel/system/do_vm.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VM_MAP
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l1: Process that requests map
|
||||
* m4_l2: Map (TRUE) or unmap (FALSE)
|
||||
* m4_l3: Base address
|
||||
* m4_l4: Size
|
||||
* m4_l5: Memory address
|
||||
*/
|
||||
#include "../system.h"
|
||||
|
||||
#include <sys/vm.h>
|
||||
|
||||
PRIVATE int vm_needs_init= 1;
|
||||
PRIVATE u32_t vm_cr3;
|
||||
|
||||
FORWARD _PROTOTYPE( void vm_init, (void) );
|
||||
FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
|
||||
FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
|
||||
FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
|
||||
FORWARD _PROTOTYPE( void set_cr3, (void) );
|
||||
FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
|
||||
FORWARD _PROTOTYPE( void map_range, (u32_t base, u32_t size,
|
||||
u32_t offset) );
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vm_setbuf *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vm_map(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
int proc_nr, do_map;
|
||||
phys_bytes base, size, offset, p_phys;
|
||||
struct proc *pp;
|
||||
|
||||
/* do_serial_debug= 1; */
|
||||
|
||||
kprintf("in do_vm_map\n");
|
||||
|
||||
if (vm_needs_init)
|
||||
{
|
||||
vm_needs_init= 0;
|
||||
vm_init();
|
||||
}
|
||||
|
||||
proc_nr= m_ptr->m4_l1;
|
||||
do_map= m_ptr->m4_l2;
|
||||
base= m_ptr->m4_l3;
|
||||
size= m_ptr->m4_l4;
|
||||
offset= m_ptr->m4_l5;
|
||||
|
||||
pp= proc_addr(proc_nr);
|
||||
p_phys= umap_local(pp, D, base, size);
|
||||
if (p_phys == 0)
|
||||
return EFAULT;
|
||||
kprintf("got 0x%x for 0x%x [D].mem_start = 0x%x\n",
|
||||
p_phys, base, pp->p_memmap[D].mem_phys);
|
||||
|
||||
if (do_map)
|
||||
{
|
||||
kprintf(
|
||||
"do_vm_map: mapping 0x%x @ 0x%x to 0x%x @ proc %d\n",
|
||||
size, offset, base, proc_nr);
|
||||
pp->p_misc_flags |= MF_VM;
|
||||
|
||||
map_range(p_phys, size, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
map_range(p_phys, size, p_phys);
|
||||
}
|
||||
vm_set_cr3(vm_cr3);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_map_default *
|
||||
*===========================================================================*/
|
||||
PUBLIC void vm_map_default(pp)
|
||||
struct proc *pp;
|
||||
{
|
||||
phys_bytes base_clicks, size_clicks;
|
||||
|
||||
if (vm_needs_init)
|
||||
panic("vm_map_default: VM not initialized?", NO_NUM);
|
||||
pp->p_misc_flags &= ~MF_VM;
|
||||
base_clicks= pp->p_memmap[D].mem_phys;
|
||||
size_clicks= pp->p_memmap[S].mem_phys+pp->p_memmap[S].mem_len -
|
||||
base_clicks;
|
||||
map_range(base_clicks << CLICK_SHIFT, size_clicks << CLICK_SHIFT,
|
||||
base_clicks << CLICK_SHIFT);
|
||||
vm_set_cr3(vm_cr3);
|
||||
}
|
||||
|
||||
PRIVATE void vm_init(void)
|
||||
{
|
||||
int o;
|
||||
phys_bytes p, pt_size;
|
||||
phys_bytes vm_dir_base, vm_pt_base, phys_mem;
|
||||
u32_t entry;
|
||||
unsigned pages;
|
||||
|
||||
kprintf("in vm_init\n");
|
||||
|
||||
kprintf("%s, %d\n", __FILE__, __LINE__);
|
||||
if (!vm_size)
|
||||
panic("vm_init: no space for page tables", NO_NUM);
|
||||
|
||||
/* Align page directory */
|
||||
o= (vm_base % PAGE_SIZE);
|
||||
if (o != 0)
|
||||
o= PAGE_SIZE-o;
|
||||
vm_dir_base= vm_base+o;
|
||||
|
||||
/* Page tables start after the page directory */
|
||||
vm_pt_base= vm_dir_base+PAGE_SIZE;
|
||||
|
||||
pt_size= (vm_base+vm_size)-vm_pt_base;
|
||||
pt_size -= (pt_size % PAGE_SIZE);
|
||||
|
||||
/* Compute the number of pages based on vm_mem_high */
|
||||
pages= (vm_mem_high-1)/PAGE_SIZE + 1;
|
||||
|
||||
if (pages * I386_VM_PT_ENT_SIZE > pt_size)
|
||||
panic("vm_init: page table too small", NO_NUM);
|
||||
|
||||
kprintf("%s, %d\n", __FILE__, __LINE__);
|
||||
|
||||
for (p= 0; p*I386_VM_PT_ENT_SIZE < pt_size; p++)
|
||||
{
|
||||
phys_mem= p*PAGE_SIZE;
|
||||
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
|
||||
I386_VM_PRESENT;
|
||||
if (phys_mem >= vm_mem_high)
|
||||
entry= 0;
|
||||
phys_put32(vm_pt_base + p*I386_VM_PT_ENT_SIZE, entry);
|
||||
}
|
||||
|
||||
for (p= 0; p < I386_VM_DIR_ENTRIES; p++)
|
||||
{
|
||||
phys_mem= vm_pt_base + p*PAGE_SIZE;
|
||||
entry= phys_mem | I386_VM_USER | I386_VM_WRITE |
|
||||
I386_VM_PRESENT;
|
||||
if (phys_mem >= vm_pt_base + pt_size)
|
||||
entry= 0;
|
||||
phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
|
||||
}
|
||||
|
||||
kprintf("%s, %d\n", __FILE__, __LINE__);
|
||||
vm_set_cr3(vm_dir_base);
|
||||
level0(vm_enable_paging);
|
||||
}
|
||||
|
||||
PRIVATE void phys_put32(addr, value)
|
||||
phys_bytes addr;
|
||||
u32_t value;
|
||||
{
|
||||
#if 0
|
||||
kprintf("%s, %d: %d bytes from 0x%x to 0x%x\n", __FILE__, __LINE__,
|
||||
sizeof(value), vir2phys((vir_bytes)&value), addr);
|
||||
#endif
|
||||
|
||||
phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value));
|
||||
}
|
||||
|
||||
PRIVATE u32_t phys_get32(addr)
|
||||
phys_bytes addr;
|
||||
{
|
||||
u32_t value;
|
||||
|
||||
phys_copy(addr, vir2phys((vir_bytes)&value), sizeof(value));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
PRIVATE void vm_set_cr3(value)
|
||||
u32_t value;
|
||||
{
|
||||
kprintf("%s, %d\n", __FILE__, __LINE__);
|
||||
vm_cr3= value;
|
||||
kprintf("%s, %d\n", __FILE__, __LINE__);
|
||||
level0(set_cr3);
|
||||
kprintf("%s, %d\n", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
PRIVATE void set_cr3()
|
||||
{
|
||||
write_cr3(vm_cr3);
|
||||
}
|
||||
|
||||
PRIVATE void vm_enable_paging(void)
|
||||
{
|
||||
u32_t cr0;
|
||||
|
||||
cr0= read_cr0();
|
||||
write_cr0(cr0 | I386_CR0_PG);
|
||||
}
|
||||
|
||||
PRIVATE void map_range(base, size, offset)
|
||||
u32_t base;
|
||||
u32_t size;
|
||||
u32_t offset;
|
||||
{
|
||||
u32_t curr_pt, curr_pt_addr, entry;
|
||||
int dir_ent, pt_ent;
|
||||
|
||||
if (base % PAGE_SIZE != 0)
|
||||
panic("map_range: bad base", base);
|
||||
if (size % PAGE_SIZE != 0)
|
||||
panic("map_range: bad size", size);
|
||||
if (offset % PAGE_SIZE != 0)
|
||||
panic("map_range: bad offset", offset);
|
||||
|
||||
curr_pt= -1;
|
||||
curr_pt_addr= 0;
|
||||
while (size != 0)
|
||||
{
|
||||
dir_ent= (base >> I386_VM_DIR_ENT_SHIFT);
|
||||
pt_ent= (base >> I386_VM_PT_ENT_SHIFT) & I386_VM_PT_ENT_MASK;
|
||||
if (dir_ent != curr_pt)
|
||||
{
|
||||
/* Get address of page table */
|
||||
curr_pt= dir_ent;
|
||||
curr_pt_addr= phys_get32(vm_cr3 +
|
||||
dir_ent * I386_VM_PT_ENT_SIZE);
|
||||
curr_pt_addr &= I386_VM_ADDR_MASK;
|
||||
kprintf("got address 0x%x for page table 0x%x\n",
|
||||
curr_pt_addr, curr_pt);
|
||||
}
|
||||
entry= offset | I386_VM_USER | I386_VM_WRITE |
|
||||
I386_VM_PRESENT;
|
||||
#if 0
|
||||
kprintf(
|
||||
"putting 0x%x at dir_ent 0x%x, pt_ent 0x%x (addr 0x%x)\n",
|
||||
entry, dir_ent, pt_ent,
|
||||
curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE);
|
||||
#endif
|
||||
phys_put32(curr_pt_addr + pt_ent * I386_VM_PT_ENT_SIZE, entry);
|
||||
offset += PAGE_SIZE;
|
||||
base += PAGE_SIZE;
|
||||
size -= PAGE_SIZE;
|
||||
}
|
||||
}
|
25
kernel/system/do_vm_setbuf.c
Normal file
25
kernel/system/do_vm_setbuf.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* The system call implemented in this file:
|
||||
* m_type: SYS_VM_SETBUF
|
||||
*
|
||||
* The parameters for this system call are:
|
||||
* m4_l1: Start of the buffer
|
||||
* m4_l2: Length of the buffer
|
||||
* m4_l3: End of main memory
|
||||
*/
|
||||
#include "../system.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* do_vm_setbuf *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_vm_setbuf(m_ptr)
|
||||
message *m_ptr; /* pointer to request message */
|
||||
{
|
||||
vm_base= m_ptr->m4_l1;
|
||||
vm_size= m_ptr->m4_l2;
|
||||
vm_mem_high= m_ptr->m4_l3;
|
||||
|
||||
kprintf("do_vm_setbuf: got 0x%x @ 0x%x for 0x%x\n",
|
||||
vm_size, vm_base, vm_mem_high);
|
||||
|
||||
return OK;
|
||||
}
|
|
@ -66,9 +66,9 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
|
|||
* structure 0 is shared by user processes.
|
||||
*/
|
||||
#define s(n) (1 << s_nr_to_id(n))
|
||||
#define SRV_M (~0)
|
||||
#define SYS_M (~0)
|
||||
#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR))
|
||||
#define SRV_M (~0)
|
||||
#define SYS_M (~0)
|
||||
#define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR) | s(SYSTEM))
|
||||
#define DRV_M (USR_M | s(SYSTEM) | s(CLOCK) | s(LOG_PROC_NR) | s(TTY_PROC_NR))
|
||||
|
||||
/* Define kernel calls that processes are allowed to make. This is not looking
|
||||
|
@ -84,7 +84,7 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
|
|||
| c(SYS_GETINFO) | c(SYS_EXIT) | c(SYS_TIMES) | c(SYS_SETALARM))
|
||||
#define DRV_C (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) \
|
||||
| c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO))
|
||||
#define MEM_C (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY))
|
||||
#define MEM_C (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY) | c(SYS_VM_MAP))
|
||||
|
||||
/* The system image table lists all programs that are part of the boot image.
|
||||
* The order of the entries here MUST agree with the order of the programs
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#define END_OF_KMESS -1
|
||||
FORWARD _PROTOTYPE(void kputc, (int c));
|
||||
FORWARD _PROTOTYPE( void ser_putc, (char c));
|
||||
|
||||
/*===========================================================================*
|
||||
* panic *
|
||||
|
@ -130,6 +131,8 @@ int c; /* character to append */
|
|||
* the to output driver if an END_OF_KMESS is encountered.
|
||||
*/
|
||||
if (c != END_OF_KMESS) {
|
||||
if (do_serial_debug)
|
||||
ser_putc(c);
|
||||
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
|
||||
if (kmess.km_size < KMESS_BUF_SIZE)
|
||||
kmess.km_size += 1;
|
||||
|
@ -139,3 +142,24 @@ int c; /* character to append */
|
|||
}
|
||||
}
|
||||
|
||||
#define COM1_BASE 0x3F8
|
||||
#define COM1_THR (COM1_BASE + 0)
|
||||
#define LSR_THRE 0x20
|
||||
#define COM1_LSR (COM1_BASE + 5)
|
||||
|
||||
PRIVATE void ser_putc(char c)
|
||||
{
|
||||
int i;
|
||||
int lsr, thr;
|
||||
|
||||
return;
|
||||
|
||||
lsr= COM1_LSR;
|
||||
thr= COM1_THR;
|
||||
for (i= 0; i<100000; i++)
|
||||
{
|
||||
if (inb(lsr) & LSR_THRE)
|
||||
break;
|
||||
}
|
||||
outb(thr, c);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue