home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
cpm
/
uzi
/
uzi.ark
/
MACHDEP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-29
|
8KB
|
416 lines
/**************************************************
UZI (Unix Z80 Implementation) Kernel: machdep.c
***************************************************/
#include "unix.h"
#include "extern.h"
/* This is called at the very beginning to initialize everything. */
/* It is the equivalent of main() */
fs_init()
{
di();
stkreset();
/* Initialize the interrupt vector */
initvec();
inint = 0;
udata.u_insys = 1;
/* Turn off clock */
out(0,0xf1);
ei();
init2(); /* in process.c */
}
/* This checks to see if a user-suppled address is legitimate */
valadr(base,size)
char *base;
uint16 size;
{
if (base < PROGBASE || base+size >= (char *)&udata)
{
udata.u_error = EFAULT;
return(0);
}
return(1);
}
/* This adds two tick counts together.
The t_time field holds up to one second of ticks,
while the t_date field counts minutes */
addtick(t1,t2)
time_t *t1, *t2;
{
t1->t_time += t2->t_time;
t1->t_date += t2->t_date;
if (t1->t_time >= 60*TICKSPERSEC)
{
t1->t_time -= 60*TICKSPERSEC;
++t1->t_date;
}
}
incrtick(t)
time_t *t;
{
if (++t->t_time == 60*TICKSPERSEC)
{
t->t_time = 0;
++t->t_date;
}
}
stkreset()
{
#asm 8080
POP H
LXI SP,udata?-2
PCHL
#endasm
}
tempstack()
{
#asm 8080
POP H
LXI SP,100H
PCHL
#endasm
}
initvec()
{
#asm 8080
LXI H,vector?
INX H
MOV A,L
ANI 0FEH
MOV L,A ;set hl to first even address in vector[].
MOV A,H
.Z80
LD I,A ;SET INTERRUPT REGISTER TO UPPER 8 BITS
.8080
MOV A,L
OUT 076H ;set external vector register with low order byte
LXI D,service?
MOV M,E
INX H
MOV M,D ;STORE ADDRESS OF SERVICE ROUTINE IN vector[].
RET
#endasm
}
extern int unix();
doexec()
{
#asm 8080
POP H
POP H ;get argument
SPHL ;set stack pointer to it
MVI A,0C3H ;jump inst
STA 0030H ;dest of RST6 instruction.
LXI H,unix? ;entry address
SHLD 0031H
XRA A
STA udata? + ?OSYS
JMP 0100H
#endasm
}
static int cursig;
static int (*curvec)();
/* This interrupt device routine calls the service routine of each device
that could have interrupted. */
service()
{
;
#asm 8080
PUSH PSW
PUSH B
PUSH D
PUSH H
.Z80
PUSH IX
PUSH IY
.8080
#endasm
inint = 1;
if (tty_int())
goto found;
if (clk_int())
goto found;
/* if ( ) ... */
warning("Spurious interrupt");
found:
inint = 0;
/* Deal with a pending caught signal, if any */
if (!udata.u_insys)
calltrap();
;
#asm 8080
.Z80
POP IY
POP IX
.8080
POP H
POP D
POP B
POP PSW
EI
RET
#endasm
}
calltrap()
{
/* Deal with a pending caught signal, if any. */
/* udata.u_insys should be false, and interrupts enabled.
remember, the user may never return from the trap routine */
if (udata.u_cursig)
{
cursig = udata.u_cursig;
curvec = udata.u_sigvec[cursig];
udata.u_cursig = 0;
udata.u_sigvec[cursig] = SIG_DFL; /* Reset to default */
ei();
(*curvec)(cursig);
di();
}
}
/* Port addresses of clock chip registers. */
#define SECS 0xe2
#define MINS 0xe3
#define HRS 0xe4
#define DAY 0xe6
#define MON 0xe7
#define YEAR 86
sttime()
{
panic("Calling sttime");
}
rdtime(tloc)
time_t *tloc;
{
di();
tloc->t_time = tod.t_time;
tloc->t_date = tod.t_date;
ei();
}
/* Update global time of day */
rdtod()
{
tod.t_time = (tread(SECS)>>1) | (tread(MINS)<<5) | (tread(HRS)<<11);
tod.t_date = tread(DAY) | (tread(MON)<<5) | (YEAR<<9);
}
/* Read BCD clock register, convert to binary. */
tread(port)
uint16 port;
{
int n;
n = in(port);
return ( 10*((n>>4)&0x0f) + (n&0x0f) );
}
/* Disable interrupts */
di()
{
#asm 8080
DI ;disable interrupts
#endasm
}
/* Enable interrupts if we are not in service routine */
ei()
{
if (inint)
return;
; /* Empty statement necessary to fool compiler */
#asm 8080
EI ;disable interrupts
#endasm
}
/* This shifts an unsigned int right 8 places. */
shift8()
{
#asm 8080
POP D ;ret addr
POP H
MOV L,H
MVI H,0
MOV A,L
ANA A ;set Z flag on result
PUSH H
PUSH D ;restore stack
#endasm
}
/* This prints an error message and dies. */
panic(s)
char *s;
{
di();
inint = 1;
kprintf("PANIC: %s\n",s);
idump();
abort();
}
warning(s)
char *s;
{
kprintf("WARNING: %s\n",s);
}
puts(s)
char *s;
{
while (*s)
kputchar(*(s++));
}
kputchar(c)
int c;
{
if (c == '\n')
_putc('\r');
_putc(c);
if (c == '\t')
puts("\177\177\177\177\177\177\177\177\177\177");
}
idump()
{
inoptr ip;
ptptr pp;
extern struct cinode i_tab[];
kprintf(
"\tMAGIC\tDEV\tNUM\tMODE\tNLINK\t(DEV)\tREFS\tDIRTY err %d root %d\n",
udata.u_error, root - i_tab);
for (ip=i_tab; ip < i_tab+ITABSIZE; ++ip)
{
kprintf("%d\t%d\t%d\t%u\t0%o\t%d\t%d\t%d\t%d\n",
ip-i_tab, ip->c_magic,ip->c_dev, ip->c_num,
ip->c_node.i_mode,ip->c_node.i_nlink,ip->c_node.i_addr[0],
ip->c_refs,ip->c_dirty);
/*****
ifnot (ip->c_magic)
break;
******/
}
kprintf("\n\tSTAT\tWAIT\tPID\tPPTR\tALARM\tPENDING\tIGNORED\n");
for (pp=ptab; pp < ptab+PTABSIZE; ++pp)
{
kprintf("%d\t%d\t0x%x\t%d\t%d\t%d\t0x%x\t0x%x\n",
pp-ptab, pp->p_status, pp->p_wait, pp->p_pid,
pp->p_pptr-ptab, pp->p_alarm, pp->p_pending,
pp->p_ignored);
ifnot(pp->p_pptr)
break;
}
bufdump();
kprintf("\ninsys %d ptab %d call %d cwd %d sp 0x%x\n",
udata.u_insys,udata.u_ptab-ptab, udata.u_callno, udata.u_cwd-i_tab,
udata.u_sp);
}
/* Short version of printf to save space */
kprintf(nargs)
{
register char **arg, *fmt;
register c, base;
char s[7], *itob();
arg = (char **)&nargs + nargs;
fmt = *arg;
while (c = *fmt++) {
if (c != '%') {
kputchar(c);
continue;
}
switch (c = *fmt++) {
case 'c':
kputchar(*--arg);
continue;
case 'd':
base = -10;
goto prt;
case 'o':
base = 8;
goto prt;
case 'u':
base = 10;
goto prt;
case 'x':
base = 16;
prt:
puts(itob(*--arg, s, base));
continue;
case 's':
puts(*--arg);
continue;
default:
kputchar(c);
continue;
}
}
}