Initial import, 0.1 + pk 0.2.4-B1

This commit is contained in:
Rodney W. Grimes
1993-06-12 14:58:17 +00:00
parent 9002c02abc
commit 5b81b6b301
247 changed files with 78588 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
#
# PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
# -------------------- ----- ----------------------
# CURRENT PATCH LEVEL: 1 00092
# -------------------- ----- ----------------------
#
# 15 Mar 93 Patchkit Coordinator Corrected SRCS, missing .c
#
PROG=expr
SRCS=expr.c
CFLAGS+=-I. -I${.CURDIR}
NOMAN=noman
CLEANFILES+=expr.c y.tab.h
expr.c:
${YACC} -d ${.IMPSRC}
mv y.tab.c expr.c
.include <bsd.prog.mk>
+594
View File
@@ -0,0 +1,594 @@
%{
/* Written by Pace Willisson (pace@blitz.com)
* and placed in the public domain
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00148
* -------------------- ----- ----------------------
*
* 20 Apr 93 J. T. Conklin Many fixes for () and other such things
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
enum valtype {
integer, string
} ;
struct val {
enum valtype type;
union {
char *s;
int i;
} u;
};
struct val *result;
struct val *op_or ();
struct val *op_and ();
struct val *op_eq ();
struct val *op_gt ();
struct val *op_lt ();
struct val *op_ge ();
struct val *op_le ();
struct val *op_ne ();
struct val *op_plus ();
struct val *op_minus ();
struct val *op_times ();
struct val *op_div ();
struct val *op_rem ();
struct val *op_colon ();
char **av;
%}
%union
{
struct val *val;
}
%left <val> '|'
%left <val> '&'
%left <val> '=' '>' '<' GE LE NE
%left <val> '+' '-'
%left <val> '*' '/' '%'
%left <val> ':'
%left UNARY
%token <val> TOKEN
%type <val> start expr
%%
start: expr { result = $$; }
expr: TOKEN
| '(' expr ')' { $$ = $2; }
| expr '|' expr { $$ = op_or ($1, $3); }
| expr '&' expr { $$ = op_and ($1, $3); }
| expr '=' expr { $$ = op_eq ($1, $3); }
| expr '>' expr { $$ = op_gt ($1, $3); }
| expr '<' expr { $$ = op_lt ($1, $3); }
| expr GE expr { $$ = op_ge ($1, $3); }
| expr LE expr { $$ = op_le ($1, $3); }
| expr NE expr { $$ = op_ne ($1, $3); }
| expr '+' expr { $$ = op_plus ($1, $3); }
| expr '-' expr { $$ = op_minus ($1, $3); }
| expr '*' expr { $$ = op_times ($1, $3); }
| expr '/' expr { $$ = op_div ($1, $3); }
| expr '%' expr { $$ = op_rem ($1, $3); }
| expr ':' expr { $$ = op_colon ($1, $3); }
| '-' expr %prec UNARY { $$ = op_minus (NULL, $2); }
;
%%
struct val *
make_integer (i)
int i;
{
struct val *vp;
vp = (struct val *) malloc (sizeof (*vp));
if (vp == NULL) {
fprintf (stderr, "expr: out of memory\n");
exit (2);
}
vp->type = integer;
vp->u.i = i;
return vp;
}
struct val *
make_str (s)
char *s;
{
struct val *vp;
vp = (struct val *) malloc (sizeof (*vp));
if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
fprintf (stderr, "expr: out of memory\n");
exit (2);
}
vp->type = string;
return vp;
}
void
free_value (vp)
struct val *vp;
{
if (vp->type == string)
free (vp->u.s);
}
int
to_integer (vp)
struct val *vp;
{
char *s;
int neg;
int i;
if (vp->type == integer)
return 1;
s = vp->u.s;
i = 0;
neg = (*s == '-');
if (neg)
s++;
for (;*s; s++) {
if (!isdigit (*s))
return 0;
i *= 10;
i += *s - '0';
}
free (vp->u.s);
if (neg)
i *= -1;
vp->type = integer;
vp->u.i = i;
return 1;
}
void
to_string (vp)
struct val *vp;
{
char *tmp;
if (vp->type == string)
return;
tmp = malloc (25);
if (tmp == NULL) {
fprintf (stderr, "expr: out of memory\n");
exit (2);
}
sprintf (tmp, "%d", vp->u.i);
vp->type = string;
vp->u.s = tmp;
}
int
isstring (vp)
struct val *vp;
{
return (vp->type == string);
}
int
yylex ()
{
struct val *vp;
char *p;
if (*av == NULL)
return (0);
p = *av++;
if (strlen (p) == 1) {
if (strchr ("|&=<>+-*/%:()", *p))
return (*p);
} else if (strlen (p) == 2 && p[1] == '=') {
switch (*p) {
case '>': return (GE);
case '<': return (LE);
case '!': return (NE);
}
}
yylval.val = make_str (p);
return (TOKEN);
}
int
is_zero_or_null (vp)
struct val *vp;
{
/* Like most other versions of expr, this version will return
false for a string value of multiple zeros.*/
if (vp->type == integer) {
return (vp->u.i == 0);
} else {
return (*vp->u.s == 0 || strcmp (vp->u.s, "0") == 0);
}
/* NOTREACHED */
}
void
main (argc, argv)
int argc;
char **argv;
{
av = argv + 1;
yyparse ();
if (result->type == integer)
printf ("%d\n", result->u.i);
else
printf ("%s\n", result->u.s);
if (is_zero_or_null (result))
exit (1);
else
exit (0);
}
int
yyerror (s)
char *s;
{
fprintf (stderr, "expr: syntax error\n");
exit (2);
}
struct val *
op_or (a, b)
struct val *a, *b;
{
if (is_zero_or_null (a)) {
free_value (a);
return (b);
} else {
free_value (b);
return (a);
}
}
struct val *
op_and (a, b)
struct val *a, *b;
{
if (is_zero_or_null (a) || is_zero_or_null (b)) {
free_value (a);
free_value (b);
return (make_integer (0));
} else {
free_value (b);
return (a);
}
}
struct val *
op_eq (a, b)
struct val *a, *b;
{
struct val *r;
/* attempt to coerce both arguments to integers */
(void) to_integer (a);
(void) to_integer (b);
/* But if either one of them really is a string, do
a string comparison */
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer (strcmp (a->u.s, b->u.s) == 0);
} else {
r = make_integer (a->u.i == b->u.i);
}
free_value (a);
free_value (b);
return r;
}
struct val *
op_gt (a, b)
struct val *a, *b;
{
struct val *r;
/* attempt to coerce both arguments to integers */
(void) to_integer (a);
(void) to_integer (b);
/* But if either one of them really is a string, do
a string comparison */
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer (strcmp (a->u.s, b->u.s) > 0);
} else {
r= make_integer (a->u.i > b->u.i);
}
free_value (a);
free_value (b);
return r;
}
struct val *
op_lt (a, b)
struct val *a, *b;
{
struct val *r;
/* attempt to coerce both arguments to integers */
(void) to_integer (a);
(void) to_integer (b);
/* But if either one of them really is a string, do
a string comparison */
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer (strcmp (a->u.s, b->u.s) < 0);
} else {
r = make_integer (a->u.i < b->u.i);
}
free_value (a);
free_value (b);
return r;
}
struct val *
op_ge (a, b)
struct val *a, *b;
{
struct val *r;
/* attempt to coerce both arguments to integers */
(void) to_integer (a);
(void) to_integer (b);
/* But if either one of them really is a string, do
a string comparison */
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer (strcmp (a->u.s, b->u.s) >= 0);
} else {
r = make_integer (a->u.i >= b->u.i);
}
free_value (a);
free_value (b);
return r;
}
struct val *
op_le (a, b)
struct val *a, *b;
{
struct val *r;
/* attempt to coerce both arguments to integers */
(void) to_integer (a);
(void) to_integer (b);
/* But if either one of them really is a string, do
a string comparison */
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer (strcmp (a->u.s, b->u.s) <= 0);
} else {
r = make_integer (a->u.i <= b->u.i);
}
free_value (a);
free_value (b);
return r;
}
struct val *
op_ne (a, b)
struct val *a, *b;
{
struct val *r;
/* attempt to coerce both arguments to integers */
(void) to_integer (a);
(void) to_integer (b);
/* But if either one of them really is a string, do
a string comparison */
if (isstring (a) || isstring (b)) {
to_string (a);
to_string (b);
r = make_integer (strcmp (a->u.s, b->u.s) != 0);
} else {
r = make_integer (a->u.i != b->u.i);
}
free_value (a);
free_value (b);
return r;
}
struct val *
op_plus (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
fprintf (stderr, "expr: non-numeric argument\n");
exit (2);
}
r = make_integer (a->u.i + b->u.i);
free_value (a);
free_value (b);
return r;
}
struct val *
op_minus (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
fprintf (stderr, "expr: non-numeric argument\n");
exit (2);
}
r = make_integer (a->u.i - b->u.i);
free_value (a);
free_value (b);
return r;
}
struct val *
op_times (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
fprintf (stderr, "expr: non-numeric argument\n");
exit (2);
}
r = make_integer (a->u.i * b->u.i);
free_value (a);
free_value (b);
return (r);
}
struct val *
op_div (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
fprintf (stderr, "expr: non-numeric argument\n");
exit (2);
}
if (b->u.i == 0) {
fprintf (stderr, "expr: division by zero\n");
exit (2);
}
r = make_integer (a->u.i / b->u.i);
free_value (a);
free_value (b);
return r;
}
struct val *
op_rem (a, b)
struct val *a, *b;
{
struct val *r;
if (!to_integer (a) || !to_integer (b)) {
fprintf (stderr, "expr: non-numeric argument\n");
exit (2);
}
if (b->u.i == 0) {
fprintf (stderr, "expr: division by zero\n");
exit (2);
}
r = make_integer (a->u.i % b->u.i);
free_value (a);
free_value (b);
return r;
}
#include <regexp.h>
struct val *
op_colon (a, b)
struct val *a, *b;
{
regexp *rp;
char *newexp;
char *p;
char *q;
newexp = malloc (3 * strlen (b->u.s));
p = b->u.s;
q = newexp;
*q++ = '^';
while (*p) {
if (*p == '\\') {
p++;
if (*p == '(' || *p == ')') {
*q++ = *p++;
} else {
*q++ = '\\';
*q++ = *p++;
}
} else if (*p == '(' || *p == ')') {
*q++ = '\\';
*q++ = *p++;
} else {
*q++ = *p++;
}
}
*q = 0;
if ((rp = regcomp (newexp)) == NULL)
yyerror ("invalid regular expression");
if (regexec (rp, a->u.s)) {
if (rp->startp[1]) {
rp->endp[1][0] = 0;
return (make_str (rp->startp[1]));
} else {
return (make_integer (rp->endp[0] - rp->startp[0]));
}
} else {
return (make_integer (0));
}
}
void
regerror (s)
const char *s;
{
fprintf (stderr, "expr: %s\n", s);
exit (2);
}
+33
View File
@@ -0,0 +1,33 @@
# @(#)Makefile 5.6 (Berkeley) 5/22/91
CFLAGS= -O -DLIBC_SCCS
OBJS= crt0.o gcrt0.o
CLEANFILES+= gmon.o moncrt0.o core a.out
all: ${OBJS}
crt0.o: crt0.c
${CC} ${CFLAGS} -c -DCRT0 ${.ALLSRC}
${LD} -x -r ${.TARGET}
mv a.out ${.TARGET}
moncrt0.o: crt0.c
${CC} ${CFLAGS} -c -DMCRT0 ${.ALLSRC} -o ${.TARGET}
${LD} -x -r ${.TARGET}
mv a.out ${.TARGET}
gcrt0.o: moncrt0.o gmon.o
${LD} -x -r -o ${.TARGET} moncrt0.o gmon.o
gmon.o: gmon.c gmon.h
${CC} -c ${DEFS} ${.IMPSRC}
${LD} -x -r ${.TARGET}
mv a.out ${.TARGET}
install:
install -o ${BINOWN} -g ${BINGRP} -m 444 ${OBJS} \
${DESTDIR}/usr/lib
depend lint tags:
.include <bsd.prog.mk>
+108
View File
@@ -0,0 +1,108 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)crt0.c 5.7 (Berkeley) 7/3/91";
#endif /* LIBC_SCCS and not lint */
/*
* C start up routine.
* Robert Henry, UCB, 20 Oct 81
*
* We make the following (true) assumption:
* 1) The only register variable that we can trust is the frame pointer,
* ebp, which points to the base of the kernel calling frame.
*/
char **environ = (char **)0;
int errno = 0;
asm(".text");
asm(".long 0xc000c000");
extern unsigned char etext;
extern unsigned char eprol asm ("eprol");
extern start() asm("start");
extern mcount() asm ("mcount");
start()
{
struct kframe {
int kargc;
char *kargv[1]; /* size depends on kargc */
char kargstr[1]; /* size varies */
char kenvstr[1]; /* size varies */
};
/*
* ALL REGISTER VARIABLES!!!
*/
register struct kframe *kfp;
register char **targv;
register char **argv;
extern void _mcleanup();
#ifdef lint
kfp = 0;
initcode = initcode = 0;
#else not lint
/* just above the saved frame pointer */
asm ("lea 4(%%ebp), %0" : "=r" (kfp) );
#endif not lint
for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
/* void */ ;
if (targv >= (char **)(*argv))
--targv;
environ = targv;
asm("eprol:");
#ifdef MCRT0
atexit(_mcleanup);
monstartup(&eprol, &etext);
#endif MCRT0
exit(main(kfp->kargc, argv, environ));
}
#ifdef CRT0
/*
* null mcount and moncontrol,
* just in case some routine is compiled for profiling
*/
moncontrol(val)
int val;
{
}
mcount() { }
#endif CRT0
+329
View File
@@ -0,0 +1,329 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91";
#endif /* LIBC_SCCS and not lint */
#include <unistd.h>
#ifdef DEBUG
#include <stdio.h>
#endif
#include "gmon.h"
extern mcount() asm ("mcount");
extern char *minbrk asm ("minbrk");
/*
* froms is actually a bunch of unsigned shorts indexing tos
*/
static int profiling = 3;
static unsigned short *froms;
static struct tostruct *tos = 0;
static long tolimit = 0;
static char *s_lowpc = 0;
static char *s_highpc = 0;
static unsigned long s_textsize = 0;
static int ssiz;
static char *sbuf;
static int s_scale;
/* see profil(2) where this is describe (incorrectly) */
#define SCALE_1_TO_1 0x10000L
#define MSG "No space for profiling buffer(s)\n"
monstartup(lowpc, highpc)
char *lowpc;
char *highpc;
{
int monsize;
char *buffer;
register int o;
/*
* round lowpc and highpc to multiples of the density we're using
* so the rest of the scaling (here and in gprof) stays in ints.
*/
lowpc = (char *)
ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_lowpc = lowpc;
highpc = (char *)
ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_highpc = highpc;
s_textsize = highpc - lowpc;
monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
buffer = sbrk( monsize );
if ( buffer == (char *) -1 ) {
write( 2 , MSG , sizeof(MSG) );
return;
}
froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
if ( froms == (unsigned short *) -1 ) {
write( 2 , MSG , sizeof(MSG) );
froms = 0;
return;
}
tolimit = s_textsize * ARCDENSITY / 100;
if ( tolimit < MINARCS ) {
tolimit = MINARCS;
} else if ( tolimit > 65534 ) {
tolimit = 65534;
}
tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
if ( tos == (struct tostruct *) -1 ) {
write( 2 , MSG , sizeof(MSG) );
froms = 0;
tos = 0;
return;
}
minbrk = sbrk(0);
tos[0].link = 0;
sbuf = buffer;
ssiz = monsize;
( (struct phdr *) buffer ) -> lpc = lowpc;
( (struct phdr *) buffer ) -> hpc = highpc;
( (struct phdr *) buffer ) -> ncnt = ssiz;
monsize -= sizeof(struct phdr);
if ( monsize <= 0 )
return;
o = highpc - lowpc;
if( monsize < o )
#ifndef hp300
s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
#else /* avoid floating point */
{
int quot = o / monsize;
if (quot >= 0x10000)
s_scale = 1;
else if (quot >= 0x100)
s_scale = 0x10000 / quot;
else if (o >= 0x800000)
s_scale = 0x1000000 / (o / (monsize >> 8));
else
s_scale = 0x1000000 / ((o << 8) / monsize);
}
#endif
else
s_scale = SCALE_1_TO_1;
moncontrol(1);
}
_mcleanup()
{
int fd;
int fromindex;
int endfrom;
char *frompc;
int toindex;
struct rawarc rawarc;
moncontrol(0);
fd = creat( "gmon.out" , 0666 );
if ( fd < 0 ) {
perror( "mcount: gmon.out" );
return;
}
# ifdef DEBUG
fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
# endif DEBUG
write( fd , sbuf , ssiz );
endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
if ( froms[fromindex] == 0 ) {
continue;
}
frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
# ifdef DEBUG
fprintf( stderr ,
"[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
frompc , tos[toindex].selfpc , tos[toindex].count );
# endif DEBUG
rawarc.raw_frompc = (unsigned long) frompc;
rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
rawarc.raw_count = tos[toindex].count;
write( fd , &rawarc , sizeof rawarc );
}
}
close( fd );
}
mcount()
{
register char *selfpc;
register unsigned short *frompcindex;
register struct tostruct *top;
register struct tostruct *prevtop;
register long toindex;
/*
* find the return address for mcount,
* and the return address for mcount's caller.
*/
asm(".text"); /* make sure we're in text space */
/*
* selfpc = pc pushed by mcount call
*/
asm("movl 4(%%ebp),%0" : "=r" (selfpc));
/*
* frompcindex = pc pushed by jsr into self.
* In GCC the caller's stack frame has already been built so we
* have to chase a6 to find caller's raddr.
*/
asm("movl (%%ebp),%0" : "=r" (frompcindex));
frompcindex = ((unsigned short **)frompcindex)[1];
/*
* check that we are profiling
* and that we aren't recursively invoked.
*/
if (profiling) {
goto out;
}
profiling++;
/*
* check that frompcindex is a reasonable pc value.
* for example: signal catchers get called from the stack,
* not from text space. too bad.
*/
frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
if ((unsigned long)frompcindex > s_textsize) {
goto done;
}
frompcindex =
&froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
toindex = *frompcindex;
if (toindex == 0) {
/*
* first time traversing this arc
*/
toindex = ++tos[0].link;
if (toindex >= tolimit) {
goto overflow;
}
*frompcindex = toindex;
top = &tos[toindex];
top->selfpc = selfpc;
top->count = 1;
top->link = 0;
goto done;
}
top = &tos[toindex];
if (top->selfpc == selfpc) {
/*
* arc at front of chain; usual case.
*/
top->count++;
goto done;
}
/*
* have to go looking down chain for it.
* top points to what we are looking at,
* prevtop points to previous top.
* we know it is not at the head of the chain.
*/
for (; /* goto done */; ) {
if (top->link == 0) {
/*
* top is end of the chain and none of the chain
* had top->selfpc == selfpc.
* so we allocate a new tostruct
* and link it to the head of the chain.
*/
toindex = ++tos[0].link;
if (toindex >= tolimit) {
goto overflow;
}
top = &tos[toindex];
top->selfpc = selfpc;
top->count = 1;
top->link = *frompcindex;
*frompcindex = toindex;
goto done;
}
/*
* otherwise, check the next arc on the chain.
*/
prevtop = top;
top = &tos[top->link];
if (top->selfpc == selfpc) {
/*
* there it is.
* increment its count
* move it to the head of the chain.
*/
top->count++;
toindex = prevtop->link;
prevtop->link = top->link;
top->link = *frompcindex;
*frompcindex = toindex;
goto done;
}
}
done:
profiling--;
/* and fall through */
out:
return; /* normal return restores saved registers */
overflow:
profiling++; /* halt further profiling */
# define TOLIMIT "mcount: tos overflow\n"
write(2, TOLIMIT, sizeof(TOLIMIT));
goto out;
}
/*
* Control profiling
* profiling is what mcount checks to see if
* all the data structures are ready.
*/
moncontrol(mode)
int mode;
{
if (mode) {
/* start */
profil(sbuf + sizeof(struct phdr), ssiz - sizeof(struct phdr),
(int)s_lowpc, s_scale);
profiling = 0;
} else {
/* stop */
profil((char *)0, 0, 0, 0);
profiling = 3;
}
}
+105
View File
@@ -0,0 +1,105 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)gmon.h 5.2 (Berkeley) 5/6/91
*/
struct phdr {
char *lpc;
char *hpc;
int ncnt;
};
/*
* histogram counters are unsigned shorts (according to the kernel).
*/
#define HISTCOUNTER unsigned short
/*
* fraction of text space to allocate for histogram counters
* here, 1/2
*/
#define HISTFRACTION 2
/*
* Fraction of text space to allocate for from hash buckets.
* The value of HASHFRACTION is based on the minimum number of bytes
* of separation between two subroutine call points in the object code.
* Given MIN_SUBR_SEPARATION bytes of separation the value of
* HASHFRACTION is calculated as:
*
* HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1);
*
* For the VAX, the shortest two call sequence is:
*
* calls $0,(r0)
* calls $0,(r0)
*
* which is separated by only three bytes, thus HASHFRACTION is
* calculated as:
*
* HASHFRACTION = 3 / (2 * 2 - 1) = 1
*
* Note that the division above rounds down, thus if MIN_SUBR_FRACTION
* is less than three, this algorithm will not work!
*/
#define HASHFRACTION 1
/*
* percent of text space to allocate for tostructs
* with a minimum.
*/
#define ARCDENSITY 2
#define MINARCS 50
struct tostruct {
char *selfpc;
long count;
unsigned short link;
};
/*
* a raw arc,
* with pointers to the calling site and the called site
* and a count.
*/
struct rawarc {
unsigned long raw_frompc;
unsigned long raw_selfpc;
long raw_count;
};
/*
* general rounding functions.
*/
#define ROUNDDOWN(x,y) (((x)/(y))*(y))
#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
+3
View File
@@ -0,0 +1,3 @@
g/_mcount/s/_mcount/mcount/g
w
q
+6
View File
@@ -0,0 +1,6 @@
# @(#)Makefile 5.3 (Berkeley) 5/11/90
PROG= makekey
MAN8= makekey.0
.include <bsd.prog.mk>
+59
View File
@@ -0,0 +1,59 @@
.\" Copyright (c) 1990, 1991 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)makekey.8 6.5 (Berkeley) 7/1/91
.\"
.Dd July 1, 1991
.Dt MAKEKEY 8
.Os
.Sh NAME
.Nm makekey
.Nd make encrypted keys or passwords
.Sh SYNOPSIS
.Nm makekey
.Sh DESCRIPTION
.Nm Makekey
encypts a key and salt which it reads from the standard input
and writes the result to the standard output.
The key is expected to be
ten bytes; the salt is expected to be two bytes.
See
.Xr crypt 3
for more information on what characters the key and salt can contain
and how the encrypted value is calculated.
.Sh SEE ALSO
.Xr login 1 ,
.Xr crypt 1 ,
.Xr crypt 3
.Sh HISTORY
A
.Nm
command appeared in Version 7 AT&T UNIX.
+85
View File
@@ -0,0 +1,85 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)makekey.c 5.3 (Berkeley) 2/25/91";
#endif /* not lint */
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void error(), get();
main()
{
int len;
char *r, key[9], salt[3];
get(key, sizeof(key) - 1);
get(salt, sizeof(salt) - 1);
len = strlen(r = crypt(key, salt));
if (write(STDOUT_FILENO, r, len) != len)
error();
exit(0);
}
static void
get(bp, len)
char *bp;
register int len;
{
register int nr;
bp[len] = '\0';
if ((nr = read(STDIN_FILENO, bp, len)) == len)
return;
if (nr >= 0)
errno = EFTYPE;
error();
}
static void
error()
{
(void)fprintf(stderr, "makekey: %s\n", strerror(errno));
exit(1);
}
+6
View File
@@ -0,0 +1,6 @@
# @(#)Makefile 5.4 (Berkeley) 6/5/91
PROG= comcontrol
NOMAN= noman
.include <bsd.prog.mk>
+79
View File
@@ -0,0 +1,79 @@
/*-
* Copyright (c) 1992 Christopher G. Demetriou
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* comcontrol.c */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <fcntl.h>
void usage(char *progname)
{
fprintf(stderr, "usage: %s <filename> [[-]bidir]\n", progname);
exit(1);
}
int main(int argc, char *argv[])
{
int fd;
int res;
if ((argc < 2) || (argc > 3)) usage(argv[0]);
fd = open(argv[1], O_RDONLY|O_NONBLOCK, 0);
if (fd < 0) {
fprintf(stderr, "%s: couldn't open file %s\n", argv[0], argv[1]);
perror("open");
exit(1);
}
if (argc == 2) {
if (ioctl(fd, TIOCMGBIDIR, &res) < 0) {
perror("ioctl");
exit(1);
}
if (!res) printf("-");
printf("bidir\n");
} else {
if (!strcmp(argv[2],"bidir")) {
res = 1;
} else if (!strcmp(argv[2],"-bidir")) {
res = 0;
} else {
usage(argv[0]);
}
if (ioctl(fd, TIOCMSBIDIR, &res) < 0) {
perror("ioctl");
exit(1);
}
}
close(fd);
}
+9
View File
@@ -0,0 +1,9 @@
# @(#)Makefile 1.1 (Julian Elischer) 3/28/93
#
#
PROG= fdisk
SRCS= fdisk.c
MAN8= fdisk.0
.include <bsd.prog.mk>
+177
View File
@@ -0,0 +1,177 @@
.Dd April 4, 1993
.Dt FDISK 8
.\".Os BSD 4
.Sh NAME
.Nm fdisk
.Nd DOS partition maintainance program
.Sh SYNOPSIS
.Nm
.Op Fl i
.Op Fl u
.Bl -tag -width time
.It Fl i
Initializes sector 0 of the disk.
.It Fl u
Is used for updating (editing) sector 0 of the disk.
.El
.Sh PROLOGUE
In order for the BIOS to boot the kernel,
certain conventions must be adhered to.
Sector 0 of the disk must contain boot code,
a partition table,
and a magic number.
BIOS partitions can be used to break the disk up into several pieces.
The BIOS brings in sector 0
(does it really use the code?)
and verifies the magic number.
It then searches the 4 BIOS partitions described by sector 0
to determine which of them is
.Em active.
This boot then brings in the secondary boot block from the
.Em active
partition and runs it.
Under DOS,
you could have one or more partitions with one
.Em active.
The DOS
.Nm
program can be used to divide space on the disk into partitions and set one
.Em active.
.Sh DESCRIPTION
The 386bsd program
.Nm
serves a similar purpose to the DOS program.
When called with no arguments, it prints the sector 0 partition table.
An example follows:
.Bd -literal
******* Working on device /dev/rwd0d *******
parameters extracted from in-core disklabel are:
cylinders=769 heads=15 sectors/track=33 (495 blks/cyl)
parameters to be used for BIOS calculations are:
cylinders=769 heads=15 sectors/track=33 (495 blks/cyl)
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 0 is:
sysid 165,(386BSD)
start 495, size 380160 (185 Meg), flag 0
beg: cyl 1/ sector 1/ head 0;
end: cyl 768/ sector 33/ head 14
The data for partition 1 is:
sysid 164,(unknown)
start 378180, size 2475 (1 Meg), flag 0
beg: cyl 764/ sector 1/ head 0;
end: cyl 768/ sector 33/ head 14
The data for partition 2 is:
<UNUSED>
The data for partition 3 is:
sysid 99,(ISC UNIX, other System V/386, GNU HURD or Mach)
start 380656, size 224234 (109 Meg), flag 80
beg: cyl 769/ sector 2/ head 0;
end: cyl 197/ sector 33/ head 14
.Ed
.Pp
The disk is divided into three parititions that happen to fill the disk.
The second partition overlaps the end of the first.
(Used for debugging purposes)
.Bl -tag -width "cyl, sector and head"
.It Em "sysid"
is used to label the partition. 386bsd reserves the
magic number 165 decimal (A5 in hex).
.It Em "start and size"
fields provide the start address
and size of a parition in sectors.
.It Em "flag 80"
specifies that this is the active partition.
.It Em "cyl, sector and head"
fields are used to specify the beginning address
and end address for the parititon.
.It Em "Note:"
these numbers are calculated using BIOS's understanding of the disk geometry
and saved in the bootblock.
.El
.Pp
The flags
.Fl i
or
.Fl u
are used to indicate that the paritition data is to be updated.
The
.Nm
program will enter a conversational mode.
This mode is designed not to change any data unless you explicitly tell it to.
.Nm
selects defaults for its questions to guarantee the above behaviour.
.Pp
It displays each partition
and ask if you want to edit it.
If you say yes,
it will step through each field showing the old value
and asking for a new one.
When you are done with a partition,
.Nm
will display it and ask if it is correct.
.Nm
will then procede to the next entry.
.Pp
Getting the
.Em cyl, sector,
and
.Em head
fields correct is tricky.
So by default,
they will be calculated for you;
you can specify them if you choose.
.Pp
After all the partitions are processed,
you are given the option to change the
.Em active
partition.
Finally,
when the all the data for the first sector has been accumulated,
you are asked if you really want to rewrite sector 0.
Only if you answer yes,
will the data be written to disk.
.Pp
The difference between the
.Fl u
flag and
.Fl i
flag is that
the
.Fl u
flag just edits the fields as they appear on the disk.
While the
.Fl i
flag is used to "initialize" sector 0;
it will setup the last BIOS partition to use the whole disk for 386bsd;
and make it active.
.Sh NOTES
.Pp
The automatic calculation of starting cylinder etc. uses
a set of figures that represent what the BIOS thinks is the
geometry of the drive.
These figures are by default taken from the incore disklabel,
but the program initially gives you an oportunity to change them.
This allows the user to create a bootblock that can work with drives
that use geometry translation under the BIOS.
.Pp
If you hand craft your disk layout,
please make sure that the 386bsd partition starts on a cylinder boundary.
A number of decisions made later may assume this.
(This might not be necessary later.)
.Pp
Editing an existing partition will most likely cause you to
lose all the data in that partition.
.Pp
You should run this program interactively once or twice to see how it works.
This is completely safe as long as you answer the last question in the negative.
There are subtleties
that the program detects
that are not fully explained in this manual page.
.Sh SEE ALSO
.Xr disklabel 8
.Sh BUGS
One less now, but probably more
+686
View File
@@ -0,0 +1,686 @@
/*
* Mach Operating System
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
#include <sys/types.h>
#include <sys/disklabel.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
int iotest;
#define LBUF 100
static char lbuf[LBUF];
/*
*
* Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992
*
* 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
* Copyright (c) 1989 Robert. V. Baron
* Created.
*/
#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
#define SECSIZE 512
char *disk = "/dev/rwd0d";
char *name;
struct disklabel disklabel; /* disk parameters */
int cyls, sectors, heads, cylsecs, disksecs;
struct mboot
{
unsigned char padding[2]; /* force the longs to be long alligned */
unsigned char bootinst[DOSPARTOFF];
struct dos_partition parts[4];
unsigned short int signature;
};
struct mboot mboot;
#define ACTIVE 0x80
#define BOOT_MAGIC 0xAA55
int dos_cyls;
int dos_heads;
int dos_sectors;
int dos_cylsecs;
#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
#define DOSCYL(c) (c & 0xff)
static int dos();
char *get_type();
static int partition = -1;
static int a_flag = 0; /* set active partition */
static int i_flag = 0; /* replace partition data */
static int u_flag = 0; /* update partition data */
static unsigned char bootcode[] = {
0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
struct part_type
{
unsigned char type;
char *name;
}part_types[] =
{
{0x00, "unused"}
,{0x01, "Primary DOS with 12 bit FAT"}
,{0x02, "XENIX / filesystem"}
,{0x03, "XENIX /usr filesystem"}
,{0x04, "Primary DOS with 16 bit FAT"}
,{0x05, "Extended DOS"}
,{0x06, "Primary 'big' DOS (> 32MB)"}
,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
,{0x08, "AIX filesystem"}
,{0x09, "AIX boot partition or Coherent"}
,{0x0A, "OS/2 Boot Manager or OPUS"}
,{0x10, "OPUS"}
,{0x40, "VENIX 286"}
,{0x50, "DM"}
,{0x51, "DM"}
,{0x52, "CP/M or Microport SysV/AT"}
,{0x56, "GB"}
,{0x61, "Speed"}
,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
,{0x64, "Novell Netware 2.xx"}
,{0x65, "Novell Netware 3.xx"}
,{0x75, "PCIX"}
,{0x80, "Minix 1.1 ... 1.4a"}
,{0x81, "Minix 1.4b ... 1.5.10"}
,{0x82, "Linux"}
,{0x93, "Amoeba filesystem"}
,{0x94, "Amoeba bad block table"}
,{0xA5, "386BSD"}
,{0xB7, "BSDI BSD/386 filesystem"}
,{0xB8, "BSDI BSD/386 swap"}
,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
,{0xE1, "Speed"}
,{0xE3, "Speed"}
,{0xE4, "Speed"}
,{0xF1, "Speed"}
,{0xF2, "DOS 3.3+ Secondary"}
,{0xF4, "Speed"}
,{0xFF, "BBT (Bad Blocks Table)"}
};
main(argc, argv)
char **argv;
{
int i;
name = *argv;
{register char *cp = name;
while (*cp) if (*cp++ == '/') name = cp;
}
for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
if (*token++ != '-' || !*token)
break;
else { register int flag;
for ( ; flag = *token++ ; ) {
switch (flag) {
case '0':
partition = 0;
break;
case '1':
partition = 1;
break;
case '2':
partition = 2;
break;
case '3':
partition = 3;
break;
case 'a':
a_flag = 1;
break;
case 'i':
i_flag = 1;
case 'u':
u_flag = 1;
break;
default:
goto usage;
}
}
}
}
if (argc > 0)
disk = argv[0];
if (open_disk(u_flag) < 0)
exit(1);
printf("******* Working on device %s *******\n",disk);
if(u_flag)
{
get_params_to_use();
}
else
{
print_params();
}
if (read_s0())
init_sector0(1);
printf("Warning: BIOS sector numbering starts with sector 1\n");
printf("Information from DOS bootblock is:\n");
if (partition == -1)
for (i = 0; i < NDOSPART; i++)
change_part(i);
else
change_part(partition);
if (u_flag || a_flag)
change_active(partition);
if (u_flag || a_flag) {
printf("\nWe haven't changed the partition table yet. ");
printf("This is your last chance.\n");
print_s0(-1);
if (ok("Should we write new partition table?"))
write_s0();
}
exit(0);
usage:
printf("fdisk {-a|-i|-r} {disk}\n");
}
print_s0(which)
{
int i;
print_params();
printf("Information from DOS bootblock is:\n");
if (which == -1)
for (i = 0; i < NDOSPART; i++)
printf("%d: ", i), print_part(i);
else
print_part(which);
}
static struct dos_partition mtpart = { 0 };
print_part(i)
{
struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
printf("<UNUSED>\n");
return;
}
printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
printf(" start %d, size %d (%d Meg), flag %x\n",
partp->dp_start,
partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
partp->dp_flag);
printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
,DPCYL(partp->dp_scyl, partp->dp_ssect)
,DPSECT(partp->dp_ssect)
,partp->dp_shd
,DPCYL(partp->dp_ecyl, partp->dp_esect)
,DPSECT(partp->dp_esect)
,partp->dp_ehd);
}
init_sector0(start)
{
struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
int size = disksecs - start;
int rest;
memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
mboot.signature = BOOT_MAGIC;
partp->dp_typ = DOSPTYP_386BSD;
partp->dp_flag = ACTIVE;
partp->dp_start = start;
partp->dp_size = size;
dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
}
change_part(i)
{
struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
printf("The data for partition %d is:\n", i);
print_part(i);
if (u_flag && ok("Do you want to change it?")) {
int tmp;
if (i_flag) {
bzero((char *)partp, sizeof (struct dos_partition));
if (i == 3) {
init_sector0(1);
printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
print_part(i);
}
}
do {
Decimal("sysid", partp->dp_typ, tmp);
Decimal("start", partp->dp_start, tmp);
Decimal("size", partp->dp_size, tmp);
if (ok("Explicitly specifiy beg/end address ?"))
{
int tsec,tcyl,thd;
tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
thd = partp->dp_shd;
tsec = DPSECT(partp->dp_ssect);
Decimal("beginning cylinder", tcyl, tmp);
Decimal("beginning head", thd, tmp);
Decimal("beginning sector", tsec, tmp);
partp->dp_scyl = DOSCYL(tcyl);
partp->dp_ssect = DOSSECT(tsec,tcyl);
partp->dp_shd = thd;
tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
thd = partp->dp_ehd;
tsec = DPSECT(partp->dp_esect);
Decimal("ending cylinder", tcyl, tmp);
Decimal("ending head", thd, tmp);
Decimal("ending sector", tsec, tmp);
partp->dp_ecyl = DOSCYL(tcyl);
partp->dp_esect = DOSSECT(tsec,tcyl);
partp->dp_ehd = thd;
} else {
dos(partp->dp_start,
&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
dos(partp->dp_start+partp->dp_size - 1,
&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
}
print_part(i);
} while (!ok("Are we happy with this entry?"));
}
}
print_params()
{
printf("parameters extracted from in-core disklabel are:\n");
printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
,cyls,heads,sectors,cylsecs);
if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
printf("parameters to be used for BIOS calculations are:\n");
printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
}
change_active(which)
{
int i;
int active = 3, tmp;
struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
if (a_flag && which != -1)
active = which;
if (ok("Do you want to change the active partition?")) {
do
Decimal("active partition", active, tmp);
while(!ok("Are you happy with this choice"));
}
for (i = 0; i < NDOSPART; i++)
partp[i].dp_flag = 0;
partp[active].dp_flag = ACTIVE;
}
get_params_to_use()
{
int tmp;
print_params();
if (ok("Do you want to change our idea of what BIOS thinks ?"))
{
do
{
Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
Decimal("BIOS's idea of #heads", dos_heads, tmp);
Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
dos_cylsecs = dos_heads * dos_sectors;
print_params();
}
while(!ok("Are you happy with this choice"));
}
}
/***********************************************\
* Change real numbers into strange dos numbers *
\***********************************************/
static
dos(sec, c, s, h)
int sec;
unsigned char *c, *s, *h;
{
int cy;
int hd;
cy = sec / ( dos_cylsecs );
sec = sec - cy * ( dos_cylsecs );
hd = sec / dos_sectors;
sec = (sec - hd * dos_sectors) + 1;
*h = hd;
*c = cy & 0xff;
*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
}
int fd;
/* Getting device status */
open_disk(u_flag)
{
struct stat st;
if (stat(disk, &st) == -1) {
fprintf(stderr, "%s: Can't get file status of %s\n",
name, disk);
return -1;
} else if ( !(st.st_mode & S_IFCHR) ) {
fprintf(stderr,"%s: Device %s is not character special\n",
name, disk);
return -1;
}
if ((fd = open(disk, u_flag?O_RDWR:O_RDONLY)) == -1) {
fprintf(stderr,"%s: Can't open device %s\n", name, disk);
return -1;
}
if (get_params(0) == -1) {
fprintf(stderr, "%s: Can't get disk parameters on %s\n",
name, disk);
return -1;
}
return fd;
}
read_disk(sector, buf)
{
lseek(fd,(sector * 512), 0);
return read(fd, buf, 512);
}
write_disk(sector, buf)
{
lseek(fd,(sector * 512), 0);
return write(fd, buf, 512);
}
get_params(verbose)
{
if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
return -1;
}
dos_cyls = cyls = disklabel.d_ncylinders;
dos_heads = heads = disklabel.d_ntracks;
dos_sectors = sectors = disklabel.d_nsectors;
dos_cylsecs = cylsecs = heads * sectors;
disksecs = cyls * heads * sectors;
return (disksecs);
}
read_s0()
{
if (read_disk(0, (char *) mboot.bootinst) == -1) {
fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
return -1;
}
if (mboot.signature != BOOT_MAGIC) {
fprintf(stderr, "%s: Invalid fdisk partition table found\n",
name);
/* So should we initialize things */
return -1;
}
return 0;
}
write_s0()
{
int flag;
if (iotest) {
print_s0(-1);
return 0;
}
/*
* write enable label sector before write (if necessary),
* disable after writing.
* needed if the disklabel protected area also protects
* sector 0. (e.g. empty disk)
*/
flag = 1;
if (ioctl(fd, DIOCWLABEL, &flag) < 0)
perror("ioctl DIOCWLABEL");
if (write_disk(0, (char *) mboot.bootinst) == -1) {
fprintf(stderr, "%s: Can't write fdisk partition table\n",
name);
return -1;
flag = 0;
(void) ioctl(fd, DIOCWLABEL, &flag);
}
}
ok(str)
char *str;
{
printf("%s [n] ", str);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (*lbuf &&
(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
!strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
return 1;
else
return 0;
}
decimal(str, num, deflt)
char *str;
int *num;
{
int acc = 0, c;
char *cp;
while (1) {
printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (!*lbuf)
return 0;
cp = lbuf;
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c)
return 0;
while (c = *cp++) {
if (c <= '9' && c >= '0')
acc = acc * 10 + c - '0';
else
break;
}
if (c == ' ' || c == '\t')
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c) {
*num = acc;
return 1;
} else
printf("%s is an invalid decimal number. Try again\n",
lbuf);
}
}
hex(str, num, deflt)
char *str;
int *num;
{
int acc = 0, c;
char *cp;
while (1) {
printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (!*lbuf)
return 0;
cp = lbuf;
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c)
return 0;
while (c = *cp++) {
if (c <= '9' && c >= '0')
acc = (acc << 4) + c - '0';
else if (c <= 'f' && c >= 'a')
acc = (acc << 4) + c - 'a' + 10;
else if (c <= 'F' && c >= 'A')
acc = (acc << 4) + c - 'A' + 10;
else
break;
}
if (c == ' ' || c == '\t')
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c) {
*num = acc;
return 1;
} else
printf("%s is an invalid hex number. Try again\n",
lbuf);
}
}
string(str, ans)
char *str;
char **ans;
{
int c;
char *cp = lbuf;
while (1) {
printf("Supply a string value for \"%s\" [%s] ", str, *ans);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (!*lbuf)
return 0;
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (c == '"') {
c = *++cp;
*ans = cp;
while ((c = *cp) && c != '"') cp++;
} else {
*ans = cp;
while ((c = *cp) && c != ' ' && c != '\t') cp++;
}
if (c)
*cp = 0;
return 1;
}
}
char *get_type(type)
int type;
{
int numentries = (sizeof(part_types)/sizeof(struct part_type));
int counter = 0;
struct part_type *ptr = part_types;
while(counter < numentries)
{
if(ptr->type == type)
{
return(ptr->name);
}
ptr++;
counter++;
}
return("unknown");
}
+6
View File
@@ -0,0 +1,6 @@
# @(#)Makefile 5.4 (Berkeley) 6/5/91
PROG= comcontrol
NOMAN= noman
.include <bsd.prog.mk>
+79
View File
@@ -0,0 +1,79 @@
/*-
* Copyright (c) 1992 Christopher G. Demetriou
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* comcontrol.c */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <fcntl.h>
void usage(char *progname)
{
fprintf(stderr, "usage: %s <filename> [[-]bidir]\n", progname);
exit(1);
}
int main(int argc, char *argv[])
{
int fd;
int res;
if ((argc < 2) || (argc > 3)) usage(argv[0]);
fd = open(argv[1], O_RDONLY|O_NONBLOCK, 0);
if (fd < 0) {
fprintf(stderr, "%s: couldn't open file %s\n", argv[0], argv[1]);
perror("open");
exit(1);
}
if (argc == 2) {
if (ioctl(fd, TIOCMGBIDIR, &res) < 0) {
perror("ioctl");
exit(1);
}
if (!res) printf("-");
printf("bidir\n");
} else {
if (!strcmp(argv[2],"bidir")) {
res = 1;
} else if (!strcmp(argv[2],"-bidir")) {
res = 0;
} else {
usage(argv[0]);
}
if (ioctl(fd, TIOCMSBIDIR, &res) < 0) {
perror("ioctl");
exit(1);
}
}
close(fd);
}
+9
View File
@@ -0,0 +1,9 @@
# @(#)Makefile 1.1 (Julian Elischer) 3/28/93
#
#
PROG= fdisk
SRCS= fdisk.c
MAN8= fdisk.0
.include <bsd.prog.mk>
+177
View File
@@ -0,0 +1,177 @@
.Dd April 4, 1993
.Dt FDISK 8
.\".Os BSD 4
.Sh NAME
.Nm fdisk
.Nd DOS partition maintainance program
.Sh SYNOPSIS
.Nm
.Op Fl i
.Op Fl u
.Bl -tag -width time
.It Fl i
Initializes sector 0 of the disk.
.It Fl u
Is used for updating (editing) sector 0 of the disk.
.El
.Sh PROLOGUE
In order for the BIOS to boot the kernel,
certain conventions must be adhered to.
Sector 0 of the disk must contain boot code,
a partition table,
and a magic number.
BIOS partitions can be used to break the disk up into several pieces.
The BIOS brings in sector 0
(does it really use the code?)
and verifies the magic number.
It then searches the 4 BIOS partitions described by sector 0
to determine which of them is
.Em active.
This boot then brings in the secondary boot block from the
.Em active
partition and runs it.
Under DOS,
you could have one or more partitions with one
.Em active.
The DOS
.Nm
program can be used to divide space on the disk into partitions and set one
.Em active.
.Sh DESCRIPTION
The 386bsd program
.Nm
serves a similar purpose to the DOS program.
When called with no arguments, it prints the sector 0 partition table.
An example follows:
.Bd -literal
******* Working on device /dev/rwd0d *******
parameters extracted from in-core disklabel are:
cylinders=769 heads=15 sectors/track=33 (495 blks/cyl)
parameters to be used for BIOS calculations are:
cylinders=769 heads=15 sectors/track=33 (495 blks/cyl)
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 0 is:
sysid 165,(386BSD)
start 495, size 380160 (185 Meg), flag 0
beg: cyl 1/ sector 1/ head 0;
end: cyl 768/ sector 33/ head 14
The data for partition 1 is:
sysid 164,(unknown)
start 378180, size 2475 (1 Meg), flag 0
beg: cyl 764/ sector 1/ head 0;
end: cyl 768/ sector 33/ head 14
The data for partition 2 is:
<UNUSED>
The data for partition 3 is:
sysid 99,(ISC UNIX, other System V/386, GNU HURD or Mach)
start 380656, size 224234 (109 Meg), flag 80
beg: cyl 769/ sector 2/ head 0;
end: cyl 197/ sector 33/ head 14
.Ed
.Pp
The disk is divided into three parititions that happen to fill the disk.
The second partition overlaps the end of the first.
(Used for debugging purposes)
.Bl -tag -width "cyl, sector and head"
.It Em "sysid"
is used to label the partition. 386bsd reserves the
magic number 165 decimal (A5 in hex).
.It Em "start and size"
fields provide the start address
and size of a parition in sectors.
.It Em "flag 80"
specifies that this is the active partition.
.It Em "cyl, sector and head"
fields are used to specify the beginning address
and end address for the parititon.
.It Em "Note:"
these numbers are calculated using BIOS's understanding of the disk geometry
and saved in the bootblock.
.El
.Pp
The flags
.Fl i
or
.Fl u
are used to indicate that the paritition data is to be updated.
The
.Nm
program will enter a conversational mode.
This mode is designed not to change any data unless you explicitly tell it to.
.Nm
selects defaults for its questions to guarantee the above behaviour.
.Pp
It displays each partition
and ask if you want to edit it.
If you say yes,
it will step through each field showing the old value
and asking for a new one.
When you are done with a partition,
.Nm
will display it and ask if it is correct.
.Nm
will then procede to the next entry.
.Pp
Getting the
.Em cyl, sector,
and
.Em head
fields correct is tricky.
So by default,
they will be calculated for you;
you can specify them if you choose.
.Pp
After all the partitions are processed,
you are given the option to change the
.Em active
partition.
Finally,
when the all the data for the first sector has been accumulated,
you are asked if you really want to rewrite sector 0.
Only if you answer yes,
will the data be written to disk.
.Pp
The difference between the
.Fl u
flag and
.Fl i
flag is that
the
.Fl u
flag just edits the fields as they appear on the disk.
While the
.Fl i
flag is used to "initialize" sector 0;
it will setup the last BIOS partition to use the whole disk for 386bsd;
and make it active.
.Sh NOTES
.Pp
The automatic calculation of starting cylinder etc. uses
a set of figures that represent what the BIOS thinks is the
geometry of the drive.
These figures are by default taken from the incore disklabel,
but the program initially gives you an oportunity to change them.
This allows the user to create a bootblock that can work with drives
that use geometry translation under the BIOS.
.Pp
If you hand craft your disk layout,
please make sure that the 386bsd partition starts on a cylinder boundary.
A number of decisions made later may assume this.
(This might not be necessary later.)
.Pp
Editing an existing partition will most likely cause you to
lose all the data in that partition.
.Pp
You should run this program interactively once or twice to see how it works.
This is completely safe as long as you answer the last question in the negative.
There are subtleties
that the program detects
that are not fully explained in this manual page.
.Sh SEE ALSO
.Xr disklabel 8
.Sh BUGS
One less now, but probably more
+686
View File
@@ -0,0 +1,686 @@
/*
* Mach Operating System
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
#include <sys/types.h>
#include <sys/disklabel.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
int iotest;
#define LBUF 100
static char lbuf[LBUF];
/*
*
* Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992
*
* 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
* Copyright (c) 1989 Robert. V. Baron
* Created.
*/
#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
#define SECSIZE 512
char *disk = "/dev/rwd0d";
char *name;
struct disklabel disklabel; /* disk parameters */
int cyls, sectors, heads, cylsecs, disksecs;
struct mboot
{
unsigned char padding[2]; /* force the longs to be long alligned */
unsigned char bootinst[DOSPARTOFF];
struct dos_partition parts[4];
unsigned short int signature;
};
struct mboot mboot;
#define ACTIVE 0x80
#define BOOT_MAGIC 0xAA55
int dos_cyls;
int dos_heads;
int dos_sectors;
int dos_cylsecs;
#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
#define DOSCYL(c) (c & 0xff)
static int dos();
char *get_type();
static int partition = -1;
static int a_flag = 0; /* set active partition */
static int i_flag = 0; /* replace partition data */
static int u_flag = 0; /* update partition data */
static unsigned char bootcode[] = {
0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
struct part_type
{
unsigned char type;
char *name;
}part_types[] =
{
{0x00, "unused"}
,{0x01, "Primary DOS with 12 bit FAT"}
,{0x02, "XENIX / filesystem"}
,{0x03, "XENIX /usr filesystem"}
,{0x04, "Primary DOS with 16 bit FAT"}
,{0x05, "Extended DOS"}
,{0x06, "Primary 'big' DOS (> 32MB)"}
,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
,{0x08, "AIX filesystem"}
,{0x09, "AIX boot partition or Coherent"}
,{0x0A, "OS/2 Boot Manager or OPUS"}
,{0x10, "OPUS"}
,{0x40, "VENIX 286"}
,{0x50, "DM"}
,{0x51, "DM"}
,{0x52, "CP/M or Microport SysV/AT"}
,{0x56, "GB"}
,{0x61, "Speed"}
,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
,{0x64, "Novell Netware 2.xx"}
,{0x65, "Novell Netware 3.xx"}
,{0x75, "PCIX"}
,{0x80, "Minix 1.1 ... 1.4a"}
,{0x81, "Minix 1.4b ... 1.5.10"}
,{0x82, "Linux"}
,{0x93, "Amoeba filesystem"}
,{0x94, "Amoeba bad block table"}
,{0xA5, "386BSD"}
,{0xB7, "BSDI BSD/386 filesystem"}
,{0xB8, "BSDI BSD/386 swap"}
,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
,{0xE1, "Speed"}
,{0xE3, "Speed"}
,{0xE4, "Speed"}
,{0xF1, "Speed"}
,{0xF2, "DOS 3.3+ Secondary"}
,{0xF4, "Speed"}
,{0xFF, "BBT (Bad Blocks Table)"}
};
main(argc, argv)
char **argv;
{
int i;
name = *argv;
{register char *cp = name;
while (*cp) if (*cp++ == '/') name = cp;
}
for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
if (*token++ != '-' || !*token)
break;
else { register int flag;
for ( ; flag = *token++ ; ) {
switch (flag) {
case '0':
partition = 0;
break;
case '1':
partition = 1;
break;
case '2':
partition = 2;
break;
case '3':
partition = 3;
break;
case 'a':
a_flag = 1;
break;
case 'i':
i_flag = 1;
case 'u':
u_flag = 1;
break;
default:
goto usage;
}
}
}
}
if (argc > 0)
disk = argv[0];
if (open_disk(u_flag) < 0)
exit(1);
printf("******* Working on device %s *******\n",disk);
if(u_flag)
{
get_params_to_use();
}
else
{
print_params();
}
if (read_s0())
init_sector0(1);
printf("Warning: BIOS sector numbering starts with sector 1\n");
printf("Information from DOS bootblock is:\n");
if (partition == -1)
for (i = 0; i < NDOSPART; i++)
change_part(i);
else
change_part(partition);
if (u_flag || a_flag)
change_active(partition);
if (u_flag || a_flag) {
printf("\nWe haven't changed the partition table yet. ");
printf("This is your last chance.\n");
print_s0(-1);
if (ok("Should we write new partition table?"))
write_s0();
}
exit(0);
usage:
printf("fdisk {-a|-i|-r} {disk}\n");
}
print_s0(which)
{
int i;
print_params();
printf("Information from DOS bootblock is:\n");
if (which == -1)
for (i = 0; i < NDOSPART; i++)
printf("%d: ", i), print_part(i);
else
print_part(which);
}
static struct dos_partition mtpart = { 0 };
print_part(i)
{
struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
printf("<UNUSED>\n");
return;
}
printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
printf(" start %d, size %d (%d Meg), flag %x\n",
partp->dp_start,
partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
partp->dp_flag);
printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
,DPCYL(partp->dp_scyl, partp->dp_ssect)
,DPSECT(partp->dp_ssect)
,partp->dp_shd
,DPCYL(partp->dp_ecyl, partp->dp_esect)
,DPSECT(partp->dp_esect)
,partp->dp_ehd);
}
init_sector0(start)
{
struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
int size = disksecs - start;
int rest;
memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
mboot.signature = BOOT_MAGIC;
partp->dp_typ = DOSPTYP_386BSD;
partp->dp_flag = ACTIVE;
partp->dp_start = start;
partp->dp_size = size;
dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
}
change_part(i)
{
struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
printf("The data for partition %d is:\n", i);
print_part(i);
if (u_flag && ok("Do you want to change it?")) {
int tmp;
if (i_flag) {
bzero((char *)partp, sizeof (struct dos_partition));
if (i == 3) {
init_sector0(1);
printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
print_part(i);
}
}
do {
Decimal("sysid", partp->dp_typ, tmp);
Decimal("start", partp->dp_start, tmp);
Decimal("size", partp->dp_size, tmp);
if (ok("Explicitly specifiy beg/end address ?"))
{
int tsec,tcyl,thd;
tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
thd = partp->dp_shd;
tsec = DPSECT(partp->dp_ssect);
Decimal("beginning cylinder", tcyl, tmp);
Decimal("beginning head", thd, tmp);
Decimal("beginning sector", tsec, tmp);
partp->dp_scyl = DOSCYL(tcyl);
partp->dp_ssect = DOSSECT(tsec,tcyl);
partp->dp_shd = thd;
tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
thd = partp->dp_ehd;
tsec = DPSECT(partp->dp_esect);
Decimal("ending cylinder", tcyl, tmp);
Decimal("ending head", thd, tmp);
Decimal("ending sector", tsec, tmp);
partp->dp_ecyl = DOSCYL(tcyl);
partp->dp_esect = DOSSECT(tsec,tcyl);
partp->dp_ehd = thd;
} else {
dos(partp->dp_start,
&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
dos(partp->dp_start+partp->dp_size - 1,
&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
}
print_part(i);
} while (!ok("Are we happy with this entry?"));
}
}
print_params()
{
printf("parameters extracted from in-core disklabel are:\n");
printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
,cyls,heads,sectors,cylsecs);
if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
printf("parameters to be used for BIOS calculations are:\n");
printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
}
change_active(which)
{
int i;
int active = 3, tmp;
struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
if (a_flag && which != -1)
active = which;
if (ok("Do you want to change the active partition?")) {
do
Decimal("active partition", active, tmp);
while(!ok("Are you happy with this choice"));
}
for (i = 0; i < NDOSPART; i++)
partp[i].dp_flag = 0;
partp[active].dp_flag = ACTIVE;
}
get_params_to_use()
{
int tmp;
print_params();
if (ok("Do you want to change our idea of what BIOS thinks ?"))
{
do
{
Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
Decimal("BIOS's idea of #heads", dos_heads, tmp);
Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
dos_cylsecs = dos_heads * dos_sectors;
print_params();
}
while(!ok("Are you happy with this choice"));
}
}
/***********************************************\
* Change real numbers into strange dos numbers *
\***********************************************/
static
dos(sec, c, s, h)
int sec;
unsigned char *c, *s, *h;
{
int cy;
int hd;
cy = sec / ( dos_cylsecs );
sec = sec - cy * ( dos_cylsecs );
hd = sec / dos_sectors;
sec = (sec - hd * dos_sectors) + 1;
*h = hd;
*c = cy & 0xff;
*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
}
int fd;
/* Getting device status */
open_disk(u_flag)
{
struct stat st;
if (stat(disk, &st) == -1) {
fprintf(stderr, "%s: Can't get file status of %s\n",
name, disk);
return -1;
} else if ( !(st.st_mode & S_IFCHR) ) {
fprintf(stderr,"%s: Device %s is not character special\n",
name, disk);
return -1;
}
if ((fd = open(disk, u_flag?O_RDWR:O_RDONLY)) == -1) {
fprintf(stderr,"%s: Can't open device %s\n", name, disk);
return -1;
}
if (get_params(0) == -1) {
fprintf(stderr, "%s: Can't get disk parameters on %s\n",
name, disk);
return -1;
}
return fd;
}
read_disk(sector, buf)
{
lseek(fd,(sector * 512), 0);
return read(fd, buf, 512);
}
write_disk(sector, buf)
{
lseek(fd,(sector * 512), 0);
return write(fd, buf, 512);
}
get_params(verbose)
{
if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
return -1;
}
dos_cyls = cyls = disklabel.d_ncylinders;
dos_heads = heads = disklabel.d_ntracks;
dos_sectors = sectors = disklabel.d_nsectors;
dos_cylsecs = cylsecs = heads * sectors;
disksecs = cyls * heads * sectors;
return (disksecs);
}
read_s0()
{
if (read_disk(0, (char *) mboot.bootinst) == -1) {
fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
return -1;
}
if (mboot.signature != BOOT_MAGIC) {
fprintf(stderr, "%s: Invalid fdisk partition table found\n",
name);
/* So should we initialize things */
return -1;
}
return 0;
}
write_s0()
{
int flag;
if (iotest) {
print_s0(-1);
return 0;
}
/*
* write enable label sector before write (if necessary),
* disable after writing.
* needed if the disklabel protected area also protects
* sector 0. (e.g. empty disk)
*/
flag = 1;
if (ioctl(fd, DIOCWLABEL, &flag) < 0)
perror("ioctl DIOCWLABEL");
if (write_disk(0, (char *) mboot.bootinst) == -1) {
fprintf(stderr, "%s: Can't write fdisk partition table\n",
name);
return -1;
flag = 0;
(void) ioctl(fd, DIOCWLABEL, &flag);
}
}
ok(str)
char *str;
{
printf("%s [n] ", str);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (*lbuf &&
(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
!strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
return 1;
else
return 0;
}
decimal(str, num, deflt)
char *str;
int *num;
{
int acc = 0, c;
char *cp;
while (1) {
printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (!*lbuf)
return 0;
cp = lbuf;
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c)
return 0;
while (c = *cp++) {
if (c <= '9' && c >= '0')
acc = acc * 10 + c - '0';
else
break;
}
if (c == ' ' || c == '\t')
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c) {
*num = acc;
return 1;
} else
printf("%s is an invalid decimal number. Try again\n",
lbuf);
}
}
hex(str, num, deflt)
char *str;
int *num;
{
int acc = 0, c;
char *cp;
while (1) {
printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (!*lbuf)
return 0;
cp = lbuf;
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c)
return 0;
while (c = *cp++) {
if (c <= '9' && c >= '0')
acc = (acc << 4) + c - '0';
else if (c <= 'f' && c >= 'a')
acc = (acc << 4) + c - 'a' + 10;
else if (c <= 'F' && c >= 'A')
acc = (acc << 4) + c - 'A' + 10;
else
break;
}
if (c == ' ' || c == '\t')
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (!c) {
*num = acc;
return 1;
} else
printf("%s is an invalid hex number. Try again\n",
lbuf);
}
}
string(str, ans)
char *str;
char **ans;
{
int c;
char *cp = lbuf;
while (1) {
printf("Supply a string value for \"%s\" [%s] ", str, *ans);
fgets(lbuf, LBUF, stdin);
lbuf[strlen(lbuf)-1] = 0;
if (!*lbuf)
return 0;
while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
if (c == '"') {
c = *++cp;
*ans = cp;
while ((c = *cp) && c != '"') cp++;
} else {
*ans = cp;
while ((c = *cp) && c != ' ' && c != '\t') cp++;
}
if (c)
*cp = 0;
return 1;
}
}
char *get_type(type)
int type;
{
int numentries = (sizeof(part_types)/sizeof(struct part_type));
int counter = 0;
struct part_type *ptr = part_types;
while(counter < numentries)
{
if(ptr->type == type)
{
return(ptr->name);
}
ptr++;
counter++;
}
return("unknown");
}
+43
View File
@@ -0,0 +1,43 @@
/*
* IBM PC display definitions
*/
/* Color attributes for foreground text */
#define FG_BLACK 0
#define FG_BLUE 1
#define FG_GREEN 2
#define FG_CYAN 3
#define FG_RED 4
#define FG_MAGENTA 5
#define FG_BROWN 6
#define FG_LIGHTGREY 7
#define FG_DARKGREY 8
#define FG_LIGHTBLUE 9
#define FG_LIGHTGREEN 10
#define FG_LIGHTCYAN 11
#define FG_LIGHTRED 12
#define FG_LIGHTMAGENTA 13
#define FG_YELLOW 14
#define FG_WHITE 15
#define FG_BLINK 0x80
/* Color attributes for text background */
#define BG_BLACK 0x00
#define BG_BLUE 0x10
#define BG_GREEN 0x20
#define BG_CYAN 0x30
#define BG_RED 0x40
#define BG_MAGENTA 0x50
#define BG_BROWN 0x60
#define BG_LIGHTGREY 0x70
/* Monochrome attributes for foreground text */
#define FG_UNDERLINE 0x01
#define FG_INTENSE 0x08
/* Monochrome attributes for text background */
#define BG_INTENSE 0x10
+63
View File
@@ -0,0 +1,63 @@
/*
* msdos common header file
* [obtained from mtools -wfj]
* how to decipher DOS disk structures in coexisting with DOS
*/
#define MSECTOR_SIZE 512 /* MSDOS sector size in bytes */
#define MDIR_SIZE 32 /* MSDOS directory size in bytes */
#define MAX_CLUSTER 8192 /* largest cluster size */
#define MAX_PATH 128 /* largest MSDOS path length */
#define MAX_DIR_SECS 64 /* largest directory (in sectors) */
#define NEW 1
#define OLD 0
struct directory {
unsigned char name[8]; /* file name */
unsigned char ext[3]; /* file extension */
unsigned char attr; /* attribute byte */
unsigned char reserved[10]; /* ?? */
unsigned char time[2]; /* time stamp */
unsigned char date[2]; /* date stamp */
unsigned char start[2]; /* starting cluster number */
unsigned char size[4]; /* size of the file */
};
struct bootsector {
unsigned char jump[3]; /* Jump to boot code */
unsigned char banner[8]; /* OEM name & version */
unsigned char secsiz[2]; /* Bytes per sector hopefully 512 */
unsigned char clsiz; /* Cluster size in sectors */
unsigned char nrsvsect[2]; /* Number of reserved (boot) sectors */
unsigned char nfat; /* Number of FAT tables hopefully 2 */
unsigned char dirents[2]; /* Number of directory slots */
unsigned char psect[2]; /* Total sectors on disk */
unsigned char descr; /* Media descriptor=first byte of FAT */
unsigned char fatlen[2]; /* Sectors in FAT */
unsigned char nsect[2]; /* Sectors/track */
unsigned char nheads[2]; /* Heads */
unsigned char nhs[4]; /* number of hidden sectors */
unsigned char bigsect[4]; /* big total sectors */
unsigned char junk[476]; /* who cares? */
};
/* DOS partition table -- located in boot block */
#define DOSBBSECTOR 0 /* DOS boot block relative sector number */
#define DOSPARTOFF 446
#define NDOSPART 4
struct dos_partition {
unsigned char dp_flag; /* bootstrap flags */
unsigned char dp_shd; /* starting head */
unsigned char dp_ssect; /* starting sector */
unsigned char dp_scyl; /* starting cylinder */
unsigned char dp_typ; /* partition type */
#define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */
unsigned char dp_ehd; /* end head */
unsigned char dp_esect; /* end sector */
unsigned char dp_ecyl; /* end cylinder */
unsigned long dp_start; /* absolute starting sector number */
unsigned long dp_size; /* partition size in sectors */
} dos_partitions[NDOSPART];
+24
View File
@@ -0,0 +1,24 @@
# @(#)Makefile 7.3 (Berkeley) 6/9/91
# Makefile for i386 tags file
all:
@echo "make tags or links only"
TI386= ../i386/tags
SI386= ../i386/i386/*.[ch] ../i386/include/*.h ../i386/isa/*.[ch]
AI386= ../i386/i386/*.s
# Directories in which to place i386 tags links
DI386= eisa isa mca include
tags:
-ctags -dtf ${TI386} ${COMM} ${SI386}
egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AI386} | \
sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
>> ${TI386}
sort -o ${TI386} ${TI386}
links:
-for i in ${DI386}; do \
cd $$i && rm -f tags; ln -s ../tags tags; done
+213
View File
@@ -0,0 +1,213 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)autoconf.c 7.1 (Berkeley) 5/9/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00117
* -------------------- ----- ----------------------
*
* 09 Apr 93 ???(From sun-lamp) Fix to report sd when Julians
* scsi code is used, allow you to swap
* root floppies during a boot
*/
static char rcsid[] = "$Header: /b/source/CVS/src/sys.386bsd/i386/i386/autoconf.c,v 1.3 1993/04/10 21:58:52 cgd Exp $";
/*
* Setup the system to run on the current machine.
*
* Configure() is called at boot time and initializes the vba
* device tables and the memory controller monitoring. Available
* devices are determined (from possibilities mentioned in ioconf.c),
* and the drivers are initialized.
*/
#include "param.h"
#include "systm.h"
#include "buf.h"
#include "dkstat.h"
#include "conf.h"
#include "dmap.h"
#include "reboot.h"
#include "machine/pte.h"
/*
* The following several variables are related to
* the configuration process, and are used in initializing
* the machine.
*/
int dkn; /* number of iostat dk numbers assigned so far */
extern int cold; /* cold start flag initialized in locore.s */
/*
* Determine i/o configuration for a machine.
*/
configure()
{
#include "isa.h"
#if NISA > 0
isa_configure();
#endif
#if GENERICxxx
if ((boothowto & RB_ASKNAME) == 0)
setroot();
setconf();
#else
setroot();
#endif
/*
* Configure swap area and related system
* parameter based on device(s) used.
*/
swapconf();
cold = 0;
}
/*
* Configure swap space and related parameters.
*/
swapconf()
{
register struct swdevt *swp;
register int nblks;
extern int Maxmem;
for (swp = swdevt; swp->sw_dev > 0; swp++)
{
unsigned d = major(swp->sw_dev);
if (d > nblkdev) break;
if (bdevsw[d].d_psize) {
nblks = (*bdevsw[d].d_psize)(swp->sw_dev);
if (nblks > 0 &&
(swp->sw_nblks == 0 || swp->sw_nblks > nblks))
swp->sw_nblks = nblks;
else
swp->sw_nblks = 0;
}
swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
}
if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize)
/*dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem;*/
dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) -
Maxmem*NBPG/512;
if (dumplo < 0)
dumplo = 0;
}
#define DOSWAP /* change swdevt and dumpdev */
u_long bootdev = 0; /* should be dev_t, but not until 32 bits */
#include "sd.h"
static char devname[][2] = {
'w','d', /* 0 = wd */
's','w', /* 1 = sw */
'f','d', /* 2 = fd */
'w','t', /* 3 = wt */
#if NSD < 1
'a','s', /* 4 = as */
#else
's','d', /* 4 = sd -- new SCSI system */
#endif
};
#define PARTITIONMASK 0x7
#define PARTITIONSHIFT 3
/*
* Attempt to find the device from which we were booted.
* If we can do so, and not instructed not to do so,
* change rootdev to correspond to the load device.
*/
setroot()
{
int majdev, mindev, unit, part, adaptor;
dev_t temp, orootdev;
struct swdevt *swp;
/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
if (boothowto & RB_DFLTROOT ||
(bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
return;
majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
if (majdev > sizeof(devname) / sizeof(devname[0]))
return;
adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
mindev = (unit << PARTITIONSHIFT) + part;
orootdev = rootdev;
rootdev = makedev(majdev, mindev);
/*
* If the original rootdev is the same as the one
* just calculated, don't need to adjust the swap configuration.
*/
if (rootdev == orootdev)
return;
if (devname[majdev][0] == 'f' && devname[majdev][1] == 'd') {
printf("");
printf("* insert the floppy you want to have mounted as\n");
printf("* root, and hit any key to continue booting:\n");
cngetc();
printf("");
}
printf("changing root device to %c%c%d%c\n",
devname[majdev][0], devname[majdev][1],
mindev >> PARTITIONSHIFT, part + 'a');
#ifdef DOSWAP
mindev &= ~PARTITIONMASK;
for (swp = swdevt; swp->sw_dev; swp++) {
if (majdev == major(swp->sw_dev) &&
mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
temp = swdevt[0].sw_dev;
swdevt[0].sw_dev = swp->sw_dev;
swp->sw_dev = temp;
break;
}
}
if (swp->sw_dev == 0)
return;
/*
* If dumpdev was the same as the old primary swap
* device, move it to the new primary swap device.
*/
if (temp == dumpdev)
dumpdev = swdevt[0].sw_dev;
#endif
}
File diff suppressed because it is too large Load Diff
+255
View File
@@ -0,0 +1,255 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_interface.c,v $
* Revision 1.1 1992/03/25 21:42:03 pace
* Initial revision
*
* Revision 2.4 91/02/05 17:11:13 mrt
* Changed to new Mach copyright
* [91/02/01 17:31:17 mrt]
*
* Revision 2.3 90/12/04 14:45:55 jsb
* Changes for merged intel/pmap.{c,h}.
* [90/12/04 11:14:41 jsb]
*
* Revision 2.2 90/10/25 14:44:43 rwd
* Added watchpoint support.
* [90/10/18 rpd]
*
* Created.
* [90/07/25 dbg]
*
*
*/
/*
* Interface to new debugger.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <sys/reboot.h>
#include <vm/vm_statistics.h>
#include <vm/pmap.h>
#include <setjmp.h>
#include <sys/systm.h> /* just for boothowto --eichin */
int db_active = 0;
/*
* Received keyboard interrupt sequence.
*/
kdb_kbd_trap(regs)
struct i386_saved_state *regs;
{
if (db_active == 0 && (boothowto & RB_KDB)) {
printf("\n\nkernel: keyboard interrupt\n");
kdb_trap(-1, 0, regs);
}
}
/*
* kdb_trap - field a TRACE or BPT trap
*/
static jmp_buf *db_nofault = 0;
kdb_trap(type, code, regs)
int type, code;
register struct i386_saved_state *regs;
{
#if 0
if ((boothowto&RB_KDB) == 0)
return(0);
#endif
switch (type) {
case T_BPTFLT /* T_INT3 */: /* breakpoint */
case T_KDBTRAP /* T_WATCHPOINT */: /* watchpoint */
case T_PRIVINFLT /* T_DEBUG */: /* single_step */
case -1: /* keyboard interrupt */
break;
default:
kdbprinttrap(type, code);
if (db_nofault) {
jmp_buf *no_fault = db_nofault;
db_nofault = 0;
longjmp(*no_fault, 1);
}
}
/* Should switch to kdb`s own stack here. */
ddb_regs = *regs;
if ((regs->tf_cs & 0x3) == 0) {
/*
* Kernel mode - esp and ss not saved
*/
ddb_regs.tf_esp = (int)&regs->tf_esp; /* kernel stack pointer */
#if 0
ddb_regs.ss = KERNEL_DS;
#endif
asm(" movw %%ss,%%ax; movl %%eax,%0 "
: "=g" (ddb_regs.tf_ss)
:
: "ax");
}
db_active++;
cnpollc(TRUE);
db_trap(type, code);
cnpollc(FALSE);
db_active--;
regs->tf_eip = ddb_regs.tf_eip;
regs->tf_eflags = ddb_regs.tf_eflags;
regs->tf_eax = ddb_regs.tf_eax;
regs->tf_ecx = ddb_regs.tf_ecx;
regs->tf_edx = ddb_regs.tf_edx;
regs->tf_ebx = ddb_regs.tf_ebx;
if (regs->tf_cs & 0x3) {
/*
* user mode - saved esp and ss valid
*/
regs->tf_esp = ddb_regs.tf_esp; /* user stack pointer */
regs->tf_ss = ddb_regs.tf_ss & 0xffff; /* user stack segment */
}
regs->tf_ebp = ddb_regs.tf_ebp;
regs->tf_esi = ddb_regs.tf_esi;
regs->tf_edi = ddb_regs.tf_edi;
regs->tf_es = ddb_regs.tf_es & 0xffff;
regs->tf_cs = ddb_regs.tf_cs & 0xffff;
regs->tf_ds = ddb_regs.tf_ds & 0xffff;
#if 0
regs->tf_fs = ddb_regs.tf_fs & 0xffff;
regs->tf_gs = ddb_regs.tf_gs & 0xffff;
#endif
return (1);
}
/*
* Print trap reason.
*/
kdbprinttrap(type, code)
int type, code;
{
printf("kernel: ");
printf("type %d", type);
printf(" trap, code=%x\n", code);
}
/*
* Read bytes from kernel address space for debugger.
*/
extern jmp_buf db_jmpbuf;
void
db_read_bytes(addr, size, data)
vm_offset_t addr;
register int size;
register char *data;
{
register char *src;
db_nofault = &db_jmpbuf;
src = (char *)addr;
while (--size >= 0)
*data++ = *src++;
db_nofault = 0;
}
struct pte *pmap_pte(pmap_t, vm_offset_t);
/*
* Write bytes to kernel address space for debugger.
*/
void
db_write_bytes(addr, size, data)
vm_offset_t addr;
register int size;
register char *data;
{
register char *dst;
register pt_entry_t *ptep0 = 0;
pt_entry_t oldmap0 = { 0 };
vm_offset_t addr1;
register pt_entry_t *ptep1 = 0;
pt_entry_t oldmap1 = { 0 };
extern char etext;
db_nofault = &db_jmpbuf;
if (addr >= VM_MIN_KERNEL_ADDRESS &&
addr <= (vm_offset_t)&etext)
{
ptep0 = pmap_pte(kernel_pmap, addr);
oldmap0 = *ptep0;
*(int *)ptep0 |= /* INTEL_PTE_WRITE */ PG_RW;
addr1 = i386_trunc_page(addr + size - 1);
if (i386_trunc_page(addr) != addr1) {
/* data crosses a page boundary */
ptep1 = pmap_pte(kernel_pmap, addr1);
oldmap1 = *ptep1;
*(int *)ptep1 |= /* INTEL_PTE_WRITE */ PG_RW;
}
tlbflush();
}
dst = (char *)addr;
while (--size >= 0)
*dst++ = *data++;
db_nofault = 0;
if (ptep0) {
*ptep0 = oldmap0;
if (ptep1) {
*ptep1 = oldmap1;
}
tlbflush();
}
}
Debugger (msg)
char *msg;
{
asm ("int $3");
}
+292
View File
@@ -0,0 +1,292 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_trace.c,v $
* Revision 1.1 1992/03/25 21:42:05 pace
* Initial revision
*
* Revision 2.6 91/02/05 17:11:21 mrt
* Changed to new Mach copyright
* [91/02/01 17:31:32 mrt]
*
* Revision 2.5 91/01/09 19:55:27 rpd
* Fixed stack tracing for threads without kernel stacks.
* [91/01/09 rpd]
*
* Revision 2.4 91/01/08 15:10:22 rpd
* Reorganized the pcb.
* [90/12/11 rpd]
*
* Revision 2.3 90/11/05 14:27:07 rpd
* If we can not guess the number of args to a function, use 5 vs 0.
* [90/11/02 rvb]
*
* Revision 2.2 90/08/27 21:56:20 dbg
* Import db_sym.h.
* [90/08/21 dbg]
* Fix includes.
* [90/08/08 dbg]
* Created from rvb's code for new debugger.
* [90/07/11 dbg]
*
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
/*
* Machine register set.
*/
struct db_variable db_regs[] = {
"cs", (int *)&ddb_regs.tf_cs, FCN_NULL,
"ds", (int *)&ddb_regs.tf_ds, FCN_NULL,
"es", (int *)&ddb_regs.tf_es, FCN_NULL,
#if 0
"fs", (int *)&ddb_regs.tf_fs, FCN_NULL,
"gs", (int *)&ddb_regs.tf_gs, FCN_NULL,
#endif
"ss", (int *)&ddb_regs.tf_ss, FCN_NULL,
"eax", (int *)&ddb_regs.tf_eax, FCN_NULL,
"ecx", (int *)&ddb_regs.tf_ecx, FCN_NULL,
"edx", (int *)&ddb_regs.tf_edx, FCN_NULL,
"ebx", (int *)&ddb_regs.tf_ebx, FCN_NULL,
"esp", (int *)&ddb_regs.tf_esp,FCN_NULL,
"ebp", (int *)&ddb_regs.tf_ebp, FCN_NULL,
"esi", (int *)&ddb_regs.tf_esi, FCN_NULL,
"edi", (int *)&ddb_regs.tf_edi, FCN_NULL,
"eip", (int *)&ddb_regs.tf_eip, FCN_NULL,
"efl", (int *)&ddb_regs.tf_eflags, FCN_NULL,
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
/*
* Stack trace.
*/
#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
struct i386_frame {
struct i386_frame *f_frame;
int f_retaddr;
int f_arg0;
};
#define TRAP 1
#define INTERRUPT 2
db_addr_t db_trap_symbol_value = 0;
db_addr_t db_kdintr_symbol_value = 0;
boolean_t db_trace_symbols_found = FALSE;
void
db_find_trace_symbols()
{
db_expr_t value;
if (db_value_of_name("_trap", &value))
db_trap_symbol_value = (db_addr_t) value;
if (db_value_of_name("_kdintr", &value))
db_kdintr_symbol_value = (db_addr_t) value;
db_trace_symbols_found = TRUE;
}
/*
* Figure out how many arguments were passed into the frame at "fp".
*/
int
db_numargs(fp)
struct i386_frame *fp;
{
int *argp;
int inst;
int args;
extern char etext[];
argp = (int *)db_get_value((int)&fp->f_retaddr, 4, FALSE);
if (argp < (int *)VM_MIN_KERNEL_ADDRESS || argp > (int *)etext)
args = 5;
else {
inst = db_get_value((int)argp, 4, FALSE);
if ((inst & 0xff) == 0x59) /* popl %ecx */
args = 1;
else if ((inst & 0xffff) == 0xc483) /* addl %n, %esp */
args = ((inst >> 16) & 0xff) / 4;
else
args = 5;
}
return (args);
}
/*
* Figure out the next frame up in the call stack.
* For trap(), we print the address of the faulting instruction and
* proceed with the calling frame. We return the ip that faulted.
* If the trap was caused by jumping through a bogus pointer, then
* the next line in the backtrace will list some random function as
* being called. It should get the argument list correct, though.
* It might be possible to dig out from the next frame up the name
* of the function that faulted, but that could get hairy.
*/
void
db_nextframe(fp, ip, argp, is_trap)
struct i386_frame **fp; /* in/out */
db_addr_t *ip; /* out */
int *argp; /* in */
int is_trap; /* in */
{
struct i386_saved_state *saved_regs;
if (is_trap == 0) {
*ip = (db_addr_t)
db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
*fp = (struct i386_frame *)
db_get_value((int) &(*fp)->f_frame, 4, FALSE);
} else {
/*
* We know that trap() has 1 argument and we know that
* it is an (int *).
*/
saved_regs = (struct i386_saved_state *)
db_get_value((int)argp, 4, FALSE);
db_printf("--- trap (number %d) ---\n",
saved_regs->tf_trapno & 0xffff);
db_printsym(saved_regs->tf_eip, DB_STGY_XTRN);
db_printf(":\n");
*fp = (struct i386_frame *)saved_regs->tf_ebp;
*ip = (db_addr_t)saved_regs->tf_eip;
}
}
void
db_stack_trace_cmd(addr, have_addr, count, modif)
db_expr_t addr;
boolean_t have_addr;
db_expr_t count;
char *modif;
{
struct i386_frame *frame, *lastframe;
int *argp;
db_addr_t callpc;
int is_trap;
boolean_t kernel_only = TRUE;
boolean_t trace_thread = FALSE;
if (!db_trace_symbols_found)
db_find_trace_symbols();
{
register char *cp = modif;
register char c;
while ((c = *cp++) != 0) {
if (c == 't')
trace_thread = TRUE;
if (c == 'u')
kernel_only = FALSE;
}
}
if (count == -1)
count = 65535;
if (!have_addr) {
frame = (struct i386_frame *)ddb_regs.tf_ebp;
callpc = (db_addr_t)ddb_regs.tf_eip;
}
else if (trace_thread) {
printf ("db_trace.c: can't trace thread\n");
}
else {
frame = (struct i386_frame *)addr;
callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
}
lastframe = 0;
while (count-- && frame != 0) {
register int narg;
char * name;
db_expr_t offset;
if (INKERNEL((int)frame) && callpc == db_trap_symbol_value) {
narg = 1;
is_trap = TRAP;
}
else
if (INKERNEL((int)frame) && callpc == db_kdintr_symbol_value) {
is_trap = INTERRUPT;
narg = 0;
}
else {
is_trap = 0;
narg = db_numargs(frame);
}
db_find_sym_and_offset(callpc, &name, &offset);
db_printf("%s(", name);
argp = &frame->f_arg0;
while (narg) {
db_printf("%x", db_get_value((int)argp, 4, FALSE));
argp++;
if (--narg != 0)
db_printf(",");
}
db_printf(") at ");
db_printsym(callpc, DB_STGY_XTRN);
db_printf("\n");
lastframe = frame;
db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap);
if (frame == 0) {
/* end of chain */
break;
}
if (INKERNEL((int)frame)) {
/* staying in kernel */
if (frame <= lastframe) {
db_printf("Bad frame pointer: 0x%x\n", frame);
break;
}
}
else if (INKERNEL((int)lastframe)) {
/* switch from user to kernel */
if (kernel_only)
break; /* kernel stack only */
}
else {
/* in user */
if (frame <= lastframe) {
db_printf("Bad frame pointer: 0x%x\n", frame);
break;
}
}
}
}
+564
View File
@@ -0,0 +1,564 @@
/*-
* Copyright (c) 1990 William Jolitz.
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)npx.c 7.2 (Berkeley) 5/12/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 20 Apr 93 Bruce Evans New npx-0.5 code
* 23 May 93 Rodney W. Grimes Return a special value of -1 from
* the probe code to keep isa_config from
* printing out the I/O address when we
* are using trap 16 handling.
*
*/
static char rcsid[] = "$Header: /usr/bill/working/sys/i386/isa/RCS/npx.c,v 1.2 92/01/21 14:34:27 william Exp $";
#include "npx.h"
#if NNPX > 0
#include "param.h"
#include "systm.h"
#include "conf.h"
#include "file.h"
#include "proc.h"
#include "machine/cpu.h"
#include "machine/pcb.h"
#include "machine/trap.h"
#include "ioctl.h"
#include "machine/specialreg.h"
#include "i386/isa/icu.h"
#include "i386/isa/isa_device.h"
#include "i386/isa/isa.h"
/*
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
*/
#ifdef __GNUC__
#define disable_intr() __asm("cli")
#define enable_intr() __asm("sti")
#define fldcw(addr) __asm("fldcw %0" : : "m" (*addr))
#define fnclex() __asm("fnclex")
#define fninit() __asm("fninit")
#define fnsave(addr) __asm("fnsave %0" : "=m" (*addr) : "0" (*addr))
#define fnstcw(addr) __asm("fnstcw %0" : "=m" (*addr) : "0" (*addr))
#define fnstsw(addr) __asm("fnstsw %0" : "=m" (*addr) : "0" (*addr))
#define fp_divide_by_0() __asm("fldz; fld1; fdiv %st,%st(1); fwait")
#define frstor(addr) __asm("frstor %0" : : "m" (*addr))
#define fwait() __asm("fwait")
#define read_eflags() ({u_long ef; \
__asm("pushf; popl %0" : "=a" (ef)); \
ef; })
#define start_emulating() __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
: : "n" (CR0_TS) : "ax")
#define stop_emulating() __asm("clts")
#define write_eflags(ef) __asm("pushl %0; popf" : : "a" ((u_long) ef))
#else /* not __GNUC__ */
void disable_intr __P((void));
void enable_intr __P((void));
void fldcw __P((caddr_t addr));
void fnclex __P((void));
void fninit __P((void));
void fnsave __P((caddr_t addr));
void fnstcw __P((caddr_t addr));
void fnstsw __P((caddr_t addr));
void fp_divide_by_0 __P((void));
void frstor __P((caddr_t addr));
void fwait __P((void));
u_long read_eflags __P((void));
void start_emulating __P((void));
void stop_emulating __P((void));
void write_eflags __P((u_long ef));
#endif /* __GNUC__ */
typedef u_char bool_t;
extern struct gate_descriptor idt[];
int npxdna __P((void));
void npxexit __P((struct proc *p));
void npxinit __P((u_int control));
void npxintr __P((struct intrframe frame));
void npxsave __P((struct save87 *addr));
static int npxattach __P((struct isa_device *dvp));
static int npxprobe __P((struct isa_device *dvp));
static int npxprobe1 __P((struct isa_device *dvp));
struct isa_driver npxdriver = {
npxprobe, npxattach, "npx",
};
u_int npx0mask;
struct proc *npxproc;
static bool_t npx_ex16;
static bool_t npx_exists;
static struct gate_descriptor npx_idt_probeintr;
static int npx_intrno;
static volatile u_int npx_intrs_while_probing;
static bool_t npx_irq13;
static volatile u_int npx_traps_while_probing;
/*
* Special interrupt handlers. Someday intr0-intr15 will be used to count
* interrupts. We'll still need a special exception 16 handler. The busy
* latch stuff in probintr() can be moved to npxprobe().
*/
void probeintr(void);
asm
("
.text
_probeintr:
ss
incl _npx_intrs_while_probing
pushl %eax
movb $0x20,%al /* EOI (asm in strings loses cpp features) */
outb %al,$0xa0 /* IO_ICU2 */
outb %al,$0x20 /* IO_ICU1 */
movb $0,%al
outb %al,$0xf0 /* clear BUSY# latch */
popl %eax
iret
");
void probetrap(void);
asm
("
.text
_probetrap:
ss
incl _npx_traps_while_probing
fnclex
iret
");
/*
* Probe routine. Initialize cr0 to give correct behaviour for [f]wait
* whether the device exists or not (XXX should be elsewhere). Set flags
* to tell npxattach() what to do. Modify device struct if npx doesn't
* need to use interrupts. Return 1 if device exists.
*/
static int
npxprobe(dvp)
struct isa_device *dvp;
{
int result;
u_long save_eflags;
u_char save_icu1_mask;
u_char save_icu2_mask;
struct gate_descriptor save_idt_npxintr;
struct gate_descriptor save_idt_npxtrap;
/*
* This routine is now just a wrapper for npxprobe1(), to install
* special npx interrupt and trap handlers, to enable npx interrupts
* and to disable other interrupts. Someday isa_configure() will
* install suitable handlers and run with interrupts enabled so we
* won't need to do so much here.
*/
npx_intrno = NRSVIDT + ffs(dvp->id_irq) - 1;
save_eflags = read_eflags();
disable_intr();
save_icu1_mask = inb(IO_ICU1 + 1);
save_icu2_mask = inb(IO_ICU2 + 1);
save_idt_npxintr = idt[npx_intrno];
save_idt_npxtrap = idt[16];
outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq));
outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8));
setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL);
setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL);
npx_idt_probeintr = idt[npx_intrno];
enable_intr();
result = npxprobe1(dvp);
disable_intr();
outb(IO_ICU1 + 1, save_icu1_mask);
outb(IO_ICU2 + 1, save_icu2_mask);
idt[npx_intrno] = save_idt_npxintr;
idt[16] = save_idt_npxtrap;
write_eflags(save_eflags);
return (result);
}
static int
npxprobe1(dvp)
struct isa_device *dvp;
{
int control;
int status;
#ifdef lint
npxintr();
#endif
/*
* Partially reset the coprocessor, if any. Some BIOS's don't reset
* it after a warm boot.
*/
outb(0xf1, 0); /* full reset on some systems, NOP on others */
outb(0xf0, 0); /* clear BUSY# latch */
/*
* Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
* instructions. We must set the CR0_MP bit and use the CR0_TS
* bit to control the trap, because setting the CR0_EM bit does
* not cause WAIT instructions to trap. It's important to trap
* WAIT instructions - otherwise the "wait" variants of no-wait
* control instructions would degenerate to the "no-wait" variants
* after FP context switches but work correctly otherwise. It's
* particularly important to trap WAITs when there is no NPX -
* otherwise the "wait" variants would always degenerate.
*
* Try setting CR0_NE to get correct error reporting on 486DX's.
* Setting it should fail or do nothing on lesser processors.
*/
load_cr0(rcr0() | CR0_MP | CR0_NE);
/*
* But don't trap while we're probing.
*/
stop_emulating();
/*
* Finish resetting the coprocessor, if any. If there is an error
* pending, then we may get a bogus IRQ13, but probeintr() will handle
* it OK. Bogus halts have never been observed, but we enabled
* IRQ13 and cleared the BUSY# latch early to handle them anyway.
*/
fninit();
DELAY(1000); /* wait for any IRQ13 (fwait might hang) */
#ifdef DIAGNOSTIC
if (npx_intrs_while_probing != 0)
printf("fninit caused %u bogus npx interrupt(s)\n",
npx_intrs_while_probing);
if (npx_traps_while_probing != 0)
printf("fninit caused %u bogus npx trap(s)\n",
npx_traps_while_probing);
#endif
/*
* Check for a status of mostly zero.
*/
status = 0x5a5a;
fnstsw(&status);
if ((status & 0xb8ff) == 0) {
/*
* Good, now check for a proper control word.
*/
control = 0x5a5a;
fnstcw(&control);
if ((control & 0x1f3f) == 0x033f) {
npx_exists = 1;
/*
* We have an npx, now divide by 0 to see if exception
* 16 works.
*/
control &= ~(1 << 2); /* enable divide by 0 trap */
fldcw(&control);
npx_traps_while_probing = npx_intrs_while_probing = 0;
fp_divide_by_0();
if (npx_traps_while_probing != 0) {
/*
* Good, exception 16 works.
*/
npx_ex16 = 1;
dvp->id_irq = 0; /* zap the interrupt */
/*
* special return value to flag that we do not
* actually use any I/O registers
*/
return (-1);
}
if (npx_intrs_while_probing != 0) {
/*
* Bad, we are stuck with IRQ13.
*/
npx_irq13 = 1;
npx0mask = dvp->id_irq; /* npxattach too late */
return (IO_NPXSIZE);
}
/*
* Worse, even IRQ13 is broken. Use emulator.
*/
}
}
/*
* Probe failed, but we want to get to npxattach to initialize the
* emulator and say that it has been installed. XXX handle devices
* that aren't really devices better.
*/
dvp->id_irq = 0;
return (IO_NPXSIZE);
}
/*
* Attach routine - announce which it is, and wire into system
*/
int
npxattach(dvp)
struct isa_device *dvp;
{
if (npx_ex16)
printf(" <Errors reported via Exception 16>");
else if (npx_irq13)
printf(" <Errors reported via IRQ 13>");
else if (npx_exists)
printf(" <Error reporting broken, using 387 emulator>");
else
printf(" <387 Emulator>");
npxinit(__INITIAL_NPXCW__);
return (1); /* XXX unused */
}
/*
* Initialize floating point unit.
*/
void
npxinit(control)
u_int control;
{
struct save87 dummy;
if (!npx_exists)
return;
/*
* fninit has the same h/w bugs as fnsave. Use the detoxified
* fnsave to throw away any junk in the fpu. fnsave initializes
* the fpu and sets npxproc = NULL as important side effects.
*/
npxsave(&dummy);
stop_emulating();
fldcw(&control);
if (curpcb != NULL)
fnsave(&curpcb->pcb_savefpu);
start_emulating();
}
/*
* Free coprocessor (if we have it).
*/
void
npxexit(p)
struct proc *p;
{
if (p == npxproc) {
start_emulating();
npxproc = NULL;
}
}
/*
* Record the FPU state and reinitialize it all except for the control word.
* Then generate a SIGFPE.
*
* Reinitializing the state allows naive SIGFPE handlers to longjmp without
* doing any fixups.
*
* XXX there is currently no way to pass the full error state to signal
* handlers, and if this is a nested interrupt there is no way to pass even
* a status code! So there is no way to have a non-naive SIGFPE handler. At
* best a handler could do an fninit followed by an fldcw of a static value.
* fnclex would be of little use because it would leave junk on the FPU stack.
* Returning from the handler would be even less safe than usual because
* IRQ13 exception handling makes exceptions even less precise than usual.
*/
void
npxintr(frame)
struct intrframe frame;
{
int code;
if (npxproc == NULL || !npx_exists) {
/* XXX no %p in stand/printf.c. Cast to quiet gcc -Wall. */
printf("npxintr: npxproc = %lx, curproc = %lx, npx_exists = %d\n",
(u_long) npxproc, (u_long) curproc, npx_exists);
panic("npxintr from nowhere");
}
if (npxproc != curproc) {
printf("npxintr: npxproc = %lx, curproc = %lx, npx_exists = %d\n",
(u_long) npxproc, (u_long) curproc, npx_exists);
panic("npxintr from non-current process");
}
/*
* Save state. This does an implied fninit. It had better not halt
* the cpu or we'll hang.
*/
outb(0xf0, 0);
fnsave(&curpcb->pcb_savefpu);
fwait();
/*
* Restore control word (was clobbered by fnsave).
*/
fldcw(&curpcb->pcb_savefpu.sv_env.en_cw);
fwait();
/*
* Remember the exception status word and tag word. The current
* (almost fninit'ed) fpu state is in the fpu and the exception
* state just saved will soon be junk. However, the implied fninit
* doesn't change the error pointers or register contents, and we
* preserved the control word and will copy the status and tag
* words, so the complete exception state can be recovered.
*/
curpcb->pcb_savefpu.sv_ex_sw = curpcb->pcb_savefpu.sv_env.en_sw;
curpcb->pcb_savefpu.sv_ex_tw = curpcb->pcb_savefpu.sv_env.en_tw;
/*
* Pass exception to process.
*/
if (ISPL(frame.if_cs) == SEL_UPL) {
/*
* Interrupt is essentially a trap, so we can afford to call
* the SIGFPE handler (if any) as soon as the interrupt
* returns.
*
* XXX little or nothing is gained from this, and plenty is
* lost - the interrupt frame has to contain the trap frame
* (this is otherwise only necessary for the rescheduling trap
* in doreti, and the frame for that could easily be set up
* just before it is used).
*/
curproc->p_regs = (int *)&frame.if_es;
curpcb->pcb_flags |= FM_TRAP; /* used by sendsig */
#ifdef notyet
/*
* Encode the appropriate code for detailed information on
* this exception.
*/
code = XXX_ENCODE(curpcb->pcb_savefpu.sv_ex_sw);
#else
code = 0; /* XXX */
#endif
trapsignal(curproc, SIGFPE, code);
curpcb->pcb_flags &= ~FM_TRAP;
} else {
/*
* Nested interrupt. These losers occur when:
* o an IRQ13 is bogusly generated at a bogus time, e.g.:
* o immediately after an fnsave or frstor of an
* error state.
* o a couple of 386 instructions after
* "fstpl _memvar" causes a stack overflow.
* These are especially nasty when combined with a
* trace trap.
* o an IRQ13 occurs at the same time as another higher-
* priority interrupt.
*
* Treat them like a true async interrupt.
*/
psignal(npxproc, SIGFPE);
}
}
/*
* Implement device not available (DNA) exception
*
* It would be better to switch FP context here (only). This would require
* saving the state in the proc table instead of in the pcb.
*/
int
npxdna()
{
if (!npx_exists)
return (0);
if (npxproc != NULL) {
printf("npxdna: npxproc = %lx, curproc = %lx\n",
(u_long) npxproc, (u_long) curproc);
panic("npxdna");
}
stop_emulating();
/*
* Record new context early in case frstor causes an IRQ13.
*/
npxproc = curproc;
/*
* The following frstor may cause an IRQ13 when the state being
* restored has a pending error. The error will appear to have been
* triggered by the current (npx) user instruction even when that
* instruction is a no-wait instruction that should not trigger an
* error (e.g., fnclex). On at least one 486 system all of the
* no-wait instructions are broken the same as frstor, so our
* treatment does not amplify the breakage. On at least one
* 386/Cyrix 387 system, fnclex works correctly while frstor and
* fnsave are broken, so our treatment breaks fnclex if it is the
* first FPU instruction after a context switch.
*/
frstor(&curpcb->pcb_savefpu);
return (1);
}
/*
* Wrapper for fnsave instruction to handle h/w bugs. If there is an error
* pending, then fnsave generates a bogus IRQ13 on some systems. Force
* any IRQ13 to be handled immediately, and then ignore it. This routine is
* often called at splhigh so it must not use many system services. In
* particular, it's much easier to install a special handler than to
* guarantee that it's safe to use npxintr() and its supporting code.
*/
void
npxsave(addr)
struct save87 *addr;
{
u_char icu1_mask;
u_char icu2_mask;
u_char old_icu1_mask;
u_char old_icu2_mask;
struct gate_descriptor save_idt_npxintr;
disable_intr();
old_icu1_mask = inb(IO_ICU1 + 1);
old_icu2_mask = inb(IO_ICU2 + 1);
save_idt_npxintr = idt[npx_intrno];
outb(IO_ICU1 + 1, old_icu1_mask & ~(IRQ_SLAVE | npx0mask));
outb(IO_ICU2 + 1, old_icu2_mask & ~(npx0mask >> 8));
idt[npx_intrno] = npx_idt_probeintr;
enable_intr();
stop_emulating();
fnsave(addr);
fwait();
start_emulating();
npxproc = NULL;
disable_intr();
icu1_mask = inb(IO_ICU1 + 1); /* masks may have changed */
icu2_mask = inb(IO_ICU2 + 1);
outb(IO_ICU1 + 1,
(icu1_mask & ~npx0mask) | (old_icu1_mask & npx0mask));
outb(IO_ICU2 + 1,
(icu2_mask & ~(npx0mask >> 8))
| (old_icu2_mask & (npx0mask >> 8)));
idt[npx_intrno] = save_idt_npxintr;
enable_intr(); /* back to usual state */
}
#endif /* NNPX > 0 */
+174
View File
@@ -0,0 +1,174 @@
/*-
* Copyright (c) 1982, 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)genassym.c 5.11 (Berkeley) 5/10/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 24 Apr 93 Bruce Evans/Dave Rivers Npx-0.5 support
*
*/
static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/genassym.c,v 1.2 92/01/21 14:22:02 william Exp $";
#ifndef lint
static char sccsid[] = "@(#)genassym.c 5.11 (Berkeley) 5/10/91";
#endif /* not lint */
#include "sys/param.h"
#include "sys/buf.h"
#include "sys/vmmeter.h"
#include "sys/proc.h"
#include "sys/user.h"
#include "sys/mbuf.h"
#include "sys/msgbuf.h"
#include "sys/resourcevar.h"
#include "machine/cpu.h"
#include "machine/trap.h"
#include "machine/psl.h"
#include "machine/reg.h"
#include "sys/syscall.h"
#include "vm/vm_param.h"
#include "vm/vm_map.h"
#include "machine/pmap.h"
main()
{
struct proc *p = (struct proc *)0;
struct vmmeter *vm = (struct vmmeter *)0;
struct user *up = (struct user *)0;
struct rusage *rup = (struct rusage *)0;
struct uprof *uprof = (struct uprof *)0;
struct vmspace *vms = (struct vmspace *)0;
vm_map_t map = (vm_map_t)0;
pmap_t pmap = (pmap_t)0;
struct pcb *pcb = (struct pcb *)0;
register unsigned i;
printf("#define\tI386_CR3PAT %d\n", I386_CR3PAT);
printf("#define\tUDOT_SZ %d\n", sizeof(struct user));
printf("#define\tP_LINK %d\n", &p->p_link);
printf("#define\tP_RLINK %d\n", &p->p_rlink);
printf("#define\tP_VMSPACE %d\n", &p->p_vmspace);
printf("#define\tVM_PMAP %d\n", &vms->vm_pmap);
printf("#define\tP_ADDR %d\n", &p->p_addr);
printf("#define\tP_PRI %d\n", &p->p_pri);
printf("#define\tP_STAT %d\n", &p->p_stat);
printf("#define\tP_WCHAN %d\n", &p->p_wchan);
printf("#define\tP_FLAG %d\n", &p->p_flag);
printf("#define\tP_PID %d\n", &p->p_pid);
printf("#define\tSSLEEP %d\n", SSLEEP);
printf("#define\tSRUN %d\n", SRUN);
printf("#define\tV_SWTCH %d\n", &vm->v_swtch);
printf("#define\tV_TRAP %d\n", &vm->v_trap);
printf("#define\tV_SYSCALL %d\n", &vm->v_syscall);
printf("#define\tV_INTR %d\n", &vm->v_intr);
printf("#define\tV_SOFT %d\n", &vm->v_soft);
printf("#define\tV_PDMA %d\n", &vm->v_pdma);
printf("#define\tV_FAULTS %d\n", &vm->v_faults);
printf("#define\tV_PGREC %d\n", &vm->v_pgrec);
printf("#define\tV_FASTPGREC %d\n", &vm->v_fastpgrec);
printf("#define\tUPAGES %d\n", UPAGES);
printf("#define\tHIGHPAGES %d\n", HIGHPAGES);
printf("#define\tCLSIZE %d\n", CLSIZE);
printf("#define\tNBPG %d\n", NBPG);
printf("#define\tNPTEPG %d\n", NPTEPG);
printf("#define\tPGSHIFT %d\n", PGSHIFT);
printf("#define\tSYSPTSIZE %d\n", SYSPTSIZE);
printf("#define\tUSRPTSIZE %d\n", USRPTSIZE);
printf("#define\tUSRIOSIZE %d\n", USRIOSIZE);
#ifdef SYSVSHM
printf("#define\tSHMMAXPGS %d\n", SHMMAXPGS);
#endif
printf("#define\tUSRSTACK %d\n", USRSTACK);
printf("#define\tMSGBUFPTECNT %d\n", btoc(sizeof (struct msgbuf)));
printf("#define\tNMBCLUSTERS %d\n", NMBCLUSTERS);
printf("#define\tMCLBYTES %d\n", MCLBYTES);
printf("#define\tPCB_LINK %d\n", &pcb->pcb_tss.tss_link);
printf("#define\tPCB_ESP0 %d\n", &pcb->pcb_tss.tss_esp0);
printf("#define\tPCB_SS0 %d\n", &pcb->pcb_tss.tss_ss0);
printf("#define\tPCB_ESP1 %d\n", &pcb->pcb_tss.tss_esp1);
printf("#define\tPCB_SS1 %d\n", &pcb->pcb_tss.tss_ss1);
printf("#define\tPCB_ESP2 %d\n", &pcb->pcb_tss.tss_esp2);
printf("#define\tPCB_SS2 %d\n", &pcb->pcb_tss.tss_ss2);
printf("#define\tPCB_CR3 %d\n", &pcb->pcb_tss.tss_cr3);
printf("#define\tPCB_EIP %d\n", &pcb->pcb_tss.tss_eip);
printf("#define\tPCB_EFLAGS %d\n", &pcb->pcb_tss.tss_eflags);
printf("#define\tPCB_EAX %d\n", &pcb->pcb_tss.tss_eax);
printf("#define\tPCB_ECX %d\n", &pcb->pcb_tss.tss_ecx);
printf("#define\tPCB_EDX %d\n", &pcb->pcb_tss.tss_edx);
printf("#define\tPCB_EBX %d\n", &pcb->pcb_tss.tss_ebx);
printf("#define\tPCB_ESP %d\n", &pcb->pcb_tss.tss_esp);
printf("#define\tPCB_EBP %d\n", &pcb->pcb_tss.tss_ebp);
printf("#define\tPCB_ESI %d\n", &pcb->pcb_tss.tss_esi);
printf("#define\tPCB_EDI %d\n", &pcb->pcb_tss.tss_edi);
printf("#define\tPCB_ES %d\n", &pcb->pcb_tss.tss_es);
printf("#define\tPCB_CS %d\n", &pcb->pcb_tss.tss_cs);
printf("#define\tPCB_SS %d\n", &pcb->pcb_tss.tss_ss);
printf("#define\tPCB_DS %d\n", &pcb->pcb_tss.tss_ds);
printf("#define\tPCB_FS %d\n", &pcb->pcb_tss.tss_fs);
printf("#define\tPCB_GS %d\n", &pcb->pcb_tss.tss_gs);
printf("#define\tPCB_LDT %d\n", &pcb->pcb_tss.tss_ldt);
printf("#define\tPCB_IOOPT %d\n", &pcb->pcb_tss.tss_ioopt);
printf("#define\tNKMEMCLUSTERS %d\n", NKMEMCLUSTERS);
printf("#define\tU_PROF %d\n", &up->u_stats.p_prof);
printf("#define\tU_PROFSCALE %d\n", &up->u_stats.p_prof.pr_scale);
printf("#define\tPR_BASE %d\n", &uprof->pr_base);
printf("#define\tPR_SIZE %d\n", &uprof->pr_size);
printf("#define\tPR_OFF %d\n", &uprof->pr_off);
printf("#define\tPR_SCALE %d\n", &uprof->pr_scale);
printf("#define\tRU_MINFLT %d\n", &rup->ru_minflt);
printf("#define\tPCB_FLAGS %d\n", &pcb->pcb_flags);
printf("#define\tPCB_SAVEFPU %d\n", &pcb->pcb_savefpu);
#ifdef notused
printf("#define\tFP_WASUSED %d\n", FP_WASUSED);
printf("#define\tFP_NEEDSSAVE %d\n", FP_NEEDSSAVE);
printf("#define\tFP_NEEDSRESTORE %d\n", FP_NEEDSRESTORE);
#endif
printf("#define\tFP_USESEMC %d\n", FP_USESEMC);
printf("#define\tPCB_SAVEEMC %d\n", &pcb->pcb_saveemc);
printf("#define\tPCB_CMAP2 %d\n", &pcb->pcb_cmap2);
printf("#define\tPCB_SIGC %d\n", pcb->pcb_sigc);
printf("#define\tPCB_IML %d\n", &pcb->pcb_iml);
printf("#define\tPCB_ONFAULT %d\n", &pcb->pcb_onfault);
printf("#define\tB_READ %d\n", B_READ);
printf("#define\tENOENT %d\n", ENOENT);
printf("#define\tEFAULT %d\n", EFAULT);
printf("#define\tENAMETOOLONG %d\n", ENAMETOOLONG);
exit(0);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+191
View File
@@ -0,0 +1,191 @@
/*-
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* Science Department, and code derived from software contributed to
* Berkeley by William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: Utah $Hdr: mem.c 1.13 89/10/08$
* @(#)mem.c 7.2 (Berkeley) 5/9/91
*/
/*
* Memory special file
*/
#include "param.h"
#include "conf.h"
#include "buf.h"
#include "systm.h"
#include "uio.h"
#include "malloc.h"
#include "machine/cpu.h"
#include "vm/vm_param.h"
#include "vm/lock.h"
#include "vm/vm_statistics.h"
#include "vm/pmap.h"
#include "vm/vm_prot.h"
extern char *vmmap; /* poor name! */
/*ARGSUSED*/
mmrw(dev, uio, flags)
dev_t dev;
struct uio *uio;
int flags;
{
register int o;
register u_int c, v;
register struct iovec *iov;
int error = 0;
caddr_t zbuf = NULL;
while (uio->uio_resid > 0 && error == 0) {
iov = uio->uio_iov;
if (iov->iov_len == 0) {
uio->uio_iov++;
uio->uio_iovcnt--;
if (uio->uio_iovcnt < 0)
panic("mmrw");
continue;
}
switch (minor(dev)) {
/* minor device 0 is physical memory */
case 0:
v = uio->uio_offset;
pmap_enter(pmap_kernel(), vmmap, v,
uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE,
TRUE);
o = (int)uio->uio_offset & PGOFSET;
c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET));
c = MIN(c, (u_int)(NBPG - o));
c = MIN(c, (u_int)iov->iov_len);
error = uiomove((caddr_t)&vmmap[o], (int)c, uio);
pmap_remove(pmap_kernel(), vmmap, &vmmap[NBPG]);
continue;
/* minor device 1 is kernel memory */
case 1:
c = iov->iov_len;
if (!kernacc((caddr_t)uio->uio_offset, c,
uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
return(EFAULT);
error = uiomove((caddr_t)uio->uio_offset, (int)c, uio);
continue;
/* minor device 2 is EOF/RATHOLE */
case 2:
if (uio->uio_rw == UIO_READ)
return (0);
c = iov->iov_len;
break;
/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
case 12:
if (uio->uio_rw == UIO_WRITE) {
c = iov->iov_len;
break;
}
if (zbuf == NULL) {
zbuf = (caddr_t)
malloc(CLBYTES, M_TEMP, M_WAITOK);
bzero(zbuf, CLBYTES);
}
c = MIN(iov->iov_len, CLBYTES);
error = uiomove(zbuf, (int)c, uio);
continue;
#ifdef notyet
/* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate
i/o device address bus, different than memory bus. Semantics here are
very different than ordinary read/write, as if iov_len is a multiple
an implied string move from a single port will be done. Note that lseek
must be used to set the port number reliably. */
case 14:
if (iov->iov_len == 1) {
u_char tmp;
tmp = inb(uio->uio_offset);
error = uiomove (&tmp, iov->iov_len, uio);
} else {
if (!useracc((caddr_t)iov->iov_base,
iov->iov_len, uio->uio_rw))
return (EFAULT);
insb(uio->uio_offset, iov->iov_base,
iov->iov_len);
}
break;
case 15:
if (iov->iov_len == sizeof (short)) {
u_short tmp;
tmp = inw(uio->uio_offset);
error = uiomove (&tmp, iov->iov_len, uio);
} else {
if (!useracc((caddr_t)iov->iov_base,
iov->iov_len, uio->uio_rw))
return (EFAULT);
insw(uio->uio_offset, iov->iov_base,
iov->iov_len/ sizeof (short));
}
break;
case 16:
if (iov->iov_len == sizeof (long)) {
u_long tmp;
tmp = inl(uio->uio_offset);
error = uiomove (&tmp, iov->iov_len, uio);
} else {
if (!useracc((caddr_t)iov->iov_base,
iov->iov_len, uio->uio_rw))
return (EFAULT);
insl(uio->uio_offset, iov->iov_base,
iov->iov_len/ sizeof (long));
}
break;
#endif
default:
return (ENXIO);
}
if (error)
break;
iov->iov_base += c;
iov->iov_len -= c;
uio->uio_offset += c;
uio->uio_resid -= c;
}
if (zbuf)
free(zbuf, M_TEMP);
return (error);
}
File diff suppressed because it is too large Load Diff
+105
View File
@@ -0,0 +1,105 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91
*/
#include "param.h"
#include "systm.h"
#include "ioctl.h"
#include "file.h"
#include "time.h"
#include "proc.h"
#include "uio.h"
#include "kernel.h"
#include "mtio.h"
#include "buf.h"
#include "trace.h"
#ifdef TRACE
int nvualarm;
vtrace(p, uap, retval)
struct proc *p;
register struct args {
int request;
int value;
} *uap;
int *retval;
{
int vdoualarm();
switch (uap->request) {
case VTR_DISABLE: /* disable a trace point */
case VTR_ENABLE: /* enable a trace point */
if (uap->value < 0 || uap->value >= TR_NFLAGS)
return (EINVAL);
*retval = traceflags[uap->value];
traceflags[uap->value] = uap->request;
break;
case VTR_VALUE: /* return a trace point setting */
if (uap->value < 0 || uap->value >= TR_NFLAGS)
return (EINVAL);
*retval = traceflags[uap->value];
break;
case VTR_UALARM: /* set a real-time ualarm, less than 1 min */
if (uap->value <= 0 || uap->value > 60 * hz || nvualarm > 5)
return (EINVAL);
nvualarm++;
timeout(vdoualarm, (caddr_t)p->p_pid, uap->value);
break;
case VTR_STAMP:
trace(TR_STAMP, uap->value, p->p_pid);
break;
}
return (0);
}
vdoualarm(arg)
int arg;
{
register struct proc *p;
p = pfind(arg);
if (p)
psignal(p, 16);
nvualarm--;
}
#endif
+547
View File
@@ -0,0 +1,547 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the University of Utah, and William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)trap.c 7.4 (Berkeley) 5/13/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00137
* -------------------- ----- ----------------------
*
* 08 Apr 93 Bruce Evans Several VM system fixes
* Paul Kranenburg Add counter for vmstat
*/
static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/trap.c,v 1.2 92/01/21 14:22:13 william Exp $";
/*
* 386 Trap and System call handleing
*/
#include "machine/cpu.h"
#include "machine/psl.h"
#include "machine/reg.h"
#include "param.h"
#include "systm.h"
#include "proc.h"
#include "user.h"
#include "acct.h"
#include "kernel.h"
#ifdef KTRACE
#include "ktrace.h"
#endif
#include "vm/vm_param.h"
#include "vm/pmap.h"
#include "vm/vm_map.h"
#include "sys/vmmeter.h"
#include "machine/trap.h"
struct sysent sysent[];
int nsysent;
int dostacklimits;
unsigned rcr2();
extern short cpl;
/*
* trap(frame):
* Exception, fault, and trap interface to BSD kernel. This
* common code is called from assembly language IDT gate entry
* routines that prepare a suitable stack frame, and restore this
* frame after the exception has been processed. Note that the
* effect is as if the arguments were passed call by reference.
*/
/*ARGSUSED*/
trap(frame)
struct trapframe frame;
{
register int i;
register struct proc *p = curproc;
struct timeval syst;
int ucode, type, code, eva;
frame.tf_eflags &= ~PSL_NT; /* clear nested trap XXX */
type = frame.tf_trapno;
#include "ddb.h"
#if NDDB > 0
if (curpcb && curpcb->pcb_onfault) {
if (frame.tf_trapno == T_BPTFLT
|| frame.tf_trapno == T_TRCTRAP)
if (kdb_trap (type, 0, &frame))
return;
}
#endif
/*pg("trap type %d code = %x eip = %x cs = %x eva = %x esp %x",
frame.tf_trapno, frame.tf_err, frame.tf_eip,
frame.tf_cs, rcr2(), frame.tf_esp);*/
if(curpcb == 0 || curproc == 0) goto we_re_toast;
if (curpcb->pcb_onfault && frame.tf_trapno != 0xc) {
copyfault:
frame.tf_eip = (int)curpcb->pcb_onfault;
return;
}
syst = p->p_stime;
if (ISPL(frame.tf_cs) == SEL_UPL) {
type |= T_USER;
p->p_regs = (int *)&frame;
curpcb->pcb_flags |= FM_TRAP; /* used by sendsig */
}
ucode=0;
eva = rcr2();
code = frame.tf_err;
switch (type) {
default:
we_re_toast:
#ifdef KDB
if (kdb_trap(&psl))
return;
#endif
#if NDDB > 0
if (kdb_trap (type, 0, &frame))
return;
#endif
printf("trap type %d code = %x eip = %x cs = %x eflags = %x ",
frame.tf_trapno, frame.tf_err, frame.tf_eip,
frame.tf_cs, frame.tf_eflags);
eva = rcr2();
printf("cr2 %x cpl %x\n", eva, cpl);
/* type &= ~T_USER; */ /* XXX what the hell is this */
panic("trap");
/*NOTREACHED*/
case T_SEGNPFLT|T_USER:
case T_STKFLT|T_USER:
case T_PROTFLT|T_USER: /* protection fault */
ucode = code + BUS_SEGM_FAULT ;
i = SIGBUS;
break;
case T_PRIVINFLT|T_USER: /* privileged instruction fault */
case T_RESADFLT|T_USER: /* reserved addressing fault */
case T_RESOPFLT|T_USER: /* reserved operand fault */
case T_FPOPFLT|T_USER: /* coprocessor operand fault */
ucode = type &~ T_USER;
i = SIGILL;
break;
case T_ASTFLT|T_USER: /* Allow process switch */
astoff();
cnt.v_soft++;
if ((p->p_flag & SOWEUPC) && p->p_stats->p_prof.pr_scale) {
addupc(frame.tf_eip, &p->p_stats->p_prof, 1);
p->p_flag &= ~SOWEUPC;
}
goto out;
case T_DNA|T_USER:
#ifdef NPX
/* if a transparent fault (due to context switch "late") */
if (npxdna()) return;
#endif
i = math_emulate(&frame);
if (i == 0) return;
ucode = FPE_FPU_NP_TRAP;
break;
case T_BOUND|T_USER:
ucode = FPE_SUBRNG_TRAP;
i = SIGFPE;
break;
case T_OFLOW|T_USER:
ucode = FPE_INTOVF_TRAP;
i = SIGFPE;
break;
case T_DIVIDE|T_USER:
ucode = FPE_INTDIV_TRAP;
i = SIGFPE;
break;
case T_ARITHTRAP|T_USER:
ucode = code;
i = SIGFPE;
break;
case T_PAGEFLT: /* allow page faults in kernel mode */
#if 0
/* XXX - check only applies to 386's and 486's with WP off */
if (code & PGEX_P) goto we_re_toast;
#endif
/* fall into */
case T_PAGEFLT|T_USER: /* page fault */
{
register vm_offset_t va;
register struct vmspace *vm = p->p_vmspace;
register vm_map_t map;
int rv;
vm_prot_t ftype;
extern vm_map_t kernel_map;
unsigned nss,v;
va = trunc_page((vm_offset_t)eva);
/*
* Avoid even looking at pde_v(va) for high va's. va's
* above VM_MAX_KERNEL_ADDRESS don't correspond to normal
* PDE's (half of them correspond to APDEpde and half to
* an unmapped kernel PDE). va's betweeen 0xFEC00000 and
* VM_MAX_KERNEL_ADDRESS correspond to unmapped kernel PDE's
* (XXX - why are only 3 initialized when 6 are required to
* reach VM_MAX_KERNEL_ADDRESS?). Faulting in an unmapped
* kernel page table would give inconsistent PTD's.
*
* XXX - faulting in unmapped page tables wastes a page if
* va turns out to be invalid.
*
* XXX - should "kernel address space" cover the kernel page
* tables? Might have same problem with PDEpde as with
* APDEpde (or there may be no problem with APDEpde).
*/
if (va > 0xFEBFF000) {
rv = KERN_FAILURE; /* becomes SIGBUS */
goto nogo;
}
/*
* It is only a kernel address space fault iff:
* 1. (type & T_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
if (type == T_PAGEFLT && va >= KERNBASE)
map = kernel_map;
else
map = &vm->vm_map;
if (code & PGEX_W)
ftype = VM_PROT_READ | VM_PROT_WRITE;
else
ftype = VM_PROT_READ;
#ifdef DEBUG
if (map == kernel_map && va == 0) {
printf("trap: bad kernel access at %x\n", va);
goto we_re_toast;
}
#endif
/*
* XXX: rude hack to make stack limits "work"
*/
nss = 0;
if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map
&& dostacklimits) {
nss = clrnd(btoc((unsigned)vm->vm_maxsaddr
+ MAXSSIZ - (unsigned)va));
if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
/*pg("trap rlimit %d, maxsaddr %x va %x ", nss, vm->vm_maxsaddr, va);*/
rv = KERN_FAILURE;
goto nogo;
}
}
/* check if page table is mapped, if not, fault it first */
#define pde_v(v) (PTD[((v)>>PD_SHIFT)&1023].pd_v)
if (!pde_v(va)) {
v = trunc_page(vtopte(va));
rv = vm_fault(map, v, ftype, FALSE);
if (rv != KERN_SUCCESS) goto nogo;
/* check if page table fault, increment wiring */
vm_map_pageable(map, v, round_page(v+1), FALSE);
} else v=0;
rv = vm_fault(map, va, ftype, FALSE);
if (rv == KERN_SUCCESS) {
/*
* XXX: continuation of rude stack hack
*/
if (nss > vm->vm_ssize)
vm->vm_ssize = nss;
va = trunc_page(vtopte(va));
/* for page table, increment wiring
as long as not a page table fault as well */
if (!v && type != T_PAGEFLT)
vm_map_pageable(map, va, round_page(va+1), FALSE);
if (type == T_PAGEFLT)
return;
goto out;
}
nogo:
if (type == T_PAGEFLT) {
if (curpcb->pcb_onfault)
goto copyfault;
printf("vm_fault(%x, %x, %x, 0) -> %x\n",
map, va, ftype, rv);
printf(" type %x, code %x\n",
type, code);
goto we_re_toast;
}
i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
break;
}
#if NDDB == 0
case T_TRCTRAP: /* trace trap -- someone single stepping lcall's */
frame.tf_eflags &= ~PSL_T;
/* Q: how do we turn it on again? */
return;
#endif
case T_BPTFLT|T_USER: /* bpt instruction fault */
case T_TRCTRAP|T_USER: /* trace trap */
frame.tf_eflags &= ~PSL_T;
i = SIGTRAP;
break;
#include "isa.h"
#if NISA > 0
case T_NMI:
case T_NMI|T_USER:
#if NDDB > 0
/* NMI can be hooked up to a pushbutton for debugging */
printf ("NMI ... going to debugger\n");
if (kdb_trap (type, 0, &frame))
return;
#endif
/* machine/parity/power fail/"kitchen sink" faults */
if(isa_nmi(code) == 0) return;
else goto we_re_toast;
#endif
}
trapsignal(p, i, ucode);
if ((type & T_USER) == 0)
return;
out:
while (i = CURSIG(p))
psig(i);
p->p_pri = p->p_usrpri;
if (want_resched) {
/*
* Since we are curproc, clock will normally just change
* our priority without moving us from one queue to another
* (since the running process is not on a queue.)
* If that happened after we setrq ourselves but before we
* swtch()'ed, we might not be on the queue indicated by
* our priority.
*/
(void) splclock();
setrq(p);
p->p_stats->p_ru.ru_nivcsw++;
swtch();
(void) splnone();
while (i = CURSIG(p))
psig(i);
}
if (p->p_stats->p_prof.pr_scale) {
int ticks;
struct timeval *tv = &p->p_stime;
ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
if (ticks) {
#ifdef PROFTIMER
extern int profscale;
addupc(frame.tf_eip, &p->p_stats->p_prof,
ticks * profscale);
#else
addupc(frame.tf_eip, &p->p_stats->p_prof, ticks);
#endif
}
}
curpri = p->p_pri;
curpcb->pcb_flags &= ~FM_TRAP; /* used by sendsig */
}
/*
* Compensate for 386 brain damage (missing URKR)
*/
int trapwrite(unsigned addr) {
int rv;
vm_offset_t va;
va = trunc_page((vm_offset_t)addr);
if (va > VM_MAXUSER_ADDRESS) return(1);
rv = vm_fault(&curproc->p_vmspace->vm_map, va,
VM_PROT_READ | VM_PROT_WRITE, FALSE);
if (rv == KERN_SUCCESS) return(0);
else return(1);
}
/*
* syscall(frame):
* System call request from POSIX system call gate interface to kernel.
* Like trap(), argument is call by reference.
*/
/*ARGSUSED*/
syscall(frame)
volatile struct syscframe frame;
{
register int *locr0 = ((int *)&frame);
register caddr_t params;
register int i;
register struct sysent *callp;
register struct proc *p = curproc;
struct timeval syst;
int error, opc;
int args[8], rval[2];
int code;
#ifdef lint
r0 = 0; r0 = r0; r1 = 0; r1 = r1;
#endif
syst = p->p_stime;
if (ISPL(frame.sf_cs) != SEL_UPL)
panic("syscall");
code = frame.sf_eax;
curpcb->pcb_flags &= ~FM_TRAP; /* used by sendsig */
p->p_regs = (int *)&frame;
params = (caddr_t)frame.sf_esp + sizeof (int) ;
/*
* Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always.
*/
opc = frame.sf_eip - 7;
callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
if (callp == sysent) {
i = fuword(params);
params += sizeof (int);
callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
}
if ((i = callp->sy_narg * sizeof (int)) &&
(error = copyin(params, (caddr_t)args, (u_int)i))) {
frame.sf_eax = error;
frame.sf_eflags |= PSL_C; /* carry bit */
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
#endif
goto done;
}
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p->p_tracep, code, callp->sy_narg, &args);
#endif
rval[0] = 0;
rval[1] = frame.sf_edx;
/*pg("%d. s %d\n", p->p_pid, code);*/
error = (*callp->sy_call)(p, args, rval);
if (error == ERESTART)
frame.sf_eip = opc;
else if (error != EJUSTRETURN) {
if (error) {
/*pg("error %d", error);*/
frame.sf_eax = error;
frame.sf_eflags |= PSL_C; /* carry bit */
} else {
frame.sf_eax = rval[0];
frame.sf_edx = rval[1];
frame.sf_eflags &= ~PSL_C; /* carry bit */
}
}
/* else if (error == EJUSTRETURN) */
/* nothing to do */
done:
/*
* Reinitialize proc pointer `p' as it may be different
* if this is a child returning from fork syscall.
*/
p = curproc;
while (i = CURSIG(p))
psig(i);
p->p_pri = p->p_usrpri;
if (want_resched) {
/*
* Since we are curproc, clock will normally just change
* our priority without moving us from one queue to another
* (since the running process is not on a queue.)
* If that happened after we setrq ourselves but before we
* swtch()'ed, we might not be on the queue indicated by
* our priority.
*/
(void) splclock();
setrq(p);
p->p_stats->p_ru.ru_nivcsw++;
swtch();
(void) splnone();
while (i = CURSIG(p))
psig(i);
}
if (p->p_stats->p_prof.pr_scale) {
int ticks;
struct timeval *tv = &p->p_stime;
ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
if (ticks) {
#ifdef PROFTIMER
extern int profscale;
addupc(frame.sf_eip, &p->p_stats->p_prof,
ticks * profscale);
#else
addupc(frame.sf_eip, &p->p_stats->p_prof, ticks);
#endif
}
}
curpri = p->p_pri;
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSRET))
ktrsysret(p->p_tracep, code, error, rval[0]);
#endif
#ifdef DIAGNOSTICx
{ extern int _udatasel, _ucodesel;
if (frame.sf_ss != _udatasel)
printf("ss %x call %d\n", frame.sf_ss, code);
if ((frame.sf_cs&0xffff) != _ucodesel)
printf("cs %x call %d\n", frame.sf_cs, code);
if (frame.sf_eip > VM_MAXUSER_ADDRESS) {
printf("eip %x call %d\n", frame.sf_eip, code);
frame.sf_eip = 0;
}
}
#endif
}
+271
View File
@@ -0,0 +1,271 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz and Don Ahn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)clock.c 7.2 (Berkeley) 5/12/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 5 00158
* -------------------- ----- ----------------------
*
* 14 Aug 92 Arne Henrik Juul Added code in the kernel to
* allow for DST in the BIOS.
* 17 Jan 93 Bruce Evans Fixed leap year and second
* calculations
* 01 Feb 93 Julian Elischer Added code to for the cpu
* speed independent spinwait()
* function, (used by scsi and others)
* 25 Mar 93 Sean Eric Fagan Add microtimer support using timer 1
* 08 Apr 93 Poul-Henning Kamp/P-HK Fixes, and support for dcfclock
* 26 Apr 93 Bruce Evans Eliminate findspeed, new spinwait
* 26 Apr 93 Rodney W. Grimes I merged in Bruce changes and hope I
* still kept the other fixes... Had to
* add back in findcpuspeed that Bruce
* had removed.
*/
/*
* Primitive clock interrupt routines.
*/
#include "param.h"
#include "systm.h"
#include "time.h"
#include "kernel.h"
#include "machine/segments.h"
#include "i386/isa/icu.h"
#include "i386/isa/isa.h"
#include "i386/isa/rtc.h"
#include "i386/isa/timerreg.h"
#define DAYST 119
#define DAYEN 303
/* X-tals being what they are, it's nice to be able to fudge this one... */
/* Note, the name changed here from XTALSPEED to TIMER_FREQ rgrimes 4/26/93 */
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */
#endif
startrtclock() {
int s;
findcpuspeed(); /* use the clock (while it's free)
to find the cpu speed */
/* initialize 8253 clock */
outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
/* Correct rounding will buy us a better precision in timekeeping */
outb (IO_TIMER1, (TIMER_FREQ+hz/2)/hz);
outb (IO_TIMER1, ((TIMER_FREQ+hz/2)/hz)/256);
/* initialize brain-dead battery powered clock */
outb (IO_RTC, RTC_STATUSA);
outb (IO_RTC+1, 0x26);
outb (IO_RTC, RTC_STATUSB);
outb (IO_RTC+1, 2);
outb (IO_RTC, RTC_DIAG);
if (s = inb (IO_RTC+1))
printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS);
outb (IO_RTC, RTC_DIAG);
outb (IO_RTC+1, 0);
}
unsigned int delaycount; /* calibrated loop variable (1 millisecond) */
#define FIRST_GUESS 0x2000
findcpuspeed()
{
unsigned char low;
unsigned int remainder;
/* Put counter in count down mode */
outb(IO_TIMER1+3, 0x34);
outb(IO_TIMER1, 0xff);
outb(IO_TIMER1, 0xff);
delaycount = FIRST_GUESS;
spinwait(1);
/* Read the value left in the counter */
low = inb(IO_TIMER1); /* least siginifcant */
remainder = inb(IO_TIMER1); /* most significant */
remainder = (remainder<<8) + low ;
/* Formula for delaycount is :
* (loopcount * timer clock speed)/ (counter ticks * 1000)
*/
delaycount = (FIRST_GUESS * (TIMER_FREQ/1000)) / (0xffff-remainder);
}
/* convert 2 digit BCD number */
bcd(i)
int i;
{
return ((i/16)*10 + (i%16));
}
/* convert years to seconds (from 1970) */
unsigned long
ytos(y)
int y;
{
int i;
unsigned long ret;
ret = 0;
for(i = 1970; i < y; i++) {
if (i % 4) ret += 365*24*60*60;
else ret += 366*24*60*60;
}
return ret;
}
/* convert months to seconds */
unsigned long
mtos(m,leap)
int m,leap;
{
int i;
unsigned long ret;
ret = 0;
for(i=1;i<m;i++) {
switch(i){
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
ret += 31*24*60*60; break;
case 4: case 6: case 9: case 11:
ret += 30*24*60*60; break;
case 2:
if (leap) ret += 29*24*60*60;
else ret += 28*24*60*60;
}
}
return ret;
}
/*
* Initialize the time of day register, based on the time base which is, e.g.
* from a filesystem.
*/
inittodr(base)
time_t base;
{
unsigned long sec;
int leap,day_week,t,yd;
int sa,s;
/* do we have a realtime clock present? (otherwise we loop below) */
sa = rtcin(RTC_STATUSA);
if (sa == 0xff || sa == 0) return;
/* ready for a read? */
while ((sa&RTCSA_TUP) == RTCSA_TUP)
sa = rtcin(RTC_STATUSA);
sec = bcd(rtcin(RTC_YEAR)) + 1900;
if (sec < 1970)
sec += 100;
leap = !(sec % 4); sec = ytos(sec); /* year */
yd = mtos(bcd(rtcin(RTC_MONTH)),leap); sec += yd; /* month */
t = (bcd(rtcin(RTC_DAY))-1) * 24*60*60; sec += t; yd += t; /* date */
day_week = rtcin(RTC_WDAY); /* day */
sec += bcd(rtcin(RTC_HRS)) * 60*60; /* hour */
sec += bcd(rtcin(RTC_MIN)) * 60; /* minutes */
sec += bcd(rtcin(RTC_SEC)); /* seconds */
/* XXX off by one? Need to calculate DST on SUNDAY */
/* Perhaps we should have the RTC hold GMT time to save */
/* us the bother of converting. */
yd = yd / (24*60*60);
if ((yd >= DAYST) && ( yd <= DAYEN)) {
sec -= 60*60;
}
sec += tz.tz_minuteswest * 60;
time.tv_sec = sec;
}
#ifdef garbage
/*
* Initialze the time of day register, based on the time base which is, e.g.
* from a filesystem.
*/
test_inittodr(base)
time_t base;
{
outb(IO_RTC,9); /* year */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,8); /* month */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,7); /* day */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,4); /* hour */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,2); /* minutes */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,0); /* seconds */
printf("%d\n",bcd(inb(IO_RTC+1)));
time.tv_sec = base;
}
#endif
/*
* Restart the clock.
*/
resettodr()
{
}
/*
* Wire clock interrupt in.
*/
#define V(s) __CONCAT(V, s)
extern V(clk)();
enablertclock() {
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
INTREN(IRQ0);
}
/*
* Delay for some number of milliseconds.
*/
void
spinwait(millisecs)
int millisecs;
{
DELAY(1000 * millisecs);
}
+410
View File
@@ -0,0 +1,410 @@
/*-
* Copyright (c) 1982, 1986 The Regents of the University of California.
* Copyright (c) 1989, 1990 William Jolitz
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* Science Department, and William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 20 Apr 93 Bruce Evans New npx-0.5 code
*
*/
/*
* Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
*/
static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/vm_machdep.c,v 1.2 92/01/21 14:22:17 william Exp $";
#include "param.h"
#include "systm.h"
#include "proc.h"
#include "malloc.h"
#include "buf.h"
#include "user.h"
#include "../include/cpu.h"
#include "vm/vm.h"
#include "vm/vm_kern.h"
/*
* Finish a fork operation, with process p2 nearly set up.
* Copy and update the kernel stack and pcb, making the child
* ready to run, and marking it so that it can return differently
* than the parent. Returns 1 in the child process, 0 in the parent.
* We currently double-map the user area so that the stack is at the same
* address in each process; in the future we will probably relocate
* the frame pointers on the stack after copying.
*/
cpu_fork(p1, p2)
register struct proc *p1, *p2;
{
register struct user *up = p2->p_addr;
int foo, offset, addr, i;
extern char kstack[];
extern int mvesp();
/*
* Copy pcb and stack from proc p1 to p2.
* We do this as cheaply as possible, copying only the active
* part of the stack. The stack and pcb need to agree;
* this is tricky, as the final pcb is constructed by savectx,
* but its frame isn't yet on the stack when the stack is copied.
* swtch compensates for this when the child eventually runs.
* This should be done differently, with a single call
* that copies and updates the pcb+stack,
* replacing the bcopy and savectx.
*/
p2->p_addr->u_pcb = p1->p_addr->u_pcb;
offset = mvesp() - (int)kstack;
bcopy((caddr_t)kstack + offset, (caddr_t)p2->p_addr + offset,
(unsigned) ctob(UPAGES) - offset);
p2->p_regs = p1->p_regs;
/*
* Wire top of address space of child to it's kstack.
* First, fault in a page of pte's to map it.
*/
addr = trunc_page((u_int)vtopte(kstack));
vm_map_pageable(&p2->p_vmspace->vm_map, addr, addr+NBPG, FALSE);
for (i=0; i < UPAGES; i++)
pmap_enter(&p2->p_vmspace->vm_pmap, kstack+i*NBPG,
pmap_extract(kernel_pmap, ((int)p2->p_addr)+i*NBPG), VM_PROT_READ, 1);
pmap_activate(&p2->p_vmspace->vm_pmap, &up->u_pcb);
/*
*
* Arrange for a non-local goto when the new process
* is started, to resume here, returning nonzero from setjmp.
*/
if (savectx(up, 1)) {
/*
* Return 1 in child.
*/
return (1);
}
return (0);
}
#ifdef notyet
/*
* cpu_exit is called as the last action during exit.
*
* We change to an inactive address space and a "safe" stack,
* passing thru an argument to the new stack. Now, safely isolated
* from the resources we're shedding, we release the address space
* and any remaining machine-dependent resources, including the
* memory for the user structure and kernel stack.
*
* Next, we assign a dummy context to be written over by swtch,
* calling it to send this process off to oblivion.
* [The nullpcb allows us to minimize cost in swtch() by not having
* a special case].
*/
struct proc *swtch_to_inactive();
cpu_exit(p)
register struct proc *p;
{
static struct pcb nullpcb; /* pcb to overwrite on last swtch */
#ifdef NPX
npxexit(p);
#endif
/* move to inactive space and stack, passing arg accross */
p = swtch_to_inactive(p);
/* drop per-process resources */
vmspace_free(p->p_vmspace);
kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
p->p_addr = (struct user *) &nullpcb;
splclock();
swtch();
/* NOTREACHED */
}
#else
cpu_exit(p)
register struct proc *p;
{
#ifdef NPX
npxexit(p);
#endif
splclock();
swtch();
}
cpu_wait(p) struct proc *p; {
/* drop per-process resources */
vmspace_free(p->p_vmspace);
kmem_free(kernel_map, (vm_offset_t)p->p_addr, ctob(UPAGES));
}
#endif
/*
* Set a red zone in the kernel stack after the u. area.
*/
setredzone(pte, vaddr)
u_short *pte;
caddr_t vaddr;
{
/* eventually do this by setting up an expand-down stack segment
for ss0: selector, allowing stack access down to top of u.
this means though that protection violations need to be handled
thru a double fault exception that must do an integral task
switch to a known good context, within which a dump can be
taken. a sensible scheme might be to save the initial context
used by sched (that has physical memory mapped 1:1 at bottom)
and take the dump while still in mapped mode */
}
/*
* Move pages from one kernel virtual address to another.
* Both addresses are assumed to reside in the Sysmap,
* and size must be a multiple of CLSIZE.
*/
pagemove(from, to, size)
register caddr_t from, to;
int size;
{
register struct pte *fpte, *tpte;
if (size % CLBYTES)
panic("pagemove");
fpte = kvtopte(from);
tpte = kvtopte(to);
while (size > 0) {
*tpte++ = *fpte;
*(int *)fpte++ = 0;
from += NBPG;
to += NBPG;
size -= NBPG;
}
tlbflush();
}
/*
* Convert kernel VA to physical address
*/
kvtop(addr)
register caddr_t addr;
{
vm_offset_t va;
va = pmap_extract(kernel_pmap, (vm_offset_t)addr);
if (va == 0)
panic("kvtop: zero page frame");
return((int)va);
}
#ifdef notdef
/*
* The probe[rw] routines should probably be redone in assembler
* for efficiency.
*/
prober(addr)
register u_int addr;
{
register int page;
register struct proc *p;
if (addr >= USRSTACK)
return(0);
p = u.u_procp;
page = btop(addr);
if (page < dptov(p, p->p_dsize) || page > sptov(p, p->p_ssize))
return(1);
return(0);
}
probew(addr)
register u_int addr;
{
register int page;
register struct proc *p;
if (addr >= USRSTACK)
return(0);
p = u.u_procp;
page = btop(addr);
if (page < dptov(p, p->p_dsize) || page > sptov(p, p->p_ssize))
return((*(int *)vtopte(p, page) & PG_PROT) == PG_UW);
return(0);
}
/*
* NB: assumes a physically contiguous kernel page table
* (makes life a LOT simpler).
*/
kernacc(addr, count, rw)
register u_int addr;
int count, rw;
{
register struct pde *pde;
register struct pte *pte;
register int ix, cnt;
extern long Syssize;
if (count <= 0)
return(0);
pde = (struct pde *)((u_int)u.u_procp->p_p0br + u.u_procp->p_szpt * NBPG);
ix = (addr & PD_MASK) >> PD_SHIFT;
cnt = ((addr + count + (1 << PD_SHIFT) - 1) & PD_MASK) >> PD_SHIFT;
cnt -= ix;
for (pde += ix; cnt; cnt--, pde++)
if (pde->pd_v == 0)
return(0);
ix = btop(addr-0xfe000000);
cnt = btop(addr-0xfe000000+count+NBPG-1);
if (cnt > (int)&Syssize)
return(0);
cnt -= ix;
for (pte = &Sysmap[ix]; cnt; cnt--, pte++)
if (pte->pg_v == 0 /*|| (rw == B_WRITE && pte->pg_prot == 1)*/)
return(0);
return(1);
}
useracc(addr, count, rw)
register u_int addr;
int count, rw;
{
register int (*func)();
register u_int addr2;
extern int prober(), probew();
if (count <= 0)
return(0);
addr2 = addr;
addr += count;
func = (rw == B_READ) ? prober : probew;
do {
if ((*func)(addr2) == 0)
return(0);
addr2 = (addr2 + NBPG) & ~PGOFSET;
} while (addr2 < addr);
return(1);
}
#endif
extern vm_map_t phys_map;
/*
* Map an IO request into kernel virtual address space. Requests fall into
* one of five catagories:
*
* B_PHYS|B_UAREA: User u-area swap.
* Address is relative to start of u-area (p_addr).
* B_PHYS|B_PAGET: User page table swap.
* Address is a kernel VA in usrpt (Usrptmap).
* B_PHYS|B_DIRTY: Dirty page push.
* Address is a VA in proc2's address space.
* B_PHYS|B_PGIN: Kernel pagein of user pages.
* Address is VA in user's address space.
* B_PHYS: User "raw" IO request.
* Address is VA in user's address space.
*
* All requests are (re)mapped into kernel VA space via the useriomap
* (a name with only slightly more meaning than "kernelmap")
*/
vmapbuf(bp)
register struct buf *bp;
{
register int npf;
register caddr_t addr;
register long flags = bp->b_flags;
struct proc *p;
int off;
vm_offset_t kva;
register vm_offset_t pa;
if ((flags & B_PHYS) == 0)
panic("vmapbuf");
addr = bp->b_saveaddr = bp->b_un.b_addr;
off = (int)addr & PGOFSET;
p = bp->b_proc;
npf = btoc(round_page(bp->b_bcount + off));
kva = kmem_alloc_wait(phys_map, ctob(npf));
bp->b_un.b_addr = (caddr_t) (kva + off);
while (npf--) {
pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)addr);
if (pa == 0)
panic("vmapbuf: null page frame");
pmap_enter(vm_map_pmap(phys_map), kva, trunc_page(pa),
VM_PROT_READ|VM_PROT_WRITE, TRUE);
addr += PAGE_SIZE;
kva += PAGE_SIZE;
}
}
/*
* Free the io map PTEs associated with this IO operation.
* We also invalidate the TLB entries and restore the original b_addr.
*/
vunmapbuf(bp)
register struct buf *bp;
{
register int npf;
register caddr_t addr = bp->b_un.b_addr;
vm_offset_t kva;
if ((bp->b_flags & B_PHYS) == 0)
panic("vunmapbuf");
npf = btoc(round_page(bp->b_bcount + ((int)addr & PGOFSET)));
kva = (vm_offset_t)((int)addr & ~PGOFSET);
kmem_free_wakeup(phys_map, kva, ctob(npf));
bp->b_un.b_addr = bp->b_saveaddr;
bp->b_saveaddr = NULL;
}
/*
* Force reset the processor by invalidating the entire address space!
*/
cpu_reset() {
/* force a shutdown by unmapping entire address space ! */
bzero((caddr_t) PTD, NBPG);
/* "good night, sweet prince .... <THUNK!>" */
tlbflush();
/* NOTREACHED */
}
+108
View File
@@ -0,0 +1,108 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cpu.h 5.4 (Berkeley) 5/9/91
*/
/*
* Definitions unique to i386 cpu support.
*/
#include "machine/frame.h"
#include "machine/segments.h"
/*
* definitions of cpu-dependent requirements
* referenced in generic code
*/
#undef COPY_SIGCODE /* don't copy sigcode above user stack in exec */
/*
* function vs. inline configuration;
* these are defined to get generic functions
* rather than inline or machine-dependent implementations
*/
#define NEED_MINMAX /* need {,i,l,ul}{min,max} functions */
#define NEED_FFS /* need ffs function */
#define NEED_BCMP /* need bcmp function */
#define NEED_STRLEN /* need strlen function */
#define cpu_exec(p) /* nothing */
/*
* Arguments to hardclock, softclock and gatherstats
* encapsulate the previous machine state in an opaque
* clockframe; for now, use generic intrframe.
*/
typedef struct intrframe clockframe;
#define CLKF_USERMODE(framep) (ISPL((framep)->if_cs) == SEL_UPL)
#define CLKF_BASEPRI(framep) ((framep)->if_ppl == 0)
#define CLKF_PC(framep) ((framep)->if_eip)
#define resettodr() /* no todr to set */
/*
* Preempt the current process if in interrupt from user mode,
* or after the current trap/syscall if in system mode.
*/
#define need_resched() { want_resched++; aston(); }
/*
* Give a profiling tick to the current process from the softclock
* interrupt. On tahoe, request an ast to send us through trap(),
* marking the proc as needing a profiling tick.
*/
#define profile_tick(p, framep) { (p)->p_flag |= SOWEUPC; aston(); }
/*
* Notify the current process (p) that it has a signal pending,
* process as soon as possible.
*/
#define signotify(p) aston()
#define aston() (astpending++)
int astpending; /* need to trap before returning to user mode */
int want_resched; /* resched() was called */
/*
* Kinds of processor
*/
#define CPU_386SX 0
#define CPU_386 1
#define CPU_486SX 2
#define CPU_486 3
#define CPU_586 4
+82
View File
@@ -0,0 +1,82 @@
/*
* Functions to provide access to special i386 instructions.
* XXX - bezillions more are defined in locore.s but are not declared anywhere.
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#ifdef __GNUC__
static __inline int bdb(void)
{
extern int bdb_exists;
if (!bdb_exists)
return (0);
__asm("int $3");
return (1);
}
static __inline void
disable_intr(void)
{
__asm __volatile("cli");
}
static __inline void
enable_intr(void)
{
__asm __volatile("sti");
}
/*
* This roundabout method of returning a u_char helps stop gcc-1.40 from
* generating unnecessary movzbl's.
*/
#define inb(port) ((u_char) u_int_inb(port))
static __inline u_int
u_int_inb(u_int port)
{
u_char data;
/*
* We use %%dx and not %1 here because i/o is done at %dx and not at
* %edx, while gcc-2.2.2 generates inferior code (movw instead of movl)
* if we tell it to load (u_short) port.
*/
__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
return data;
}
static __inline void
outb(u_int port, u_char data)
{
register u_char al asm("ax");
al = data; /* help gcc-1.40's register allocator */
__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
}
#else /* not __GNUC__ */
int bdb __P((void));
void disable_intr __P((void));
void enable_intr __P((void));
u_char inb __P((u_int port));
void outb __P((u_int port, u_int data)); /* XXX - incompat */
#endif /* __GNUC__ */
#define really_u_int int /* XXX */
#define really_void int /* XXX */
void load_cr0 __P((u_int cr0));
really_u_int rcr0 __P((void));
#ifdef notyet
really_void setidt __P((int idx, /*XXX*/caddr_t func, int typ, int dpl));
#endif
#undef really_u_int
#undef really_void
+154
View File
@@ -0,0 +1,154 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_machdep.h,v $
* Revision 2.8 92/02/19 15:07:56 elf
* Added db_thread_fp_used.
* [92/02/19 rpd]
*
* Revision 2.7 91/10/09 16:06:28 af
* Revision 2.6.3.1 91/10/05 13:10:32 jeffreyh
* Added access and task name macros.
* [91/08/29 tak]
*
* Revision 2.6.3.1 91/10/05 13:10:32 jeffreyh
* Added access and task name macros.
* [91/08/29 tak]
*
* Revision 2.6 91/05/14 16:05:58 mrt
* Correcting copyright
*
* Revision 2.5 91/02/05 17:11:17 mrt
* Changed to new Mach copyright
* [91/02/01 17:31:24 mrt]
*
* Revision 2.4 91/01/08 15:10:16 rpd
* Added dummy inst_load/inst_store macros.
* [90/12/11 rpd]
*
* Revision 2.3 90/10/25 14:44:49 rwd
* Added watchpoint support.
* [90/10/18 rpd]
*
* Revision 2.2 90/08/27 21:56:15 dbg
* Created.
* [90/07/25 dbg]
*
*/
#ifndef _I386_DB_MACHDEP_H_
#define _I386_DB_MACHDEP_H_
/*
* Machine-dependent defines for new kernel debugger.
*/
/* #include <mach/i386/vm_types.h> */
/* #include <mach/i386/vm_param.h> */
#include <vm/vm_prot.h>
#include <vm/vm_param.h>
#include <vm/vm_inherit.h>
#include <vm/lock.h>
/* #include <i386/thread.h> */ /* for thread_status */
#include <machine/frame.h> /* for struct trapframe */
/* #include <i386/eflags.h> */
#include <machine/eflags.h> /* from Mach... */
/* #include <i386/trap.h> */
#include <machine/trap.h>
#define i386_saved_state trapframe
/* end of mangling */
typedef vm_offset_t db_addr_t; /* address - unsigned */
typedef int db_expr_t; /* expression - signed */
typedef struct i386_saved_state db_regs_t;
db_regs_t ddb_regs; /* register state */
#define DDB_REGS (&ddb_regs)
#define PC_REGS(regs) ((db_addr_t)(regs)->tf_eip)
#define BKPT_INST 0xcc /* breakpoint instruction */
#define BKPT_SIZE (1) /* size of breakpoint inst */
#define BKPT_SET(inst) (BKPT_INST)
#define FIXUP_PC_AFTER_BREAK ddb_regs.tf_eip -= 1;
#define db_clear_single_step(regs) ((regs)->tf_eflags &= ~EFL_TF)
#define db_set_single_step(regs) ((regs)->tf_eflags |= EFL_TF)
/* #define IS_BREAKPOINT_TRAP(type, code) ((type) == T_INT3) */
/* #define IS_WATCHPOINT_TRAP(type, code) ((type) == T_WATCHPOINT) */
/* using the 386bsd values, rather than the Mach ones: */
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_KDBTRAP)
#define I_CALL 0xe8
#define I_CALLI 0xff
#define I_RET 0xc3
#define I_IRET 0xcf
#define inst_trap_return(ins) (((ins)&0xff) == I_IRET)
#define inst_return(ins) (((ins)&0xff) == I_RET)
#define inst_call(ins) (((ins)&0xff) == I_CALL || \
(((ins)&0xff) == I_CALLI && \
((ins)&0x3800) == 0x1000))
#define inst_load(ins) 0
#define inst_store(ins) 0
/* access capability and access macros */
#define DB_ACCESS_LEVEL 2 /* access any space */
#define DB_CHECK_ACCESS(addr,size,task) \
db_check_access(addr,size,task)
#define DB_PHYS_EQ(task1,addr1,task2,addr2) \
db_phys_eq(task1,addr1,task2,addr2)
#define DB_VALID_KERN_ADDR(addr) \
((addr) >= VM_MIN_KERNEL_ADDRESS && \
(addr) < VM_MAX_KERNEL_ADDRESS)
#define DB_VALID_ADDRESS(addr,user) \
((!(user) && DB_VALID_KERN_ADDR(addr)) || \
((user) && (addr) < VM_MIN_KERNEL_ADDRESS))
boolean_t db_check_access(/* vm_offset_t, int, task_t */);
boolean_t db_phys_eq(/* task_t, vm_offset_t, task_t, vm_offset_t */);
/* macros for printing OS server dependent task name */
#define DB_TASK_NAME(task) db_task_name(task)
#define DB_TASK_NAME_TITLE "COMMAND "
#define DB_TASK_NAME_LEN 23
#define DB_NULL_TASK_NAME "? "
void db_task_name(/* task_t */);
/* macro for checking if a thread has used floating-point */
#define db_thread_fp_used(thread) ((thread)->pcb->ims.ifps != 0)
#endif /* _I386_DB_MACHDEP_H_ */
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)float.h 7.1 (Berkeley) 5/8/90
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00086
* -------------------- ----- ----------------------
*
* 27 Feb 93 Handel/da Silva/Poirot Adjust value for MAX_DOUBLE
*/
#define FLT_RADIX 2 /* b */
#define FLT_ROUNDS 1 /* FP addition rounds to nearest */
#define FLT_MANT_DIG 24 /* p */
#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */
#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */
#define FLT_MIN_EXP -125 /* emin */
#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */
#define FLT_MIN_10_EXP -37 /* ceil(log10(b**(emin-1))) */
#define FLT_MAX_EXP 128 /* emax */
#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */
#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */
#define DBL_MANT_DIG 53
#define DBL_EPSILON 2.2204460492503131E-16
#define DBL_DIG 15
#define DBL_MIN_EXP -1021
#define DBL_MIN 2.225073858507201E-308
#define DBL_MIN_10_EXP -307
#define DBL_MAX_EXP 1024
#define DBL_MAX 1.797693134862315E+308
#define DBL_MAX_10_EXP 308
#define LDBL_MANT_DIG DBL_MANT_DIG
#define LDBL_EPSILON DBL_EPSILON
#define LDBL_DIG DBL_DIG
#define LDBL_MIN_EXP DBL_MIN_EXP
#define LDBL_MIN DBL_MIN
#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
#define LDBL_MAX_EXP DBL_MAX_EXP
#define LDBL_MAX DBL_MAX
#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+146
View File
@@ -0,0 +1,146 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)npx.h 5.3 (Berkeley) 1/18/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 20 Apr 93 Bruce Evans New npx-0.5 code
*
*/
/*
* 287/387 NPX Coprocessor Data Structures and Constants
* W. Jolitz 1/90
*/
#ifndef ___NPX87___
#define ___NPX87___
/* Environment information of floating point unit */
struct env87 {
long en_cw; /* control word (16bits) */
long en_sw; /* status word (16bits) */
long en_tw; /* tag word (16bits) */
long en_fip; /* floating point instruction pointer */
u_short en_fcs; /* floating code segment selector */
u_short en_opcode; /* opcode last executed (11 bits ) */
long en_foo; /* floating operand offset */
long en_fos; /* floating operand segment selector */
};
/* Contents of each floating point accumulator */
struct fpacc87 {
#ifdef dontdef /* too unportable */
u_long fp_mantlo; /* mantissa low (31:0) */
u_long fp_manthi; /* mantissa high (63:32) */
int fp_exp:15; /* exponent */
int fp_sgn:1; /* mantissa sign */
#else
u_char fp_bytes[10];
#endif
};
/* Floating point context */
struct save87 {
struct env87 sv_env; /* floating point control/status */
struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
#ifndef dontdef
u_long sv_ex_sw; /* status word for last exception (was pad) */
u_long sv_ex_tw; /* tag word for last exception (was pad) */
u_char sv_pad[8 * 2 - 2 * 4]; /* bogus historical padding */
#endif
};
/* Cyrix EMC memory - mapped coprocessor context switch information */
struct emcsts {
long em_msw; /* memory mapped status register when swtched */
long em_tar; /* memory mapped temp A register when swtched */
long em_dl; /* memory mapped D low register when swtched */
};
/* Intel prefers long real (53 bit) precision */
#define __iBCS_NPXCW__ 0x262
/* wfj prefers temporary real (64 bit) precision */
#define __386BSD_NPXCW__ 0x362
/*
* bde prefers 53 bit precision and all exceptions masked.
*
* The standard control word from finit is 0x37F, giving:
*
* round to nearest
* 64-bit precision
* all exceptions masked.
*
* Now I want:
*
* affine mode for 287's (if they work at all) (1 in bitfield 1<<12)
* 53-bit precision (2 in bitfield 3<<8)
* overflow exception unmasked (0 in bitfield 1<<3)
* zero divide exception unmasked (0 in bitfield 1<<2)
* invalid-operand exception unmasked (0 in bitfield 1<<0).
*
* 64-bit precision often gives bad results with high level languages
* because it makes the results of calculations depend on whether
* intermediate values are stored in memory or in FPU registers.
*
* The "Intel" and wfj control words have:
*
* underflow exception unmasked (0 in bitfield 1<<4)
*
* but that causes an unexpected exception in the test program 'paranoia'
* and makes denormals useless (DBL_MIN / 2 underflows). It doesn't make
* a lot of sense to trap underflow without trapping denormals.
*
* Later I will want the IEEE default of all exceptions masked. See the
* 0.0 math manpage for why this is better. The 0.1 math manpage is empty.
*/
#define __BDE_NPXCW__ 0x1272
#define __BETTER_BDE_NPXCW__ 0x127f
#ifdef __BROKEN_NPXCW__
#ifdef __386BSD__
#define __INITIAL_NPXCW__ __386BSD_NPXCW__
#else
#define __INITIAL_NPXCW__ __iBCS_NPXCW__
#endif
#else
#define __INITIAL_NPXCW__ __BDE_NPXCW__
#endif
#endif ___NPX87___
+116
View File
@@ -0,0 +1,116 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)frame.h 5.2 (Berkeley) 1/18/91
*/
/*
* System stack frames.
*/
/*
* Exception/Trap Stack Frame
*/
struct trapframe {
int tf_es;
int tf_ds;
int tf_edi;
int tf_esi;
int tf_ebp;
int tf_isp;
int tf_ebx;
int tf_edx;
int tf_ecx;
int tf_eax;
int tf_trapno;
/* below portion defined in 386 hardware */
int tf_err;
int tf_eip;
int tf_cs;
int tf_eflags;
/* below only when transitting rings (e.g. user to kernel) */
int tf_esp;
int tf_ss;
};
/* Interrupt stack frame */
struct intrframe {
int if_vec;
int if_ppl;
int if_es;
int if_ds;
int if_edi;
int if_esi;
int if_ebp;
int :32;
int if_ebx;
int if_edx;
int if_ecx;
int if_eax;
int :32; /* for compat with trap frame - trapno */
int :32; /* for compat with trap frame - err */
/* below portion defined in 386 hardware */
int if_eip;
int if_cs;
int if_eflags;
/* below only when transitting rings (e.g. user to kernel) */
int if_esp;
int if_ss;
};
/*
* Call Gate/System Call Stack Frame
*/
struct syscframe {
int sf_edi;
int sf_esi;
int sf_ebp;
int :32; /* redundant save of isp */
int sf_ebx;
int sf_edx;
int sf_ecx;
int sf_eax;
int sf_eflags;
/* below portion defined in 386 hardware */
/* int sf_args[N]; /* if call gate copy args enabled!*/
int sf_eip;
int sf_cs;
/* below only when transitting rings (e.g. user to kernel) */
int sf_esp;
int sf_ss;
};
+146
View File
@@ -0,0 +1,146 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)npx.h 5.3 (Berkeley) 1/18/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 20 Apr 93 Bruce Evans New npx-0.5 code
*
*/
/*
* 287/387 NPX Coprocessor Data Structures and Constants
* W. Jolitz 1/90
*/
#ifndef ___NPX87___
#define ___NPX87___
/* Environment information of floating point unit */
struct env87 {
long en_cw; /* control word (16bits) */
long en_sw; /* status word (16bits) */
long en_tw; /* tag word (16bits) */
long en_fip; /* floating point instruction pointer */
u_short en_fcs; /* floating code segment selector */
u_short en_opcode; /* opcode last executed (11 bits ) */
long en_foo; /* floating operand offset */
long en_fos; /* floating operand segment selector */
};
/* Contents of each floating point accumulator */
struct fpacc87 {
#ifdef dontdef /* too unportable */
u_long fp_mantlo; /* mantissa low (31:0) */
u_long fp_manthi; /* mantissa high (63:32) */
int fp_exp:15; /* exponent */
int fp_sgn:1; /* mantissa sign */
#else
u_char fp_bytes[10];
#endif
};
/* Floating point context */
struct save87 {
struct env87 sv_env; /* floating point control/status */
struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
#ifndef dontdef
u_long sv_ex_sw; /* status word for last exception (was pad) */
u_long sv_ex_tw; /* tag word for last exception (was pad) */
u_char sv_pad[8 * 2 - 2 * 4]; /* bogus historical padding */
#endif
};
/* Cyrix EMC memory - mapped coprocessor context switch information */
struct emcsts {
long em_msw; /* memory mapped status register when swtched */
long em_tar; /* memory mapped temp A register when swtched */
long em_dl; /* memory mapped D low register when swtched */
};
/* Intel prefers long real (53 bit) precision */
#define __iBCS_NPXCW__ 0x262
/* wfj prefers temporary real (64 bit) precision */
#define __386BSD_NPXCW__ 0x362
/*
* bde prefers 53 bit precision and all exceptions masked.
*
* The standard control word from finit is 0x37F, giving:
*
* round to nearest
* 64-bit precision
* all exceptions masked.
*
* Now I want:
*
* affine mode for 287's (if they work at all) (1 in bitfield 1<<12)
* 53-bit precision (2 in bitfield 3<<8)
* overflow exception unmasked (0 in bitfield 1<<3)
* zero divide exception unmasked (0 in bitfield 1<<2)
* invalid-operand exception unmasked (0 in bitfield 1<<0).
*
* 64-bit precision often gives bad results with high level languages
* because it makes the results of calculations depend on whether
* intermediate values are stored in memory or in FPU registers.
*
* The "Intel" and wfj control words have:
*
* underflow exception unmasked (0 in bitfield 1<<4)
*
* but that causes an unexpected exception in the test program 'paranoia'
* and makes denormals useless (DBL_MIN / 2 underflows). It doesn't make
* a lot of sense to trap underflow without trapping denormals.
*
* Later I will want the IEEE default of all exceptions masked. See the
* 0.0 math manpage for why this is better. The 0.1 math manpage is empty.
*/
#define __BDE_NPXCW__ 0x1272
#define __BETTER_BDE_NPXCW__ 0x127f
#ifdef __BROKEN_NPXCW__
#ifdef __386BSD__
#define __INITIAL_NPXCW__ __386BSD_NPXCW__
#else
#define __INITIAL_NPXCW__ __iBCS_NPXCW__
#endif
#else
#define __INITIAL_NPXCW__ __BDE_NPXCW__
#endif
#endif ___NPX87___
+43
View File
@@ -0,0 +1,43 @@
/*
* IBM PC display definitions
*/
/* Color attributes for foreground text */
#define FG_BLACK 0
#define FG_BLUE 1
#define FG_GREEN 2
#define FG_CYAN 3
#define FG_RED 4
#define FG_MAGENTA 5
#define FG_BROWN 6
#define FG_LIGHTGREY 7
#define FG_DARKGREY 8
#define FG_LIGHTBLUE 9
#define FG_LIGHTGREEN 10
#define FG_LIGHTCYAN 11
#define FG_LIGHTRED 12
#define FG_LIGHTMAGENTA 13
#define FG_YELLOW 14
#define FG_WHITE 15
#define FG_BLINK 0x80
/* Color attributes for text background */
#define BG_BLACK 0x00
#define BG_BLUE 0x10
#define BG_GREEN 0x20
#define BG_CYAN 0x30
#define BG_RED 0x40
#define BG_MAGENTA 0x50
#define BG_BROWN 0x60
#define BG_LIGHTGREY 0x70
/* Monochrome attributes for foreground text */
#define FG_UNDERLINE 0x01
#define FG_INTENSE 0x08
/* Monochrome attributes for text background */
#define BG_INTENSE 0x10
+87
View File
@@ -0,0 +1,87 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pcb.h 5.10 (Berkeley) 5/12/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 20 Apr 93 Bruce Evans New npx-0.5 code
*
*/
/*
* Intel 386 process control block
*/
#include "machine/tss.h"
#include "machine/npx.h"
struct pcb {
struct i386tss pcb_tss;
#define pcb_ksp pcb_tss.tss_esp0
#define pcb_ptd pcb_tss.tss_cr3
#define pcb_cr3 pcb_ptd
#define pcb_pc pcb_tss.tss_eip
#define pcb_psl pcb_tss.tss_eflags
#define pcb_usp pcb_tss.tss_esp
#define pcb_fp pcb_tss.tss_ebp
#ifdef notyet
u_char pcb_iomap[NPORT/sizeof(u_char)]; /* i/o port bitmap */
#endif
struct save87 pcb_savefpu; /* floating point state for 287/387 */
struct emcsts pcb_saveemc; /* Cyrix EMC state */
/*
* Software pcb (extension)
*/
int pcb_flags;
#ifdef notused
#define FP_WASUSED 0x01 /* process has used fltng pnt hardware */
#define FP_NEEDSSAVE 0x02 /* ... that needs save on next context switch */
#define FP_NEEDSRESTORE 0x04 /* ... that needs restore on next DNA fault */
#endif
#define FP_USESEMC 0x08 /* process uses EMC memory-mapped mode */
#define FM_TRAP 0x10 /* process entered kernel on a trap frame */
#define FP_SOFTFP 0x20 /* process using software fltng pnt emulator */
short pcb_iml; /* interrupt mask level */
caddr_t pcb_onfault; /* copyin/out fault recovery */
long pcb_sigc[8]; /* XXX signal code trampoline */
int pcb_cmap2; /* XXX temporary PTE - will prefault instead */
};
#ifdef KERNEL
struct pcb *curpcb; /* our current running pcb */
#endif
+234
View File
@@ -0,0 +1,234 @@
/*
* Copyright (c) 1991 Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* Science Department and William Jolitz of UUNET Technologies Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pmap.h 7.4 (Berkeley) 5/12/91
*/
/*
* Derived from hp300 version by Mike Hibler, this version by William
* Jolitz uses a recursive map [a pde points to the page directory] to
* map the page tables using the pagetables themselves. This is done to
* reduce the impact on kernel virtual memory for lots of sparse address
* space, and to reduce the cost of memory to each process.
*
* from hp300: @(#)pmap.h 7.2 (Berkeley) 12/16/90
*/
#ifndef _PMAP_MACHINE_
#define _PMAP_MACHINE_ 1
/*
* 386 page table entry and page table directory
* W.Jolitz, 8/89
*/
struct pde
{
unsigned int
pd_v:1, /* valid bit */
pd_prot:2, /* access control */
pd_mbz1:2, /* reserved, must be zero */
pd_u:1, /* hardware maintained 'used' bit */
:1, /* not used */
pd_mbz2:2, /* reserved, must be zero */
:3, /* reserved for software */
pd_pfnum:20; /* physical page frame number of pte's*/
};
#define PD_MASK 0xffc00000 /* page directory address bits */
#define PT_MASK 0x003ff000 /* page table address bits */
#define PD_SHIFT 22 /* page directory address shift */
#define PG_SHIFT 12 /* page table address shift */
struct pte
{
unsigned int
pg_v:1, /* valid bit */
pg_prot:2, /* access control */
pg_mbz1:2, /* reserved, must be zero */
pg_u:1, /* hardware maintained 'used' bit */
pg_m:1, /* hardware maintained modified bit */
pg_mbz2:2, /* reserved, must be zero */
pg_w:1, /* software, wired down page */
:1, /* software (unused) */
pg_nc:1, /* 'uncacheable page' bit */
pg_pfnum:20; /* physical page frame number */
};
#define PG_V 0x00000001
#define PG_RO 0x00000000
#define PG_RW 0x00000002
#define PG_u 0x00000004
#define PG_PROT 0x00000006 /* all protection bits . */
#define PG_W 0x00000200
#define PG_N 0x00000800 /* Non-cacheable */
#define PG_M 0x00000040
#define PG_U 0x00000020
#define PG_FRAME 0xfffff000
#define PG_NOACC 0
#define PG_KR 0x00000000
#define PG_KW 0x00000002
#define PG_URKR 0x00000004
#define PG_URKW 0x00000004
#define PG_UW 0x00000006
/* Garbage for current bastardized pager that assumes a hp300 */
#define PG_NV 0
#define PG_CI 0
/*
* Page Protection Exception bits
*/
#define PGEX_P 0x01 /* Protection violation vs. not present */
#define PGEX_W 0x02 /* during a Write cycle */
#define PGEX_U 0x04 /* access from User mode (UPL) */
typedef struct pde pd_entry_t; /* page directory entry */
typedef struct pte pt_entry_t; /* Mach page table entry */
/*
* One page directory, shared between
* kernel and user modes.
*/
#define I386_PAGE_SIZE NBPG
#define I386_PDR_SIZE NBPDR
#define I386_KPDES 8 /* KPT page directory size */
#define I386_UPDES NBPDR/sizeof(struct pde)-8 /* UPT page directory size */
#define UPTDI 0x3f6 /* ptd entry for u./kernel&user stack */
#define PTDPTDI 0x3f7 /* ptd entry that points to ptd! */
#define KPTDI_FIRST 0x3f8 /* start of kernel virtual pde's */
#define KPTDI_LAST 0x3fA /* last of kernel virtual pde's */
/*
* Address of current and alternate address space page table maps
* and directories.
*/
#ifdef KERNEL
extern struct pte PTmap[], APTmap[], Upte;
extern struct pde PTD[], APTD[], PTDpde, APTDpde, Upde;
extern pt_entry_t *Sysmap;
extern int IdlePTD; /* physical address of "Idle" state directory */
#endif
/*
* virtual address to page table entry and
* to physical address. Likewise for alternate address space.
* Note: these work recursively, thus vtopte of a pte will give
* the corresponding pde that in turn maps it.
*/
#define vtopte(va) (PTmap + i386_btop(va))
#define kvtopte(va) vtopte(va)
#define ptetov(pt) (i386_ptob(pt - PTmap))
#define vtophys(va) (i386_ptob(vtopte(va)->pg_pfnum) | ((int)(va) & PGOFSET))
#define ispt(va) ((va) >= UPT_MIN_ADDRESS && (va) <= KPT_MAX_ADDRESS)
#define avtopte(va) (APTmap + i386_btop(va))
#define ptetoav(pt) (i386_ptob(pt - APTmap))
#define avtophys(va) (i386_ptob(avtopte(va)->pg_pfnum) | ((int)(va) & PGOFSET))
/*
* macros to generate page directory/table indicies
*/
#define pdei(va) (((va)&PD_MASK)>>PD_SHIFT)
#define ptei(va) (((va)&PT_MASK)>>PG_SHIFT)
/*
* Pmap stuff
*/
struct pmap {
pd_entry_t *pm_pdir; /* KVA of page directory */
boolean_t pm_pdchanged; /* pdir changed */
short pm_dref; /* page directory ref count */
short pm_count; /* pmap reference count */
simple_lock_data_t pm_lock; /* lock on pmap */
struct pmap_statistics pm_stats; /* pmap statistics */
long pm_ptpages; /* more stats: PT pages */
};
typedef struct pmap *pmap_t;
#ifdef KERNEL
extern pmap_t kernel_pmap;
#endif
/*
* Macros for speed
*/
#define PMAP_ACTIVATE(pmapp, pcbp) \
if ((pmapp) != NULL /*&& (pmapp)->pm_pdchanged */) { \
(pcbp)->pcb_cr3 = \
pmap_extract(kernel_pmap, (pmapp)->pm_pdir); \
if ((pmapp) == &curproc->p_vmspace->vm_pmap) \
load_cr3((pcbp)->pcb_cr3); \
(pmapp)->pm_pdchanged = FALSE; \
}
#define PMAP_DEACTIVATE(pmapp, pcbp)
/*
* For each vm_page_t, there is a list of all currently valid virtual
* mappings of that page. An entry is a pv_entry_t, the list is pv_table.
*/
typedef struct pv_entry {
struct pv_entry *pv_next; /* next pv_entry */
pmap_t pv_pmap; /* pmap where mapping lies */
vm_offset_t pv_va; /* virtual address for mapping */
int pv_flags; /* flags */
} *pv_entry_t;
#define PV_ENTRY_NULL ((pv_entry_t) 0)
#define PV_CI 0x01 /* all entries must be cache inhibited */
#define PV_PTPAGE 0x02 /* entry maps a page table page */
#ifdef KERNEL
pv_entry_t pv_table; /* array of entries, one per page */
#define pa_index(pa) atop(pa - vm_first_phys)
#define pa_to_pvh(pa) (&pv_table[pa_index(pa)])
#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
#endif KERNEL
#endif _PMAP_MACHINE_
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 1991 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)proc.h 7.1 (Berkeley) 5/15/91
*/
/*
* Machine-dependent part of the proc structure for hp300.
*/
struct mdproc {
int md_flags; /* machine-dependent flags */
#ifdef notyet
int *p_regs; /* registers on current frame */
#endif
};
/* md_flags */
#define MDP_AST 0x0001 /* async trap pending */
+60
View File
@@ -0,0 +1,60 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)psl.h 5.2 (Berkeley) 1/18/91
*/
/*
* 386 processor status longword.
*/
#define PSL_C 0x00000001 /* carry bit */
#define PSL_PF 0x00000004 /* parity bit */
#define PSL_AF 0x00000010 /* bcd carry bit */
#define PSL_Z 0x00000040 /* zero bit */
#define PSL_N 0x00000080 /* negative bit */
#define PSL_T 0x00000100 /* trace enable bit */
#define PSL_I 0x00000200 /* interrupt enable bit */
#define PSL_D 0x00000400 /* string instruction direction bit */
#define PSL_V 0x00000800 /* overflow bit */
#define PSL_IOPL 0x00003000 /* i/o priviledge level enable */
#define PSL_NT 0x00004000 /* nested task bit */
#define PSL_RF 0x00010000 /* restart flag bit */
#define PSL_VM 0x00020000 /* virtual 8086 mode bit */
#define PSL_MBZ 0xfffc7fb7 /* must be zero bits */
#define PSL_MBO 0x00000002 /* must be one bits */
#define PSL_USERSET (PSL_IOPL)
#define PSL_USERCLR (PSL_I|PSL_NT)
+93
View File
@@ -0,0 +1,93 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)reg.h 5.5 (Berkeley) 1/18/91
*/
/*
* Location of the users' stored
* registers within appropriate frame of 'trap' and 'syscall', relative to
* base of stack frame.
* Normal usage is u.u_ar0[XX] in kernel.
*/
/* When referenced during a trap/exception, registers are at these offsets */
#define tES (0)
#define tDS (1)
#define tEDI (2)
#define tESI (3)
#define tEBP (4)
#define tEBX (6)
#define tEDX (7)
#define tECX (8)
#define tEAX (9)
#define tEIP (12)
#define tCS (13)
#define tEFLAGS (14)
#define tESP (15)
#define tSS (16)
/* During a system call, registers are at these offsets instead of above. */
#define sEDI (0)
#define sESI (1)
#define sEBP (2)
#define sEBX (4)
#define sEDX (5)
#define sECX (6)
#define sEAX (7)
#define sEFLAGS (8)
#define sEIP (9)
#define sCS (10)
#define sESP (11)
#define sSS (12)
#define PC sEIP
#define SP sESP
#define PS sEFLAGS
#define R0 sEDX
#define R1 sECX
/*
* Registers accessible to ptrace(2) syscall for debugger
*/
#ifdef IPCREG
#define NIPCREG 14
int ipcreg[NIPCREG] =
{ tES,tDS,tEDI,tESI,tEBP,tEBX,tEDX,tECX,tEAX,tEIP,tCS,tEFLAGS,tESP,tSS };
#endif
+196
View File
@@ -0,0 +1,196 @@
/*-
* Copyright (c) 1989, 1990 William F. Jolitz
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)segments.h 7.1 (Berkeley) 5/9/91
*/
/*
* 386 Segmentation Data Structures and definitions
* William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989
*/
/*
* Selectors
*/
#define ISPL(s) ((s)&3) /* what is the priority level of a selector */
#define SEL_KPL 0 /* kernel priority level */
#define SEL_UPL 3 /* user priority level */
#define ISLDT(s) ((s)&SEL_LDT) /* is it local or global */
#define SEL_LDT 4 /* local descriptor table */
#define IDXSEL(s) (((s)>>3) & 0x1fff) /* index of selector */
#define LSEL(s,r) (((s)<<3) | SEL_LDT | r) /* a local selector */
#define GSEL(s,r) (((s)<<3) | r) /* a global selector */
/*
* Memory and System segment descriptors
*/
struct segment_descriptor {
unsigned sd_lolimit:16 ; /* segment extent (lsb) */
unsigned sd_lobase:24 ; /* segment base address (lsb) */
unsigned sd_type:5 ; /* segment type */
unsigned sd_dpl:2 ; /* segment descriptor priority level */
unsigned sd_p:1 ; /* segment descriptor present */
unsigned sd_hilimit:4 ; /* segment extent (msb) */
unsigned sd_xx:2 ; /* unused */
unsigned sd_def32:1 ; /* default 32 vs 16 bit size */
unsigned sd_gran:1 ; /* limit granularity (byte/page units)*/
unsigned sd_hibase:8 ; /* segment base address (msb) */
} ;
/*
* Gate descriptors (e.g. indirect descriptors)
*/
struct gate_descriptor {
unsigned gd_looffset:16 ; /* gate offset (lsb) */
unsigned gd_selector:16 ; /* gate segment selector */
unsigned gd_stkcpy:5 ; /* number of stack wds to cpy */
unsigned gd_xx:3 ; /* unused */
unsigned gd_type:5 ; /* segment type */
unsigned gd_dpl:2 ; /* segment descriptor priority level */
unsigned gd_p:1 ; /* segment descriptor present */
unsigned gd_hioffset:16 ; /* gate offset (msb) */
} ;
/*
* Generic descriptor
*/
union descriptor {
struct segment_descriptor sd;
struct gate_descriptor gd;
};
/* system segments and gate types */
#define SDT_SYSNULL 0 /* system null */
#define SDT_SYS286TSS 1 /* system 286 TSS available */
#define SDT_SYSLDT 2 /* system local descriptor table */
#define SDT_SYS286BSY 3 /* system 286 TSS busy */
#define SDT_SYS286CGT 4 /* system 286 call gate */
#define SDT_SYSTASKGT 5 /* system task gate */
#define SDT_SYS286IGT 6 /* system 286 interrupt gate */
#define SDT_SYS286TGT 7 /* system 286 trap gate */
#define SDT_SYSNULL2 8 /* system null again */
#define SDT_SYS386TSS 9 /* system 386 TSS available */
#define SDT_SYSNULL3 10 /* system null again */
#define SDT_SYS386BSY 11 /* system 386 TSS busy */
#define SDT_SYS386CGT 12 /* system 386 call gate */
#define SDT_SYSNULL4 13 /* system null again */
#define SDT_SYS386IGT 14 /* system 386 interrupt gate */
#define SDT_SYS386TGT 15 /* system 386 trap gate */
/* memory segment types */
#define SDT_MEMRO 16 /* memory read only */
#define SDT_MEMROA 17 /* memory read only accessed */
#define SDT_MEMRW 18 /* memory read write */
#define SDT_MEMRWA 19 /* memory read write accessed */
#define SDT_MEMROD 20 /* memory read only expand dwn limit */
#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */
#define SDT_MEMRWD 22 /* memory read write expand dwn limit */
#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */
#define SDT_MEME 24 /* memory execute only */
#define SDT_MEMEA 25 /* memory execute only accessed */
#define SDT_MEMER 26 /* memory execute read */
#define SDT_MEMERA 27 /* memory execute read accessed */
#define SDT_MEMEC 28 /* memory execute only conforming */
#define SDT_MEMEAC 29 /* memory execute only accessed conforming */
#define SDT_MEMERC 30 /* memory execute read conforming */
#define SDT_MEMERAC 31 /* memory execute read accessed conforming */
/* is memory segment descriptor pointer ? */
#define ISMEMSDP(s) ((s->d_type) >= SDT_MEMRO && (s->d_type) <= SDT_MEMERAC)
/* is 286 gate descriptor pointer ? */
#define IS286GDP(s) (((s->d_type) >= SDT_SYS286CGT \
&& (s->d_type) < SDT_SYS286TGT))
/* is 386 gate descriptor pointer ? */
#define IS386GDP(s) (((s->d_type) >= SDT_SYS386CGT \
&& (s->d_type) < SDT_SYS386TGT))
/* is gate descriptor pointer ? */
#define ISGDP(s) (IS286GDP(s) || IS386GDP(s))
/* is segment descriptor pointer ? */
#define ISSDP(s) (ISMEMSDP(s) || !ISGDP(s))
/* is system segment descriptor pointer ? */
#define ISSYSSDP(s) (!ISMEMSDP(s) && !ISGDP(s))
/*
* Software definitions are in this convenient format,
* which are translated into inconvenient segment descriptors
* when needed to be used by the 386 hardware
*/
struct soft_segment_descriptor {
unsigned ssd_base ; /* segment base address */
unsigned ssd_limit ; /* segment extent */
unsigned ssd_type:5 ; /* segment type */
unsigned ssd_dpl:2 ; /* segment descriptor priority level */
unsigned ssd_p:1 ; /* segment descriptor present */
unsigned ssd_xx:4 ; /* unused */
unsigned ssd_xx1:2 ; /* unused */
unsigned ssd_def32:1 ; /* default 32 vs 16 bit size */
unsigned ssd_gran:1 ; /* limit granularity (byte/page units)*/
};
extern ssdtosd() ; /* to decode a ssd */
extern sdtossd() ; /* to encode a sd */
/*
* region descriptors, used to load gdt/idt tables before segments yet exist.
*/
struct region_descriptor {
unsigned rd_limit:16; /* segment extent */
unsigned rd_base:32; /* base address */
};
/*
* Segment Protection Exception code bits
*/
#define SEGEX_EXT 0x01 /* recursive or externally induced */
#define SEGEX_IDT 0x02 /* interrupt descriptor table */
#define SEGEX_TI 0x04 /* local descriptor table */
/* other bits are affected descriptor index */
#define SEGEX_IDX(s) ((s)>>3)&0x1fff)
/*
* Size of IDT table
*/
#define NIDT 256
#define NRSVIDT 32 /* reserved entries for cpu exceptions */
+67
View File
@@ -0,0 +1,67 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)specialreg.h 7.1 (Berkeley) 5/9/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 20 Apr 93 Bruce Evans New npx-0.5 code
*
*/
/*
* Bits in 386 special registers:
*/
#define CR0_PE 0x00000001 /* Protected mode Enable */
#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */
#ifdef notused
#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */
#endif
#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */
#ifdef notused
#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */
#endif
#define CR0_PG 0x80000000 /* PaGing enable */
/*
* Bits in 486 special registers:
*/
#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */
#define CR0_WP 0x00010000 /* Write Protect (honor ~PG_W in all modes) */
#ifdef notyet
#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */
#endif
+96
View File
@@ -0,0 +1,96 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)trap.h 5.4 (Berkeley) 5/9/91
*/
/*
* Trap type values
* also known in trap.c for name strings
*/
#define T_RESADFLT 0 /* reserved addressing */
#define T_PRIVINFLT 1 /* privileged instruction */
#define T_RESOPFLT 2 /* reserved operand */
#define T_BPTFLT 3 /* breakpoint instruction */
#define T_SYSCALL 5 /* system call (kcall) */
#define T_ARITHTRAP 6 /* arithmetic trap */
#define T_ASTFLT 7 /* system forced exception */
#define T_SEGFLT 8 /* segmentation (limit) fault */
#define T_PROTFLT 9 /* protection fault */
#define T_TRCTRAP 10 /* trace trap */
#define T_PAGEFLT 12 /* page fault */
#define T_TABLEFLT 13 /* page table fault */
#define T_ALIGNFLT 14 /* alignment fault */
#define T_KSPNOTVAL 15 /* kernel stack pointer not valid */
#define T_BUSERR 16 /* bus error */
#define T_KDBTRAP 17 /* kernel debugger trap */
#define T_DIVIDE 18 /* integer divide fault */
#define T_NMI 19 /* non-maskable trap */
#define T_OFLOW 20 /* overflow trap */
#define T_BOUND 21 /* bound instruction fault */
#define T_DNA 22 /* device not available fault */
#define T_DOUBLEFLT 23 /* double fault */
#define T_FPOPFLT 24 /* fp coprocessor operand fetch fault */
#define T_TSSFLT 25 /* invalid tss fault */
#define T_SEGNPFLT 26 /* segment not present fault */
#define T_STKFLT 27 /* stack fault */
#define T_RESERVED 28 /* reserved fault base */
/* definitions for <sys/signal.h> */
#define ILL_RESAD_FAULT T_RESADFLT
#define ILL_PRIVIN_FAULT T_PRIVINFLT
#define ILL_RESOP_FAULT T_RESOPFLT
#define ILL_ALIGN_FAULT T_ALIGNFLT
#define ILL_FPOP_FAULT T_FPOPFLT /* coprocessor operand fault */
/* codes for SIGFPE/ARITHTRAP */
#define FPE_INTOVF_TRAP 0x1 /* integer overflow */
#define FPE_INTDIV_TRAP 0x2 /* integer divide by zero */
#define FPE_FLTDIV_TRAP 0x3 /* floating/decimal divide by zero */
#define FPE_FLTOVF_TRAP 0x4 /* floating overflow */
#define FPE_FLTUND_TRAP 0x5 /* floating underflow */
#define FPE_FPU_NP_TRAP 0x6 /* floating point unit not present */
#define FPE_SUBRNG_TRAP 0x7 /* subrange out of bounds */
/* codes for SIGBUS */
#define BUS_PAGE_FAULT T_PAGEFLT /* page fault protection base */
#define BUS_SEGNP_FAULT T_SEGNPFLT /* segment not present */
#define BUS_STK_FAULT T_STKFLT /* stack segment */
#define BUS_SEGM_FAULT T_RESERVED /* segment protection base */
/* Trap's coming from user mode */
#define T_USER 0x100
+78
View File
@@ -0,0 +1,78 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tss.h 5.4 (Berkeley) 1/18/91
*/
/*
* Intel 386 Context Data Type
*/
struct i386tss {
int tss_link; /* actually 16 bits: top 16 bits must be zero */
int tss_esp0; /* kernel stack pointer priviledge level 0 */
#define tss_ksp tss_esp0
int tss_ss0; /* actually 16 bits: top 16 bits must be zero */
int tss_esp1; /* kernel stack pointer priviledge level 1 */
int tss_ss1; /* actually 16 bits: top 16 bits must be zero */
int tss_esp2; /* kernel stack pointer priviledge level 2 */
int tss_ss2; /* actually 16 bits: top 16 bits must be zero */
/* struct ptd *tss_cr3; /* page table directory */
int tss_cr3; /* page table directory */
#define tss_ptd tss_cr3
int tss_eip; /* program counter */
#define tss_pc tss_eip
int tss_eflags; /* program status longword */
#define tss_psl tss_eflags
int tss_eax;
int tss_ecx;
int tss_edx;
int tss_ebx;
int tss_esp; /* user stack pointer */
#define tss_usp tss_esp
int tss_ebp; /* user frame pointer */
#define tss_fp tss_ebp
int tss_esi;
int tss_edi;
int tss_es; /* actually 16 bits: top 16 bits must be zero */
int tss_cs; /* actually 16 bits: top 16 bits must be zero */
int tss_ss; /* actually 16 bits: top 16 bits must be zero */
int tss_ds; /* actually 16 bits: top 16 bits must be zero */
int tss_fs; /* actually 16 bits: top 16 bits must be zero */
int tss_gs; /* actually 16 bits: top 16 bits must be zero */
int tss_ldt; /* actually 16 bits: top 16 bits must be zero */
int tss_ioopt; /* options & io offset bitmap: currently zero */
/* XXX unimplemented .. i/o permission bitmap */
};
+256
View File
@@ -0,0 +1,256 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)vmparam.h 5.9 (Berkeley) 5/12/91
*/
/*
* Machine dependent constants for 386.
*/
/*
* Virtual address space arrangement. On 386, both user and kernel
* share the address space, not unlike the vax.
* USRTEXT is the start of the user text/data space, while USRSTACK
* is the top (end) of the user stack. Immediately above the user stack
* resides the user structure, which is UPAGES long and contains the
* kernel stack.
*
* Immediately after the user structure is the page table map, and then
* kernal address space.
*/
#define USRTEXT 0
#define USRSTACK 0xFDBFE000
#define BTOPUSRSTACK (0xFDC00-(UPAGES)) /* btop(USRSTACK) */
#define LOWPAGES 0
#define HIGHPAGES UPAGES
/*
* Virtual memory related constants, all in bytes
*/
#define MAXTSIZ (6*1024*1024) /* max text size */
#ifndef DFLDSIZ
#define DFLDSIZ (6*1024*1024) /* initial data size limit */
#endif
#ifndef MAXDSIZ
#define MAXDSIZ (32*1024*1024) /* max data size */
#endif
#ifndef DFLSSIZ
#define DFLSSIZ (512*1024) /* initial stack size limit */
#endif
#ifndef MAXSSIZ
#define MAXSSIZ MAXDSIZ /* max stack size */
#endif
/*
* Default sizes of swap allocation chunks (see dmap.h).
* The actual values may be changed in vminit() based on MAXDSIZ.
* With MAXDSIZ of 16Mb and NDMAP of 38, dmmax will be 1024.
*/
#define DMMIN 32 /* smallest swap allocation */
#define DMMAX 4096 /* largest potential swap allocation */
#define DMTEXT 1024 /* swap allocation for text */
/*
* Sizes of the system and user portions of the system page table.
*/
#define SYSPTSIZE (2*NPTEPG)
#define USRPTSIZE (2*NPTEPG)
/*
* Size of User Raw I/O map
*/
#define USRIOSIZE 300
/*
* The size of the clock loop.
*/
#define LOOPPAGES (maxfree - firstfree)
/*
* The time for a process to be blocked before being very swappable.
* This is a number of seconds which the system takes as being a non-trivial
* amount of real time. You probably shouldn't change this;
* it is used in subtle ways (fractions and multiples of it are, that is, like
* half of a ``long time'', almost a long time, etc.)
* It is related to human patience and other factors which don't really
* change over time.
*/
#define MAXSLP 20
/*
* A swapped in process is given a small amount of core without being bothered
* by the page replacement algorithm. Basically this says that if you are
* swapped in you deserve some resources. We protect the last SAFERSS
* pages against paging and will just swap you out rather than paging you.
* Note that each process has at least UPAGES+CLSIZE pages which are not
* paged anyways (this is currently 8+2=10 pages or 5k bytes), so this
* number just means a swapped in process is given around 25k bytes.
* Just for fun: current memory prices are 4600$ a megabyte on VAX (4/22/81),
* so we loan each swapped in process memory worth 100$, or just admit
* that we don't consider it worthwhile and swap it out to disk which costs
* $30/mb or about $0.75.
* { wfj 6/16/89: Retail AT memory expansion $800/megabyte, loan of $17
* on disk costing $7/mb or $0.18 (in memory still 100:1 in cost!) }
*/
#define SAFERSS 8 /* nominal ``small'' resident set size
protected against replacement */
/*
* DISKRPM is used to estimate the number of paging i/o operations
* which one can expect from a single disk controller.
*/
#define DISKRPM 60
/*
* Klustering constants. Klustering is the gathering
* of pages together for pagein/pageout, while clustering
* is the treatment of hardware page size as though it were
* larger than it really is.
*
* KLMAX gives maximum cluster size in CLSIZE page (cluster-page)
* units. Note that KLMAX*CLSIZE must be <= DMMIN in dmap.h.
*/
#define KLMAX (4/CLSIZE)
#define KLSEQL (2/CLSIZE) /* in klust if vadvise(VA_SEQL) */
#define KLIN (4/CLSIZE) /* default data/stack in klust */
#define KLTXT (4/CLSIZE) /* default text in klust */
#define KLOUT (4/CLSIZE)
/*
* KLSDIST is the advance or retard of the fifo reclaim for sequential
* processes data space.
*/
#define KLSDIST 3 /* klusters advance/retard for seq. fifo */
/*
* Paging thresholds (see vm_sched.c).
* Strategy of 1/19/85:
* lotsfree is 512k bytes, but at most 1/4 of memory
* desfree is 200k bytes, but at most 1/8 of memory
* minfree is 64k bytes, but at most 1/2 of desfree
*/
#define LOTSFREE (512 * 1024)
#define LOTSFREEFRACT 4
#define DESFREE (200 * 1024)
#define DESFREEFRACT 8
#define MINFREE (64 * 1024)
#define MINFREEFRACT 2
/*
* There are two clock hands, initially separated by HANDSPREAD bytes
* (but at most all of user memory). The amount of time to reclaim
* a page once the pageout process examines it increases with this
* distance and decreases as the scan rate rises.
*/
#define HANDSPREAD (2 * 1024 * 1024)
/*
* The number of times per second to recompute the desired paging rate
* and poke the pagedaemon.
*/
#define RATETOSCHEDPAGING 4
/*
* Believed threshold (in megabytes) for which interleaved
* swapping area is desirable.
*/
#define LOTSOFMEM 2
#define mapin(pte, v, pfnum, prot) \
{(*(int *)(pte) = ((pfnum)<<PGSHIFT) | (prot)) ; }
/*
* Mach derived constants
*/
/* user/kernel map constants */
#define VM_MIN_ADDRESS ((vm_offset_t)0)
#define VM_MAXUSER_ADDRESS ((vm_offset_t)0xFDBFE000)
#define UPT_MIN_ADDRESS ((vm_offset_t)0xFDC00000)
#define UPT_MAX_ADDRESS ((vm_offset_t)0xFDFF7000)
#define VM_MAX_ADDRESS UPT_MAX_ADDRESS
#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)0xFDFF7000)
#define UPDT VM_MIN_KERNEL_ADDRESS
#define KPT_MIN_ADDRESS ((vm_offset_t)0xFDFF8000)
#define KPT_MAX_ADDRESS ((vm_offset_t)0xFDFFF000)
#define VM_MAX_KERNEL_ADDRESS ((vm_offset_t)0xFF7FF000)
/* virtual sizes (bytes) for various kernel submaps */
#define VM_MBUF_SIZE (NMBCLUSTERS*MCLBYTES)
#define VM_KMEM_SIZE (NKMEMCLUSTERS*CLBYTES)
#define VM_PHYS_SIZE (USRIOSIZE*CLBYTES)
/* # of kernel PT pages (initial only, can grow dynamically) */
#define VM_KERNEL_PT_PAGES ((vm_size_t)2) /* XXX: SYSPTSIZE */
/* pcb base */
#define pcbb(p) ((u_int)(p)->p_addr)
/*
* Flush MMU TLB
*/
#ifndef I386_CR3PAT
#define I386_CR3PAT 0x0
#endif
#ifdef notyet
#define _cr3() ({u_long rtn; \
asm (" movl %%cr3,%%eax; movl %%eax,%0 " \
: "=g" (rtn) \
: \
: "ax"); \
rtn; \
})
#define load_cr3(s) ({ u_long val; \
val = (s) | I386_CR3PAT; \
asm ("movl %0,%%eax; movl %%eax,%%cr3" \
: \
: "g" (val) \
: "ax"); \
})
#define tlbflush() ({ u_long val; \
val = u.u_pcb.pcb_ptd | I386_CR3PAT; \
asm ("movl %0,%%eax; movl %%eax,%%cr3" \
: \
: "g" (val) \
: "ax"); \
})
#endif
+271
View File
@@ -0,0 +1,271 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz and Don Ahn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)clock.c 7.2 (Berkeley) 5/12/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 5 00158
* -------------------- ----- ----------------------
*
* 14 Aug 92 Arne Henrik Juul Added code in the kernel to
* allow for DST in the BIOS.
* 17 Jan 93 Bruce Evans Fixed leap year and second
* calculations
* 01 Feb 93 Julian Elischer Added code to for the cpu
* speed independent spinwait()
* function, (used by scsi and others)
* 25 Mar 93 Sean Eric Fagan Add microtimer support using timer 1
* 08 Apr 93 Poul-Henning Kamp/P-HK Fixes, and support for dcfclock
* 26 Apr 93 Bruce Evans Eliminate findspeed, new spinwait
* 26 Apr 93 Rodney W. Grimes I merged in Bruce changes and hope I
* still kept the other fixes... Had to
* add back in findcpuspeed that Bruce
* had removed.
*/
/*
* Primitive clock interrupt routines.
*/
#include "param.h"
#include "systm.h"
#include "time.h"
#include "kernel.h"
#include "machine/segments.h"
#include "i386/isa/icu.h"
#include "i386/isa/isa.h"
#include "i386/isa/rtc.h"
#include "i386/isa/timerreg.h"
#define DAYST 119
#define DAYEN 303
/* X-tals being what they are, it's nice to be able to fudge this one... */
/* Note, the name changed here from XTALSPEED to TIMER_FREQ rgrimes 4/26/93 */
#ifndef TIMER_FREQ
#define TIMER_FREQ 1193182 /* XXX - should be in isa.h */
#endif
startrtclock() {
int s;
findcpuspeed(); /* use the clock (while it's free)
to find the cpu speed */
/* initialize 8253 clock */
outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
/* Correct rounding will buy us a better precision in timekeeping */
outb (IO_TIMER1, (TIMER_FREQ+hz/2)/hz);
outb (IO_TIMER1, ((TIMER_FREQ+hz/2)/hz)/256);
/* initialize brain-dead battery powered clock */
outb (IO_RTC, RTC_STATUSA);
outb (IO_RTC+1, 0x26);
outb (IO_RTC, RTC_STATUSB);
outb (IO_RTC+1, 2);
outb (IO_RTC, RTC_DIAG);
if (s = inb (IO_RTC+1))
printf("RTC BIOS diagnostic error %b\n", s, RTCDG_BITS);
outb (IO_RTC, RTC_DIAG);
outb (IO_RTC+1, 0);
}
unsigned int delaycount; /* calibrated loop variable (1 millisecond) */
#define FIRST_GUESS 0x2000
findcpuspeed()
{
unsigned char low;
unsigned int remainder;
/* Put counter in count down mode */
outb(IO_TIMER1+3, 0x34);
outb(IO_TIMER1, 0xff);
outb(IO_TIMER1, 0xff);
delaycount = FIRST_GUESS;
spinwait(1);
/* Read the value left in the counter */
low = inb(IO_TIMER1); /* least siginifcant */
remainder = inb(IO_TIMER1); /* most significant */
remainder = (remainder<<8) + low ;
/* Formula for delaycount is :
* (loopcount * timer clock speed)/ (counter ticks * 1000)
*/
delaycount = (FIRST_GUESS * (TIMER_FREQ/1000)) / (0xffff-remainder);
}
/* convert 2 digit BCD number */
bcd(i)
int i;
{
return ((i/16)*10 + (i%16));
}
/* convert years to seconds (from 1970) */
unsigned long
ytos(y)
int y;
{
int i;
unsigned long ret;
ret = 0;
for(i = 1970; i < y; i++) {
if (i % 4) ret += 365*24*60*60;
else ret += 366*24*60*60;
}
return ret;
}
/* convert months to seconds */
unsigned long
mtos(m,leap)
int m,leap;
{
int i;
unsigned long ret;
ret = 0;
for(i=1;i<m;i++) {
switch(i){
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
ret += 31*24*60*60; break;
case 4: case 6: case 9: case 11:
ret += 30*24*60*60; break;
case 2:
if (leap) ret += 29*24*60*60;
else ret += 28*24*60*60;
}
}
return ret;
}
/*
* Initialize the time of day register, based on the time base which is, e.g.
* from a filesystem.
*/
inittodr(base)
time_t base;
{
unsigned long sec;
int leap,day_week,t,yd;
int sa,s;
/* do we have a realtime clock present? (otherwise we loop below) */
sa = rtcin(RTC_STATUSA);
if (sa == 0xff || sa == 0) return;
/* ready for a read? */
while ((sa&RTCSA_TUP) == RTCSA_TUP)
sa = rtcin(RTC_STATUSA);
sec = bcd(rtcin(RTC_YEAR)) + 1900;
if (sec < 1970)
sec += 100;
leap = !(sec % 4); sec = ytos(sec); /* year */
yd = mtos(bcd(rtcin(RTC_MONTH)),leap); sec += yd; /* month */
t = (bcd(rtcin(RTC_DAY))-1) * 24*60*60; sec += t; yd += t; /* date */
day_week = rtcin(RTC_WDAY); /* day */
sec += bcd(rtcin(RTC_HRS)) * 60*60; /* hour */
sec += bcd(rtcin(RTC_MIN)) * 60; /* minutes */
sec += bcd(rtcin(RTC_SEC)); /* seconds */
/* XXX off by one? Need to calculate DST on SUNDAY */
/* Perhaps we should have the RTC hold GMT time to save */
/* us the bother of converting. */
yd = yd / (24*60*60);
if ((yd >= DAYST) && ( yd <= DAYEN)) {
sec -= 60*60;
}
sec += tz.tz_minuteswest * 60;
time.tv_sec = sec;
}
#ifdef garbage
/*
* Initialze the time of day register, based on the time base which is, e.g.
* from a filesystem.
*/
test_inittodr(base)
time_t base;
{
outb(IO_RTC,9); /* year */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,8); /* month */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,7); /* day */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,4); /* hour */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,2); /* minutes */
printf("%d ",bcd(inb(IO_RTC+1)));
outb(IO_RTC,0); /* seconds */
printf("%d\n",bcd(inb(IO_RTC+1)));
time.tv_sec = base;
}
#endif
/*
* Restart the clock.
*/
resettodr()
{
}
/*
* Wire clock interrupt in.
*/
#define V(s) __CONCAT(V, s)
extern V(clk)();
enablertclock() {
setidt(ICU_OFFSET+0, &V(clk), SDT_SYS386IGT, SEL_KPL);
INTREN(IRQ0);
}
/*
* Delay for some number of milliseconds.
*/
void
spinwait(millisecs)
int millisecs;
{
DELAY(1000 * millisecs);
}
+109
View File
@@ -0,0 +1,109 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)icu.h 5.6 (Berkeley) 5/9/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00158
* -------------------- ----- ----------------------
*
* 25 Apr 93 Bruce Evans New fast interrupt code (intr-0.1)
*/
/*
* AT/386 Interrupt Control constants
* W. Jolitz 8/89
*/
#ifndef __ICU__
#define __ICU__
#ifndef LOCORE
/*
* Interrupt "level" mechanism variables, masks, and macros
*/
extern unsigned imen; /* interrupt mask enable */
extern unsigned cpl; /* current priority level mask */
extern unsigned highmask; /* group of interrupts masked with splhigh() */
extern unsigned ttymask; /* group of interrupts masked with spltty() */
extern unsigned biomask; /* group of interrupts masked with splbio() */
extern unsigned netmask; /* group of interrupts masked with splimp() */
#define INTREN(s) (imen &= ~(s), SET_ICUS())
#define INTRDIS(s) (imen |= (s), SET_ICUS())
#define INTRMASK(msk,s) (msk |= (s))
#if 0
#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IU_ICU2 + 1, imen >> 8))
#else
/*
* XXX - IO_ICU* are defined in isa.h, not icu.h, and nothing much bothers to
* include isa.h, while too many things include icu.h.
*/
#define SET_ICUS() (outb(0x21, imen), outb(0xa1, imen >> 8))
#endif
#endif
/*
* Interrupt enable bits -- in order of priority
*/
#define IRQ0 0x0001 /* highest priority - timer */
#define IRQ1 0x0002
#define IRQ_SLAVE 0x0004
#define IRQ8 0x0100
#define IRQ9 0x0200
#define IRQ2 IRQ9
#define IRQ10 0x0400
#define IRQ11 0x0800
#define IRQ12 0x1000
#define IRQ13 0x2000
#define IRQ14 0x4000
#define IRQ15 0x8000
#define IRQ3 0x0008
#define IRQ4 0x0010
#define IRQ5 0x0020
#define IRQ6 0x0040
#define IRQ7 0x0080 /* lowest - parallel printer */
/*
* Interrupt Control offset into Interrupt descriptor table (IDT)
*/
#define ICU_OFFSET 32 /* 0-31 are processor exceptions */
#define ICU_LEN 16 /* 32-47 are ISA interrupts */
#endif __ICU__
+766
View File
@@ -0,0 +1,766 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)isa.c 7.2 (Berkeley) 5/13/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 4 00163
* -------------------- ----- ----------------------
*
* 18 Aug 92 Frank Maclachlan *See comments below
* 25 Mar 93 Rodney W. Grimes Added counter for stray interrupt,
* turned on logging of stray interrupts,
* Now prints maddr, msize, and flags
* after finding a device.
* 26 Apr 93 Bruce Evans New intr-0.1 code
* Rodney W. Grimes Only print io address if id_alive != -1
* 17 May 93 Rodney W. Grimes renamed stray interrupt counters to
* work with new intr-0.1 code.
* Enabled printf for interrupt masks to
* aid in bug reports.
* 27 May 93 Guido van Rooij New routine add find_isa_dev
*/
static char rcsid[] = "$Header: /usr/src/sys.386bsd/i386/isa/RCS/isa.c,v 1.2 92/01/21 14:34:23 william Exp Locker: root $";
/*
* code to manage AT bus
*
* 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com):
* Fixed uninitialized variable problem and added code to deal
* with DMA page boundaries in isa_dmarangecheck(). Fixed word
* mode DMA count compution and reorganized DMA setup code in
* isa_dmastart()
*/
#include "param.h"
#include "systm.h"
#include "conf.h"
#include "file.h"
#include "buf.h"
#include "uio.h"
#include "syslog.h"
#include "malloc.h"
#include "rlist.h"
#include "machine/segments.h"
#include "vm/vm.h"
#include "i386/isa/isa_device.h"
#include "i386/isa/isa.h"
#include "i386/isa/icu.h"
#include "i386/isa/ic/i8237.h"
#include "i386/isa/ic/i8042.h"
/*
** Register definitions for DMA controller 1 (channels 0..3):
*/
#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */
#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */
#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */
#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */
/*
** Register definitions for DMA controller 2 (channels 4..7):
*/
#define DMA2_CHN(c) (IO_DMA1 + 2*(2*(c))) /* addr reg for channel c */
#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */
#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */
#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */
int config_isadev __P((struct isa_device *, u_int *));
#ifdef notyet
struct rlist *isa_iomem;
/*
* Configure all ISA devices
*/
isa_configure() {
struct isa_device *dvp;
struct isa_driver *dp;
splhigh();
INTREN(IRQ_SLAVE);
/*rlist_free(&isa_iomem, 0xa0000, 0xfffff);*/
for (dvp = isa_devtab_tty; dvp; dvp++)
(void) config_isadev(dvp, &ttymask);
for (dvp = isa_devtab_bio; dvp; dvp++)
(void) config_isadev(dvp, &biomask);
for (dvp = isa_devtab_net; dvp; dvp++)
(void) config_isadev(dvp, &netmask);
for (dvp = isa_devtab_null; dvp; dvp++)
(void) config_isadev(dvp, (u_int *) NULL);
#include "sl.h"
#if NSL > 0
netmask |= ttymask;
ttymask |= netmask;
#endif
/* printf("biomask %x ttymask %x netmask %x\n", biomask, ttymask, netmask); */
splnone();
}
/*
* Configure an ISA device.
*/
config_isadev(isdp, mp)
struct isa_device *isdp;
u_int *mp;
{
struct isa_driver *dp;
static short drqseen, irqseen;
if (dp = isdp->id_driver) {
/* if a device with i/o memory, convert to virtual address */
if (isdp->id_maddr) {
extern unsigned int atdevbase;
isdp->id_maddr -= IOM_BEGIN;
isdp->id_maddr += atdevbase;
}
isdp->id_alive = (*dp->probe)(isdp);
if (isdp->id_alive) {
printf("%s%d at port 0x%x ", dp->name,
isdp->id_unit, isdp->id_iobase);
/* check for conflicts */
if (irqseen & isdp->id_irq) {
printf("INTERRUPT CONFLICT - irq%d\n",
ffs(isdp->id_irq) - 1);
return (0);
}
if (isdp->id_drq != -1
&& (drqseen & (1<<isdp->id_drq))) {
printf("DMA CONFLICT - drq%d\n", isdp->id_drq);
return (0);
}
/* NEED TO CHECK IOMEM CONFLICT HERE */
/* allocate and wire in device */
if(isdp->id_irq) {
int intrno;
intrno = ffs(isdp->id_irq)-1;
printf("irq %d ", intrno);
INTREN(isdp->id_irq);
if(mp)INTRMASK(*mp,isdp->id_irq);
setidt(NRSVIDT + intrno, isdp->id_intr,
SDT_SYS386IGT, SEL_KPL);
irqseen |= isdp->id_irq;
}
if (isdp->id_drq != -1) {
printf("drq %d ", isdp->id_drq);
drqseen |= 1 << isdp->id_drq;
}
(*dp->attach)(isdp);
printf("on isa\n");
}
return (1);
} else return(0);
}
#else /* notyet */
/*
* Configure all ISA devices
*/
isa_configure() {
struct isa_device *dvp;
struct isa_driver *dp;
enable_intr();
splhigh();
INTREN(IRQ_SLAVE);
for (dvp = isa_devtab_tty; config_isadev(dvp,&ttymask); dvp++);
for (dvp = isa_devtab_bio; config_isadev(dvp,&biomask); dvp++);
for (dvp = isa_devtab_net; config_isadev(dvp,&netmask); dvp++);
for (dvp = isa_devtab_null; config_isadev(dvp,(u_int *) NULL); dvp++);
#include "sl.h"
#if NSL > 0
netmask |= ttymask;
ttymask |= netmask;
#endif
/* biomask |= ttymask ; can some tty devices use buffers? */
printf("biomask %x ttymask %x netmask %x\n", biomask, ttymask, netmask);
splnone();
}
/*
* Configure an ISA device.
*/
config_isadev(isdp, mp)
struct isa_device *isdp;
u_int *mp;
{
struct isa_driver *dp;
if (dp = isdp->id_driver) {
if (isdp->id_maddr) {
extern u_int atdevbase;
isdp->id_maddr -= 0xa0000; /* XXX should be a define */
isdp->id_maddr += atdevbase;
}
isdp->id_alive = (*dp->probe)(isdp);
if (isdp->id_alive) {
printf("%s%d", dp->name, isdp->id_unit);
/*
* The attach should really be after all the printf's
* but until all the drivers are fixed do it here.
* There is a comment below that shows where this
* really belongs. Rod Grimes 04/10/93
*/
(*dp->attach)(isdp);
/*
* Only print the I/O address range if id_alive != -1
* Right now this is a temporary fix just for the new
* NPX code so that if it finds a 486 that can use trap
* 16 it will not report I/O addresses.
* Rod Grimes 04/26/94
*/
if (isdp->id_alive != -1) {
printf(" at 0x%x", isdp->id_iobase);
if ((isdp->id_iobase + isdp->id_alive - 1) !=
isdp->id_iobase)
printf("-0x%x",
isdp->id_iobase +
isdp->id_alive - 1);
}
if(isdp->id_irq)
printf(" irq %d", ffs(isdp->id_irq)-1);
if (isdp->id_drq != -1)
printf(" drq %d", isdp->id_drq);
if (isdp->id_maddr != 0)
printf(" maddr 0x%x", kvtop(isdp->id_maddr));
if (isdp->id_msize != 0)
printf(" msize %d", isdp->id_msize);
if (isdp->id_flags != 0)
printf(" flags 0x%x", isdp->id_flags);
printf(" on isa\n");
/* This is the place the attach should be done! */
if(isdp->id_irq) {
int intrno;
intrno = ffs(isdp->id_irq)-1;
setidt(ICU_OFFSET+intrno, isdp->id_intr,
SDT_SYS386IGT, SEL_KPL);
if(mp)
INTRMASK(*mp,isdp->id_irq);
INTREN(isdp->id_irq);
}
}
return (1);
} else return(0);
}
#endif /* (!) notyet */
#define IDTVEC(name) __CONCAT(X,name)
/* default interrupt vector table entries */
extern IDTVEC(intr0), IDTVEC(intr1), IDTVEC(intr2), IDTVEC(intr3),
IDTVEC(intr4), IDTVEC(intr5), IDTVEC(intr6), IDTVEC(intr7),
IDTVEC(intr8), IDTVEC(intr9), IDTVEC(intr10), IDTVEC(intr11),
IDTVEC(intr12), IDTVEC(intr13), IDTVEC(intr14), IDTVEC(intr15);
static *defvec[16] = {
&IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
&IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
&IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
&IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) };
/* out of range default interrupt vector gate entry */
extern IDTVEC(intrdefault);
/*
* Fill in default interrupt table (in case of spuruious interrupt
* during configuration of kernel, setup interrupt control unit
*/
isa_defaultirq() {
int i;
/* icu vectors */
for (i = NRSVIDT ; i < NRSVIDT+ICU_LEN ; i++)
setidt(i, defvec[i], SDT_SYS386IGT, SEL_KPL);
/* out of range vectors */
for (i = NRSVIDT; i < NIDT; i++)
setidt(i, &IDTVEC(intrdefault), SDT_SYS386IGT, SEL_KPL);
/* initialize 8259's */
outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
outb(IO_ICU1+1, NRSVIDT); /* starting at this vector index */
outb(IO_ICU1+1, 1<<2); /* slave on line 2 */
#ifdef AUTO_EOI_1
outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
#else
outb(IO_ICU1+1, 1); /* 8086 mode */
#endif
outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
outb(IO_ICU1, 0x0a); /* default to IRR on read */
outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
outb(IO_ICU2+1, NRSVIDT+8); /* staring at this vector index */
outb(IO_ICU2+1,2); /* my slave id is 2 */
#ifdef AUTO_EOI_2
outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
#else
outb(IO_ICU2+1,1); /* 8086 mode */
#endif
outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
outb(IO_ICU2, 0x0a); /* default to IRR on read */
}
/* region of physical memory known to be contiguous */
vm_offset_t isaphysmem;
static caddr_t dma_bounce[8]; /* XXX */
static char bounced[8]; /* XXX */
#define MAXDMASZ 512 /* XXX */
/* high byte of address is stored in this port for i-th dma channel */
static short dmapageport[8] =
{ 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
/*
* isa_dmacascade(): program 8237 DMA controller channel to accept
* external dma control by a board.
*/
void isa_dmacascade(unsigned chan)
{
if (chan > 7)
panic("isa_dmacascade: impossible request");
/* set dma channel mode, and set dma channel mode */
if ((chan & 4) == 0) {
outb(DMA1_MODE, DMA37MD_CASCADE | chan);
outb(DMA1_SMSK, chan);
} else {
outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3));
outb(DMA2_SMSK, chan & 3);
}
}
/*
* isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
* problems by using a bounce buffer.
*/
void isa_dmastart(int flags, caddr_t addr, unsigned nbytes, unsigned chan)
{ vm_offset_t phys;
int waport;
caddr_t newaddr;
if ( chan > 7
|| (chan < 4 && nbytes > (1<<16))
|| (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1)))
panic("isa_dmastart: impossible request");
if (isa_dmarangecheck(addr, nbytes, chan)) {
if (dma_bounce[chan] == 0)
dma_bounce[chan] =
/*(caddr_t)malloc(MAXDMASZ, M_TEMP, M_WAITOK);*/
(caddr_t) isaphysmem + NBPG*chan;
bounced[chan] = 1;
newaddr = dma_bounce[chan];
*(int *) newaddr = 0; /* XXX */
/* copy bounce buffer on write */
if (!(flags & B_READ))
bcopy(addr, newaddr, nbytes);
addr = newaddr;
}
/* translate to physical */
phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr);
if ((chan & 4) == 0) {
/*
* Program one of DMA channels 0..3. These are
* byte mode channels.
*/
/* set dma channel mode, and reset address ff */
if (flags & B_READ)
outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan);
else
outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan);
outb(DMA1_FFC, 0);
/* send start address */
waport = DMA1_CHN(chan);
outb(waport, phys);
outb(waport, phys>>8);
outb(dmapageport[chan], phys>>16);
/* send count */
outb(waport + 1, --nbytes);
outb(waport + 1, nbytes>>8);
/* unmask channel */
outb(DMA1_SMSK, chan);
} else {
/*
* Program one of DMA channels 4..7. These are
* word mode channels.
*/
/* set dma channel mode, and reset address ff */
if (flags & B_READ)
outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3));
else
outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3));
outb(DMA2_FFC, 0);
/* send start address */
waport = DMA2_CHN(chan - 4);
outb(waport, phys>>1);
outb(waport, phys>>9);
outb(dmapageport[chan], phys>>16);
/* send count */
nbytes >>= 1;
outb(waport + 2, --nbytes);
outb(waport + 2, nbytes>>8);
/* unmask channel */
outb(DMA2_SMSK, chan & 3);
}
}
void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)
{
/* copy bounce buffer on read */
/*if ((flags & (B_PHYS|B_READ)) == (B_PHYS|B_READ))*/
if (bounced[chan]) {
bcopy(dma_bounce[chan], addr, nbytes);
bounced[chan] = 0;
}
}
/*
* Check for problems with the address range of a DMA transfer
* (non-contiguous physical pages, outside of bus address space,
* crossing DMA page boundaries).
* Return true if special handling needed.
*/
isa_dmarangecheck(caddr_t va, unsigned length, unsigned chan) {
vm_offset_t phys, priorpage = 0, endva;
u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1);
endva = (vm_offset_t)round_page(va + length);
for (; va < (caddr_t) endva ; va += NBPG) {
phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va));
#define ISARAM_END RAM_END
if (phys == 0)
panic("isa_dmacheck: no physical page present");
if (phys > ISARAM_END)
return (1);
if (priorpage) {
if (priorpage + NBPG != phys)
return (1);
/* check if crossing a DMA page boundary */
if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk)
return (1);
}
priorpage = phys;
}
return (0);
}
/* head of queue waiting for physmem to become available */
struct buf isa_physmemq;
/* blocked waiting for resource to become free for exclusive use */
static isaphysmemflag;
/* if waited for and call requested when free (B_CALL) */
static void (*isaphysmemunblock)(); /* needs to be a list */
/*
* Allocate contiguous physical memory for transfer, returning
* a *virtual* address to region. May block waiting for resource.
* (assumed to be called at splbio())
*/
caddr_t
isa_allocphysmem(caddr_t va, unsigned length, void (*func)()) {
isaphysmemunblock = func;
while (isaphysmemflag & B_BUSY) {
isaphysmemflag |= B_WANTED;
sleep(&isaphysmemflag, PRIBIO);
}
isaphysmemflag |= B_BUSY;
return((caddr_t)isaphysmem);
}
/*
* Free contiguous physical memory used for transfer.
* (assumed to be called at splbio())
*/
void
isa_freephysmem(caddr_t va, unsigned length) {
isaphysmemflag &= ~B_BUSY;
if (isaphysmemflag & B_WANTED) {
isaphysmemflag &= B_WANTED;
wakeup(&isaphysmemflag);
if (isaphysmemunblock)
(*isaphysmemunblock)();
}
}
/*
* Handle a NMI, possibly a machine check.
* return true to panic system, false to ignore.
*/
isa_nmi(cd) {
log(LOG_CRIT, "\nNMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70));
return(0);
}
/*
* Caught a stray interrupt, notify
*/
isa_strayintr(d) {
/* DON'T BOTHER FOR NOW! */
/* for some reason, we get bursts of intr #7, even if not enabled! */
/*
* Well the reason you got bursts of intr #7 is because someone
* raised an interrupt line and dropped it before the 8259 could
* prioritize it. This is documented in the intel data book. This
* means you have BAD hardware! I have changed this so that only
* the first 5 get logged, then it quits logging them, and puts
* out a special message. rgrimes 3/25/1993
*/
extern u_long intrcnt_stray;
intrcnt_stray++;
if (intrcnt_stray <= 5)
log(LOG_ERR,"ISA strayintr %x\n", d);
if (intrcnt_stray == 5)
log(LOG_CRIT,"Too many ISA strayintr not logging any more\n");
}
/*
* Wait "n" microseconds.
* Relies on timer 1 counting down from (TIMER_FREQ / hz) at
* (2 * TIMER_FREQ) Hz.
* Note: timer had better have been programmed before this is first used!
* (The standard programming causes the timer to generate a square wave and
* the counter is decremented twice every cycle.)
*/
#define CF (2 * TIMER_FREQ)
#define TIMER_FREQ 1193182 /* XXX - should be elsewhere */
extern int hz; /* XXX - should be elsewhere */
int DELAY(n)
int n;
{
int counter_limit;
int prev_tick;
int tick;
int ticks_left;
int sec;
int usec;
#ifdef DELAYDEBUG
int getit_calls = 1;
int n1;
static int state = 0;
if (state == 0) {
state = 1;
for (n1 = 1; n1 <= 10000000; n1 *= 10)
DELAY(n1);
state = 2;
}
if (state == 1)
printf("DELAY(%d)...", n);
#endif
/*
* Read the counter first, so that the rest of the setup overhead is
* counted. Guess the initial overhead is 20 usec (on most systems it
* takes about 1.5 usec for each of the i/o's in getit(). The loop
* takes about 6 usec on a 486/33 and 13 usec on a 386/20. The
* multiplications and divisions to scale the count take a while).
*/
prev_tick = getit(0, 0);
n -= 20;
/*
* Calculate (n * (CF / 1e6)) without using floating point and without
* any avoidable overflows.
*/
sec = n / 1000000;
usec = n - sec * 1000000;
ticks_left = sec * CF
+ usec * (CF / 1000000)
+ usec * ((CF % 1000000) / 1000) / 1000
+ usec * (CF % 1000) / 1000000;
counter_limit = TIMER_FREQ / hz;
while (ticks_left > 0) {
tick = getit(0, 0);
#ifdef DELAYDEBUG
++getit_calls;
#endif
if (tick > prev_tick)
ticks_left -= prev_tick - (tick - counter_limit);
else
ticks_left -= prev_tick - tick;
prev_tick = tick;
}
#ifdef DELAYDEBUG
if (state == 1)
printf(" %d calls to getit() at %d usec each\n",
getit_calls, (n + 5) / getit_calls);
#endif
}
getit(unit, timer) {
int high;
int low;
/*
* XXX - isa.h defines bogus timers. There's no such timer as
* IO_TIMER_2 = 0x48. There's a timer in the CMOS RAM chip but
* its interface is quite different. Neither timer is an 8252.
* We actually only call this with unit = 0 and timer = 0. It
* could be static...
*/
/*
* Protect ourself against interrupts.
* XXX - sysbeep() and sysbeepstop() need protection.
*/
disable_intr();
/*
* Latch the count for 'timer' (cc00xxxx, c = counter, x = any).
*/
outb(IO_TIMER1 + 3, timer << 6);
low = inb(IO_TIMER1 + timer);
high = inb(IO_TIMER1 + timer);
enable_intr();
return ((high << 8) | low);
}
static beeping;
static
sysbeepstop(f)
{
/* disable counter 2 */
outb(0x61, inb(0x61) & 0xFC);
if (f)
timeout(sysbeepstop, 0, f);
else
beeping = 0;
}
void sysbeep(int pitch, int period)
{
outb(0x61, inb(0x61) | 3); /* enable counter 2 */
/*
* XXX - move timer stuff to clock.c.
* Program counter 2:
* ccaammmb, c counter, a = access, m = mode, b = BCD
* 1011x110, 11 for aa = LSB then MSB, x11 for mmm = square wave.
*/
outb(0x43, 0xb6); /* set command for counter 2, 2 byte write */
outb(0x42, pitch);
outb(0x42, (pitch>>8));
if (!beeping) {
beeping = period;
timeout(sysbeepstop, period/2, period);
}
}
/*
* Pass command to keyboard controller (8042)
*/
unsigned kbc_8042cmd(val) {
while (inb(KBSTATP)&KBS_IBF);
if (val) outb(KBCMDP, val);
while (inb(KBSTATP)&KBS_IBF);
return (inb(KBDATAP));
}
/*
* find an ISA device in a given isa_devtab_* table, given
* the table to search, the expected id_driver entry, and the unit number.
*
* this function is defined in isa_device.h, and this location is debatable;
* i put it there because it's useless w/o, and directly operates on
* the other stuff in that file.
*
*/
struct isa_device *find_isadev(table, driverp, unit)
struct isa_device *table;
struct isa_driver *driverp;
int unit;
{
if (driverp == NULL) /* sanity check */
return NULL;
while ((table->id_driver != driverp) || (table->id_unit != unit)) {
if (table->id_driver == 0)
return NULL;
table++;
}
return table;
}
/*
* Return nonzero if a (masked) irq is pending for a given device.
*/
int
isa_irq_pending(dvp)
struct isa_device *dvp;
{
unsigned id_irq;
id_irq = (unsigned short) dvp->id_irq; /* XXX silly type in struct */
if (id_irq & 0xff)
return (inb(IO_ICU1) & id_irq);
return (inb(IO_ICU2) & (id_irq >> 8));
}
+188
View File
@@ -0,0 +1,188 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)isa.h 5.7 (Berkeley) 5/9/91
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 3 00158
* -------------------- ----- ----------------------
*
* 15 Feb 93 Julian Elischer Added entries for some scsi adapters
* 06 Apr 93 Rodney W. Grimes Added com3 and com4, added IO_ISASIZES
* section
* 26 Apr 93 Bruce Evans Support for intr-0.1
*/
/*
* ISA Bus conventions
*/
#ifndef LOCORE
#include <sys/cdefs.h>
unsigned char rtcin __P((int));
extern unsigned int atdevbase; /* offset in virtual memory of ISA io mem */
void sysbeep __P((int, int));
unsigned kbd_8042cmd __P((int));
struct isa_device;
int isa_irq_pending __P((struct isa_device *dvp));
#endif
/*
* Input / Output Port Assignments
*/
#ifndef IO_BEGIN
#define IO_ISABEGIN 0x000 /* 0x000 - Beginning of I/O Registers */
/* CPU Board */
#define IO_DMA1 0x000 /* 8237A DMA Controller #1 */
#define IO_ICU1 0x020 /* 8259A Interrupt Controller #1 */
#define IO_TIMER1 0x040 /* 8252 Timer #1 */
#define IO_TIMER2 0x048 /* 8252 Timer #2 */
#define IO_KBD 0x060 /* 8042 Keyboard */
#define IO_RTC 0x070 /* RTC */
#define IO_NMI IO_RTC /* NMI Control */
#define IO_DMAPG 0x080 /* DMA Page Registers */
#define IO_ICU2 0x0A0 /* 8259A Interrupt Controller #2 */
#define IO_DMA2 0x0C0 /* 8237A DMA Controller #2 */
#define IO_NPX 0x0F0 /* Numeric Coprocessor */
/* Cards */
/* 0x100 - 0x16F Open */
#define IO_WD2 0x170 /* Secondary Fixed Disk Controller */
/* 0x178 - 0x1EF Open */
#define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */
#define IO_GAME 0x200 /* Game Controller */
/* 0x208 - 0x277 Open */
#define IO_LPT2 0x278 /* Parallel Port #2 */
/* 0x280 - 0x2E7 Open */
#define IO_COM4 0x2e8 /* COM4 i/o address */
/* 0x2F0 - 0x2F7 Open */
#define IO_COM2 0x2f8 /* COM2 i/o address */
/* 0x300 - 0x32F Open */
#define IO_BT0 0x330 /* bustek 742a default addr. */
#define IO_AHA0 0x330 /* adaptec 1542 default addr. */
#define IO_UHA0 0x330 /* ultrastore 14f default addr. */
#define IO_BT1 0x334 /* bustek 742a default addr. */
#define IO_AHA1 0x334 /* adaptec 1542 default addr. */
/* 0x338 - 0x36F Open */
#define IO_FD2 0x370 /* secondary base i/o address */
#define IO_LPT1 0x378 /* Parallel Port #1 */
/* 0x380 - 0x3AF Open */
#define IO_MDA 0x3B0 /* Monochome Adapter */
#define IO_LPT3 0x3BC /* Monochome Adapter Printer Port */
#define IO_VGA 0x3C0 /* E/VGA Ports */
#define IO_CGA 0x3D0 /* CGA Ports */
/* 0x3E0 - 0x3E7 Open */
#define IO_COM3 0x3e8 /* COM3 i/o address */
#define IO_FD1 0x3f0 /* primary base i/o address */
#define IO_COM1 0x3f8 /* COM1 i/o address */
#define IO_ISAEND 0x3FF /* - 0x3FF End of I/O Registers */
#endif IO_ISABEGIN
/*
* Input / Output Port Sizes - these are from several sources, and tend
* to be the larger of what was found, ie COM ports can be 4, but some
* boards do not fully decode the address, thus 8 ports are used.
*/
#ifndef IO_ISASIZES
#define IO_ISASIZES
#define IO_COMSIZE 8 /* 8250, 16X50 com controllers (4?) */
#define IO_CGASIZE 16 /* CGA controllers */
#define IO_DMASIZE 16 /* 8237 DMA controllers */
#define IO_DPGSIZE 32 /* 74LS612 DMA page reisters */
#define IO_FDCSIZE 8 /* Nec765 floppy controllers */
#define IO_WDCSIZE 8 /* WD compatible disk controllers */
#define IO_GAMSIZE 16 /* AT compatible game controllers */
#define IO_ICUSIZE 16 /* 8259A interrupt controllers */
#define IO_KBDSIZE 16 /* 8042 Keyboard controllers */
#define IO_LPTSIZE 8 /* LPT controllers, some use only 4 */
#define IO_MDASIZE 16 /* Monochrome display controllers */
#define IO_RTCSIZE 16 /* CMOS real time clock, NMI control */
#define IO_TMRSIZE 16 /* 8253 programmable timers */
#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
#define IO_VGASIZE 16 /* VGA controllers */
#endif /* IO_ISASIZES */
/*
* Input / Output Memory Physical Addresses
*/
#ifndef IOM_BEGIN
#define IOM_BEGIN 0x0a0000 /* Start of I/O Memory "hole" */
#define IOM_END 0x100000 /* End of I/O Memory "hole" */
#define IOM_SIZE (IOM_END - IOM_BEGIN)
#endif IOM_BEGIN
/*
* RAM Physical Address Space (ignoring the above mentioned "hole")
*/
#ifndef RAM_BEGIN
#define RAM_BEGIN 0x0000000 /* Start of RAM Memory */
#define RAM_END 0x1000000 /* End of RAM Memory */
#define RAM_SIZE (RAM_END - RAM_BEGIN)
#endif RAM_BEGIN
/*
* Oddball Physical Memory Addresses
*/
#ifndef COMPAQ_RAMRELOC
#define COMPAQ_RAMRELOC 0x80c00000 /* Compaq RAM relocation/diag */
#define COMPAQ_RAMSETUP 0x80c00002 /* Compaq RAM setup */
#define WEITEK_FPU 0xC0000000 /* WTL 2167 */
#define CYRIX_EMC 0xC0000000 /* Cyrix EMC */
#endif COMPAQ_RAMRELOC
+564
View File
@@ -0,0 +1,564 @@
/*-
* Copyright (c) 1990 William Jolitz.
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)npx.c 7.2 (Berkeley) 5/12/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00154
* -------------------- ----- ----------------------
*
* 20 Apr 93 Bruce Evans New npx-0.5 code
* 23 May 93 Rodney W. Grimes Return a special value of -1 from
* the probe code to keep isa_config from
* printing out the I/O address when we
* are using trap 16 handling.
*
*/
static char rcsid[] = "$Header: /usr/bill/working/sys/i386/isa/RCS/npx.c,v 1.2 92/01/21 14:34:27 william Exp $";
#include "npx.h"
#if NNPX > 0
#include "param.h"
#include "systm.h"
#include "conf.h"
#include "file.h"
#include "proc.h"
#include "machine/cpu.h"
#include "machine/pcb.h"
#include "machine/trap.h"
#include "ioctl.h"
#include "machine/specialreg.h"
#include "i386/isa/icu.h"
#include "i386/isa/isa_device.h"
#include "i386/isa/isa.h"
/*
* 387 and 287 Numeric Coprocessor Extension (NPX) Driver.
*/
#ifdef __GNUC__
#define disable_intr() __asm("cli")
#define enable_intr() __asm("sti")
#define fldcw(addr) __asm("fldcw %0" : : "m" (*addr))
#define fnclex() __asm("fnclex")
#define fninit() __asm("fninit")
#define fnsave(addr) __asm("fnsave %0" : "=m" (*addr) : "0" (*addr))
#define fnstcw(addr) __asm("fnstcw %0" : "=m" (*addr) : "0" (*addr))
#define fnstsw(addr) __asm("fnstsw %0" : "=m" (*addr) : "0" (*addr))
#define fp_divide_by_0() __asm("fldz; fld1; fdiv %st,%st(1); fwait")
#define frstor(addr) __asm("frstor %0" : : "m" (*addr))
#define fwait() __asm("fwait")
#define read_eflags() ({u_long ef; \
__asm("pushf; popl %0" : "=a" (ef)); \
ef; })
#define start_emulating() __asm("smsw %%ax; orb %0,%%al; lmsw %%ax" \
: : "n" (CR0_TS) : "ax")
#define stop_emulating() __asm("clts")
#define write_eflags(ef) __asm("pushl %0; popf" : : "a" ((u_long) ef))
#else /* not __GNUC__ */
void disable_intr __P((void));
void enable_intr __P((void));
void fldcw __P((caddr_t addr));
void fnclex __P((void));
void fninit __P((void));
void fnsave __P((caddr_t addr));
void fnstcw __P((caddr_t addr));
void fnstsw __P((caddr_t addr));
void fp_divide_by_0 __P((void));
void frstor __P((caddr_t addr));
void fwait __P((void));
u_long read_eflags __P((void));
void start_emulating __P((void));
void stop_emulating __P((void));
void write_eflags __P((u_long ef));
#endif /* __GNUC__ */
typedef u_char bool_t;
extern struct gate_descriptor idt[];
int npxdna __P((void));
void npxexit __P((struct proc *p));
void npxinit __P((u_int control));
void npxintr __P((struct intrframe frame));
void npxsave __P((struct save87 *addr));
static int npxattach __P((struct isa_device *dvp));
static int npxprobe __P((struct isa_device *dvp));
static int npxprobe1 __P((struct isa_device *dvp));
struct isa_driver npxdriver = {
npxprobe, npxattach, "npx",
};
u_int npx0mask;
struct proc *npxproc;
static bool_t npx_ex16;
static bool_t npx_exists;
static struct gate_descriptor npx_idt_probeintr;
static int npx_intrno;
static volatile u_int npx_intrs_while_probing;
static bool_t npx_irq13;
static volatile u_int npx_traps_while_probing;
/*
* Special interrupt handlers. Someday intr0-intr15 will be used to count
* interrupts. We'll still need a special exception 16 handler. The busy
* latch stuff in probintr() can be moved to npxprobe().
*/
void probeintr(void);
asm
("
.text
_probeintr:
ss
incl _npx_intrs_while_probing
pushl %eax
movb $0x20,%al /* EOI (asm in strings loses cpp features) */
outb %al,$0xa0 /* IO_ICU2 */
outb %al,$0x20 /* IO_ICU1 */
movb $0,%al
outb %al,$0xf0 /* clear BUSY# latch */
popl %eax
iret
");
void probetrap(void);
asm
("
.text
_probetrap:
ss
incl _npx_traps_while_probing
fnclex
iret
");
/*
* Probe routine. Initialize cr0 to give correct behaviour for [f]wait
* whether the device exists or not (XXX should be elsewhere). Set flags
* to tell npxattach() what to do. Modify device struct if npx doesn't
* need to use interrupts. Return 1 if device exists.
*/
static int
npxprobe(dvp)
struct isa_device *dvp;
{
int result;
u_long save_eflags;
u_char save_icu1_mask;
u_char save_icu2_mask;
struct gate_descriptor save_idt_npxintr;
struct gate_descriptor save_idt_npxtrap;
/*
* This routine is now just a wrapper for npxprobe1(), to install
* special npx interrupt and trap handlers, to enable npx interrupts
* and to disable other interrupts. Someday isa_configure() will
* install suitable handlers and run with interrupts enabled so we
* won't need to do so much here.
*/
npx_intrno = NRSVIDT + ffs(dvp->id_irq) - 1;
save_eflags = read_eflags();
disable_intr();
save_icu1_mask = inb(IO_ICU1 + 1);
save_icu2_mask = inb(IO_ICU2 + 1);
save_idt_npxintr = idt[npx_intrno];
save_idt_npxtrap = idt[16];
outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq));
outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8));
setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL);
setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL);
npx_idt_probeintr = idt[npx_intrno];
enable_intr();
result = npxprobe1(dvp);
disable_intr();
outb(IO_ICU1 + 1, save_icu1_mask);
outb(IO_ICU2 + 1, save_icu2_mask);
idt[npx_intrno] = save_idt_npxintr;
idt[16] = save_idt_npxtrap;
write_eflags(save_eflags);
return (result);
}
static int
npxprobe1(dvp)
struct isa_device *dvp;
{
int control;
int status;
#ifdef lint
npxintr();
#endif
/*
* Partially reset the coprocessor, if any. Some BIOS's don't reset
* it after a warm boot.
*/
outb(0xf1, 0); /* full reset on some systems, NOP on others */
outb(0xf0, 0); /* clear BUSY# latch */
/*
* Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
* instructions. We must set the CR0_MP bit and use the CR0_TS
* bit to control the trap, because setting the CR0_EM bit does
* not cause WAIT instructions to trap. It's important to trap
* WAIT instructions - otherwise the "wait" variants of no-wait
* control instructions would degenerate to the "no-wait" variants
* after FP context switches but work correctly otherwise. It's
* particularly important to trap WAITs when there is no NPX -
* otherwise the "wait" variants would always degenerate.
*
* Try setting CR0_NE to get correct error reporting on 486DX's.
* Setting it should fail or do nothing on lesser processors.
*/
load_cr0(rcr0() | CR0_MP | CR0_NE);
/*
* But don't trap while we're probing.
*/
stop_emulating();
/*
* Finish resetting the coprocessor, if any. If there is an error
* pending, then we may get a bogus IRQ13, but probeintr() will handle
* it OK. Bogus halts have never been observed, but we enabled
* IRQ13 and cleared the BUSY# latch early to handle them anyway.
*/
fninit();
DELAY(1000); /* wait for any IRQ13 (fwait might hang) */
#ifdef DIAGNOSTIC
if (npx_intrs_while_probing != 0)
printf("fninit caused %u bogus npx interrupt(s)\n",
npx_intrs_while_probing);
if (npx_traps_while_probing != 0)
printf("fninit caused %u bogus npx trap(s)\n",
npx_traps_while_probing);
#endif
/*
* Check for a status of mostly zero.
*/
status = 0x5a5a;
fnstsw(&status);
if ((status & 0xb8ff) == 0) {
/*
* Good, now check for a proper control word.
*/
control = 0x5a5a;
fnstcw(&control);
if ((control & 0x1f3f) == 0x033f) {
npx_exists = 1;
/*
* We have an npx, now divide by 0 to see if exception
* 16 works.
*/
control &= ~(1 << 2); /* enable divide by 0 trap */
fldcw(&control);
npx_traps_while_probing = npx_intrs_while_probing = 0;
fp_divide_by_0();
if (npx_traps_while_probing != 0) {
/*
* Good, exception 16 works.
*/
npx_ex16 = 1;
dvp->id_irq = 0; /* zap the interrupt */
/*
* special return value to flag that we do not
* actually use any I/O registers
*/
return (-1);
}
if (npx_intrs_while_probing != 0) {
/*
* Bad, we are stuck with IRQ13.
*/
npx_irq13 = 1;
npx0mask = dvp->id_irq; /* npxattach too late */
return (IO_NPXSIZE);
}
/*
* Worse, even IRQ13 is broken. Use emulator.
*/
}
}
/*
* Probe failed, but we want to get to npxattach to initialize the
* emulator and say that it has been installed. XXX handle devices
* that aren't really devices better.
*/
dvp->id_irq = 0;
return (IO_NPXSIZE);
}
/*
* Attach routine - announce which it is, and wire into system
*/
int
npxattach(dvp)
struct isa_device *dvp;
{
if (npx_ex16)
printf(" <Errors reported via Exception 16>");
else if (npx_irq13)
printf(" <Errors reported via IRQ 13>");
else if (npx_exists)
printf(" <Error reporting broken, using 387 emulator>");
else
printf(" <387 Emulator>");
npxinit(__INITIAL_NPXCW__);
return (1); /* XXX unused */
}
/*
* Initialize floating point unit.
*/
void
npxinit(control)
u_int control;
{
struct save87 dummy;
if (!npx_exists)
return;
/*
* fninit has the same h/w bugs as fnsave. Use the detoxified
* fnsave to throw away any junk in the fpu. fnsave initializes
* the fpu and sets npxproc = NULL as important side effects.
*/
npxsave(&dummy);
stop_emulating();
fldcw(&control);
if (curpcb != NULL)
fnsave(&curpcb->pcb_savefpu);
start_emulating();
}
/*
* Free coprocessor (if we have it).
*/
void
npxexit(p)
struct proc *p;
{
if (p == npxproc) {
start_emulating();
npxproc = NULL;
}
}
/*
* Record the FPU state and reinitialize it all except for the control word.
* Then generate a SIGFPE.
*
* Reinitializing the state allows naive SIGFPE handlers to longjmp without
* doing any fixups.
*
* XXX there is currently no way to pass the full error state to signal
* handlers, and if this is a nested interrupt there is no way to pass even
* a status code! So there is no way to have a non-naive SIGFPE handler. At
* best a handler could do an fninit followed by an fldcw of a static value.
* fnclex would be of little use because it would leave junk on the FPU stack.
* Returning from the handler would be even less safe than usual because
* IRQ13 exception handling makes exceptions even less precise than usual.
*/
void
npxintr(frame)
struct intrframe frame;
{
int code;
if (npxproc == NULL || !npx_exists) {
/* XXX no %p in stand/printf.c. Cast to quiet gcc -Wall. */
printf("npxintr: npxproc = %lx, curproc = %lx, npx_exists = %d\n",
(u_long) npxproc, (u_long) curproc, npx_exists);
panic("npxintr from nowhere");
}
if (npxproc != curproc) {
printf("npxintr: npxproc = %lx, curproc = %lx, npx_exists = %d\n",
(u_long) npxproc, (u_long) curproc, npx_exists);
panic("npxintr from non-current process");
}
/*
* Save state. This does an implied fninit. It had better not halt
* the cpu or we'll hang.
*/
outb(0xf0, 0);
fnsave(&curpcb->pcb_savefpu);
fwait();
/*
* Restore control word (was clobbered by fnsave).
*/
fldcw(&curpcb->pcb_savefpu.sv_env.en_cw);
fwait();
/*
* Remember the exception status word and tag word. The current
* (almost fninit'ed) fpu state is in the fpu and the exception
* state just saved will soon be junk. However, the implied fninit
* doesn't change the error pointers or register contents, and we
* preserved the control word and will copy the status and tag
* words, so the complete exception state can be recovered.
*/
curpcb->pcb_savefpu.sv_ex_sw = curpcb->pcb_savefpu.sv_env.en_sw;
curpcb->pcb_savefpu.sv_ex_tw = curpcb->pcb_savefpu.sv_env.en_tw;
/*
* Pass exception to process.
*/
if (ISPL(frame.if_cs) == SEL_UPL) {
/*
* Interrupt is essentially a trap, so we can afford to call
* the SIGFPE handler (if any) as soon as the interrupt
* returns.
*
* XXX little or nothing is gained from this, and plenty is
* lost - the interrupt frame has to contain the trap frame
* (this is otherwise only necessary for the rescheduling trap
* in doreti, and the frame for that could easily be set up
* just before it is used).
*/
curproc->p_regs = (int *)&frame.if_es;
curpcb->pcb_flags |= FM_TRAP; /* used by sendsig */
#ifdef notyet
/*
* Encode the appropriate code for detailed information on
* this exception.
*/
code = XXX_ENCODE(curpcb->pcb_savefpu.sv_ex_sw);
#else
code = 0; /* XXX */
#endif
trapsignal(curproc, SIGFPE, code);
curpcb->pcb_flags &= ~FM_TRAP;
} else {
/*
* Nested interrupt. These losers occur when:
* o an IRQ13 is bogusly generated at a bogus time, e.g.:
* o immediately after an fnsave or frstor of an
* error state.
* o a couple of 386 instructions after
* "fstpl _memvar" causes a stack overflow.
* These are especially nasty when combined with a
* trace trap.
* o an IRQ13 occurs at the same time as another higher-
* priority interrupt.
*
* Treat them like a true async interrupt.
*/
psignal(npxproc, SIGFPE);
}
}
/*
* Implement device not available (DNA) exception
*
* It would be better to switch FP context here (only). This would require
* saving the state in the proc table instead of in the pcb.
*/
int
npxdna()
{
if (!npx_exists)
return (0);
if (npxproc != NULL) {
printf("npxdna: npxproc = %lx, curproc = %lx\n",
(u_long) npxproc, (u_long) curproc);
panic("npxdna");
}
stop_emulating();
/*
* Record new context early in case frstor causes an IRQ13.
*/
npxproc = curproc;
/*
* The following frstor may cause an IRQ13 when the state being
* restored has a pending error. The error will appear to have been
* triggered by the current (npx) user instruction even when that
* instruction is a no-wait instruction that should not trigger an
* error (e.g., fnclex). On at least one 486 system all of the
* no-wait instructions are broken the same as frstor, so our
* treatment does not amplify the breakage. On at least one
* 386/Cyrix 387 system, fnclex works correctly while frstor and
* fnsave are broken, so our treatment breaks fnclex if it is the
* first FPU instruction after a context switch.
*/
frstor(&curpcb->pcb_savefpu);
return (1);
}
/*
* Wrapper for fnsave instruction to handle h/w bugs. If there is an error
* pending, then fnsave generates a bogus IRQ13 on some systems. Force
* any IRQ13 to be handled immediately, and then ignore it. This routine is
* often called at splhigh so it must not use many system services. In
* particular, it's much easier to install a special handler than to
* guarantee that it's safe to use npxintr() and its supporting code.
*/
void
npxsave(addr)
struct save87 *addr;
{
u_char icu1_mask;
u_char icu2_mask;
u_char old_icu1_mask;
u_char old_icu2_mask;
struct gate_descriptor save_idt_npxintr;
disable_intr();
old_icu1_mask = inb(IO_ICU1 + 1);
old_icu2_mask = inb(IO_ICU2 + 1);
save_idt_npxintr = idt[npx_intrno];
outb(IO_ICU1 + 1, old_icu1_mask & ~(IRQ_SLAVE | npx0mask));
outb(IO_ICU2 + 1, old_icu2_mask & ~(npx0mask >> 8));
idt[npx_intrno] = npx_idt_probeintr;
enable_intr();
stop_emulating();
fnsave(addr);
fwait();
start_emulating();
npxproc = NULL;
disable_intr();
icu1_mask = inb(IO_ICU1 + 1); /* masks may have changed */
icu2_mask = inb(IO_ICU2 + 1);
outb(IO_ICU1 + 1,
(icu1_mask & ~npx0mask) | (old_icu1_mask & npx0mask));
outb(IO_ICU2 + 1,
(icu2_mask & ~(npx0mask >> 8))
| (old_icu2_mask & (npx0mask >> 8)));
idt[npx_intrno] = save_idt_npxintr;
enable_intr(); /* back to usual state */
}
#endif /* NNPX > 0 */
+89
View File
@@ -0,0 +1,89 @@
/*-
* Copyright (c) 1993 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Header: timerreg.h,v 1.2 93/02/28 15:08:58 mccanne Exp $
*
* Register definitions for the Intel 8253 Programmable Interval Timer.
*
* This chip has three independent 16-bit down counters that can be
* read on the fly. There are three mode registers and three countdown
* registers. The countdown registers are addressed directly, via the
* first three I/O ports. The three mode registers are accessed via
* the fourth I/O port, with two bits in the mode byte indicating the
* register. (Why are hardware interfaces always so braindead?).
*
* To write a value into the countdown register, the mode register
* is first programmed with a command indicating the which byte of
* the two byte register is to be modified. The three possibilities
* are load msb (TMR_MR_MSB), load lsb (TMR_MR_LSB), or load lsb then
* msb (TMR_MR_BOTH).
*
* To read the current value ("on the fly") from the countdown register,
* you write a "latch" command into the mode register, then read the stable
* value from the corresponding I/O port. For example, you write
* TMR_MR_LATCH into the corresponding mode register. Presumably,
* after doing this, a write operation to the I/O port would result
* in undefined behavior (but hopefully not fry the chip).
* Reading in this manner has no side effects.
*
* The outputs of the three timers are connected as follows:
*
* timer 0 -> irq 0
* timer 1 -> dma chan 0 (for dram refresh)
* timer 2 -> speaker (via keyboard controller)
*
* Timer 0 is used to call hardclock.
* Timer 2 is used to generate console beeps.
*/
/*
* Macros for specifying values to be written into a mode register.
*/
#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
#define TIMER_SEL0 0x00 /* select counter 0 */
#define TIMER_SEL1 0x40 /* select counter 1 */
#define TIMER_SEL2 0x80 /* select counter 2 */
#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */
#define TIMER_ONESHOT 0x02 /* mode 1, one shot */
#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */
#define TIMER_SQWAVE 0x06 /* mode 3, square wave */
#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */
#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */
#define TIMER_LATCH 0x00 /* latch counter for reading */
#define TIMER_LSB 0x10 /* r/w counter LSB */
#define TIMER_MSB 0x20 /* r/w counter MSB */
#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */
#define TIMER_BCD 0x01 /* count in BCD */
+376
View File
@@ -0,0 +1,376 @@
/* vector.s */
/*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00167
* -------------------- ----- ----------------------
*
* 04 Jun 93 Bruce Evans Fixed irq_num vs id_num for multiple
* devices configed on the same irq with
* respect to ipending.
*
*/
#include "i386/isa/icu.h"
#include "i386/isa/isa.h"
#include "vector.h"
#define ICU_EOI 0x20 /* XXX - define elsewhere */
#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8))
#define IRQ_BYTE(irq_num) ((irq_num) / 8)
#define ENABLE_ICU1 \
movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \
FASTER_NOP ; /* ... ASAP ... */ \
outb %al,$IO_ICU1 /* ... to clear in service bit */
#ifdef AUTO_EOI_1
#undef ENABLE_ICU1 /* we now use auto-EOI to reduce i/o */
#define ENABLE_ICU1
#endif
#define ENABLE_ICU1_AND_2 \
movb $ICU_EOI,%al ; /* as above */ \
FASTER_NOP ; \
outb %al,$IO_ICU2 ; /* but do second icu first */ \
FASTER_NOP ; \
outb %al,$IO_ICU1 /* then first icu */
#ifdef AUTO_EOI_2
#undef ENABLE_ICU1_AND_2 /* data sheet says no auto-EOI on slave ... */
#define ENABLE_ICU1_AND_2 /* ... but it works */
#endif
/*
* Macros for interrupt interrupt entry, call to handler, and exit.
*
* XXX - the interrupt frame is set up to look like a trap frame. This is
* usually a waste of time. The only interrupt handlers that want a frame
* are the clock handler (it wants a clock frame), the npx handler (it's
* easier to do right all in assembler). The interrupt return routine
* needs a trap frame for rare AST's (it could easily convert the frame).
* The direct costs of setting up a trap frame are two pushl's (error
* code and trap number), an addl to get rid of these, and pushing and
* popping the call-saved regs %esi, %edi and %ebp twice, The indirect
* costs are making the driver interface nonuniform so unpending of
* interrupts is more complicated and slower (call_driver(unit) would
* be easier than ensuring an interrupt frame for all handlers. Finally,
* there are some struct copies in the npx handler and maybe in the clock
* handler that could be avoided by working more with pointers to frames
* instead of frames.
*
* XXX - should we do a cld on every system entry to avoid the requirement
* for scattered cld's?
*
* Coding notes for *.s:
*
* If possible, avoid operations that involve an operand size override.
* Word-sized operations might be smaller, but the operand size override
* makes them slower on on 486's and no faster on 386's unless perhaps
* the instruction pipeline is depleted. E.g.,
*
* Use movl to seg regs instead of the equivalent but more descriptive
* movw - gas generates an irelevant (slower) operand size override.
*
* Use movl to ordinary regs in preference to movw and especially
* in preference to movz[bw]l. Use unsigned (long) variables with the
* top bits clear instead of unsigned short variables to provide more
* opportunities for movl.
*
* If possible, use byte-sized operations. They are smaller and no slower.
*
* Use (%reg) instead of 0(%reg) - gas generates larger code for the latter.
*
* If the interrupt frame is made more flexible, INTR can push %eax first
* and decide the ipending case with less overhead, e.g., by avoiding
* loading segregs.
*/
#define FAST_INTR(unit, irq_num, id_num, handler, enable_icus) \
pushl %eax ; /* save only call-used registers */ \
pushl %ecx ; \
pushl %edx ; \
pushl %ds ; \
/* pushl %es ; know compiler doesn't do string insns */ \
movl $KDSEL,%eax ; \
movl %ax,%ds ; \
/* movl %ax,%es ; */ \
SHOW_CLI ; /* although it interferes with "ASAP" */ \
pushl $unit ; \
call handler ; /* do the work ASAP */ \
enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \
addl $4,%esp ; \
incl _cnt+V_INTR ; /* book-keeping can wait */ \
COUNT_EVENT(_intrcnt_actv, id_num) ; \
SHOW_STI ; \
/* popl %es ; */ \
popl %ds ; \
popl %edx; \
popl %ecx; \
popl %eax; \
iret
#define INTR(unit, irq_num, id_num, mask, handler, icu, enable_icus, reg, stray) \
pushl $0 ; /* dummy error code */ \
pushl $T_ASTFLT ; \
pushal ; \
pushl %ds ; /* save our data and extra segments ... */ \
pushl %es ; \
movl $KDSEL,%eax ; /* ... and reload with kernel's own ... */ \
movl %ax,%ds ; /* ... early in case SHOW_A_LOT is on */ \
movl %ax,%es ; \
SHOW_CLI ; /* interrupt did an implicit cli */ \
movb _imen + IRQ_BYTE(irq_num),%al ; \
orb $IRQ_BIT(irq_num),%al ; \
movb %al,_imen + IRQ_BYTE(irq_num) ; \
SHOW_IMEN ; \
FASTER_NOP ; \
outb %al,$icu+1 ; \
enable_icus ; \
incl _cnt+V_INTR ; /* tally interrupts */ \
movl _cpl,%eax ; \
testb $IRQ_BIT(irq_num),%reg ; \
jne 2f ; \
1: ; \
COUNT_EVENT(_intrcnt_actv, id_num) ; \
movl _cpl,%eax ; \
pushl %eax ; \
pushl $unit ; \
orl mask,%eax ; \
movl %eax,_cpl ; \
SHOW_CPL ; \
SHOW_STI ; \
sti ; \
call handler ; \
movb _imen + IRQ_BYTE(irq_num),%al ; \
andb $~IRQ_BIT(irq_num),%al ; \
movb %al,_imen + IRQ_BYTE(irq_num) ; \
SHOW_IMEN ; \
FASTER_NOP ; \
outb %al,$icu+1 ; \
jmp doreti ; \
; \
ALIGN_TEXT ; \
2: ; \
COUNT_EVENT(_intrcnt_pend, id_num) ; \
movl $1b,%eax ; /* register resume address */ \
/* XXX - someday do it at attach time */ \
movl %eax,Vresume + (irq_num) * 4 ; \
orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \
SHOW_IPENDING ; \
popl %es ; \
popl %ds ; \
popal ; \
addl $4+4,%esp ; \
iret
/*
* vector.h has defined a macro 'BUILD_VECTORS' containing a big list of info
* about vectors, including a submacro 'BUILD_VECTOR' that operates on the
* info about each vector. We redefine 'BUILD_VECTOR' to expand the info
* in different ways. Here we expand it to a list of interrupt handlers.
* This order is of course unimportant. Elsewhere we expand it to inline
* linear search code for which the order is a little more important and
* concatenating the code with no holes is very important.
*
* XXX - now there is BUILD_FAST_VECTOR as well as BUILD_VECTOR.
*
* The info consists of the following items for each vector:
*
* name (identifier): name of the vector; used to build labels
* unit (expression): unit number to call the device driver with
* irq_num (number): number of the IRQ to handled (0-15)
* id_num (number): uniq numeric id for handler (assigned by config)
* mask (blank-ident): priority mask used
* handler (blank-ident): interrupt handler to call
* icu_num (number): (1 + irq_num / 8) converted for label building
* icu_enables (number): 1 for icu_num == 1, 1_AND_2 for icu_num == 2
* reg (blank-ident): al for icu_num == 1, ah for icu_num == 2
*
* 'irq_num' is converted in several ways at config time to get around
* limitations in cpp. The macros have blanks after commas iff they would
* not mess up identifiers and numbers.
*/
#undef BUILD_FAST_VECTOR
#define BUILD_FAST_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.globl handler ; \
.text ; \
.globl _V/**/name ; \
SUPERALIGN_TEXT ; \
_V/**/name: ; \
FAST_INTR(unit, irq_num, id_num, handler, ENABLE_ICU/**/icu_enables)
#undef BUILD_VECTOR
#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.globl handler ; \
.text ; \
.globl _V/**/name ; \
SUPERALIGN_TEXT ; \
_V/**/name: ; \
INTR(unit,irq_num,id_num, mask, handler, IO_ICU/**/icu_num, \
ENABLE_ICU/**/icu_enables, reg,)
BUILD_VECTORS
/* hardware interrupt catcher (IDT 32 - 47) */
.globl _isa_strayintr
#define STRAYINTR(irq_num, icu_num, icu_enables, reg) \
IDTVEC(intr/**/irq_num) ; \
INTR(irq_num,irq_num,irq_num, _highmask, _isa_strayintr, \
IO_ICU/**/icu_num, ENABLE_ICU/**/icu_enables, reg,stray)
/*
* XXX - the mask (1 << 2) == IRQ_SLAVE will be generated for IRQ 2, instead
* of the mask IRQ2 (defined as IRQ9 == (1 << 9)). But IRQ 2 "can't happen".
* In fact, all stray interrupts "can't happen" except for bugs. The
* "stray" IRQ 7 is documented behaviour of the 8259. It happens when there
* is a glitch on any of its interrupt inputs. Does it really interrupt when
* IRQ 7 is masked?
*
* XXX - unpend doesn't work for these, it sends them to the real handler.
*
* XXX - the race bug during initialization may be because I changed the
* order of switching from the stray to the real interrupt handler to before
* enabling interrupts. The old order looked unsafe but maybe it is OK with
* the stray interrupt handler installed. But these handlers only reduce
* the window of vulnerability - it is still open at the end of
* isa_configure().
*
* XXX - many comments are stale.
*/
STRAYINTR(0,1,1, al)
STRAYINTR(1,1,1, al)
STRAYINTR(2,1,1, al)
STRAYINTR(3,1,1, al)
STRAYINTR(4,1,1, al)
STRAYINTR(5,1,1, al)
STRAYINTR(6,1,1, al)
STRAYINTR(8,2,1_AND_2, ah)
STRAYINTR(9,2,1_AND_2, ah)
STRAYINTR(10,2,1_AND_2, ah)
STRAYINTR(11,2,1_AND_2, ah)
STRAYINTR(12,2,1_AND_2, ah)
STRAYINTR(13,2,1_AND_2, ah)
STRAYINTR(14,2,1_AND_2, ah)
STRAYINTR(15,2,1_AND_2, ah)
IDTVEC(intrdefault)
STRAYINTR(7,1,1, al) /* XXX */
#if 0
INTRSTRAY(255, _highmask, 255) ; call _isa_strayintr ; INTREXIT2
#endif
/*
* These are the interrupt counters, I moved them here from icu.s so that
* they are with the name table. rgrimes
*
* There are now lots of counters, this has been redone to work with
* Bruce Evans intr-0.1 code, which I modified some more to make it all
* work with vmstat.
*/
.data
Vresume: .space 16 * 4 /* where to resume intr handler after unpend */
.globl _intrcnt
_intrcnt: /* used by vmstat to calc size of table */
.globl _intrcnt_bad7
_intrcnt_bad7: .space 4 /* glitches on irq 7 */
.globl _intrcnt_bad15
_intrcnt_bad15: .space 4 /* glitches on irq 15 */
.globl _intrcnt_stray
_intrcnt_stray: .space 4 /* total count of stray interrupts */
.globl _intrcnt_actv
_intrcnt_actv: .space NR_REAL_INT_HANDLERS * 4 /* active interrupts */
.globl _intrcnt_pend
_intrcnt_pend: .space NR_REAL_INT_HANDLERS * 4 /* pending interrupts */
.globl _intrcnt_spl
_intrcnt_spl: .space 32 * 4 /* XXX 32 should not be hard coded ? */
.globl _intrcnt_show
_intrcnt_show: .space 8 * 4 /* XXX 16 should not be hard coded ? */
.globl _eintrcnt
_eintrcnt: /* used by vmstat to calc size of table */
/*
* Build the interrupt name table for vmstat
*/
#undef BUILD_FAST_VECTOR
#define BUILD_FAST_VECTOR BUILD_VECTOR
#undef BUILD_VECTOR
#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.ascii "name irq" ; \
.asciz "irq_num"
/*
* XXX - use the STRING and CONCAT macros from <sys/cdefs.h> to stringize
* and concatenate names above and elsewhere.
*/
.text
.globl _intrnames, _eintrnames
_intrnames:
BUILD_VECTOR(bad,,7,,,,,,)
BUILD_VECTOR(bad,,15,,,,,,)
BUILD_VECTOR(stray,,,,,,,,)
BUILD_VECTORS
#undef BUILD_FAST_VECTOR
#define BUILD_FAST_VECTOR BUILD_VECTOR
#undef BUILD_VECTOR
#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.asciz "name pend"
BUILD_VECTORS
/*
* now the spl names
*/
.asciz "unpend_v"
.asciz "doreti"
.asciz "p0!ni"
.asciz "!p0!ni"
.asciz "p0ni"
.asciz "netisr_raw"
.asciz "netisr_ip"
.asciz "netisr_imp"
.asciz "netisr_ns"
.asciz "softclock"
.asciz "trap"
.asciz "doreti_exit2"
.asciz "splbio"
.asciz "splclock"
.asciz "splhigh"
.asciz "splimp"
.asciz "splnet"
.asciz "splsoftclock"
.asciz "spltty"
.asciz "spl0"
.asciz "netisr_raw2"
.asciz "netisr_ip2"
.asciz "splx"
.asciz "splx!0"
.asciz "unpend_V"
.asciz "spl25" /* spl25-spl31 are spares */
.asciz "spl26"
.asciz "spl27"
.asciz "spl28"
.asciz "spl29"
.asciz "spl30"
.asciz "spl31"
/*
* now the mask names
*/
.asciz "cli"
.asciz "cpl"
.asciz "imen"
.asciz "ipending"
.asciz "sti"
.asciz "mask5" /* mask5-mask7 are spares */
.asciz "mask6"
.asciz "mask7"
_eintrnames:
+376
View File
@@ -0,0 +1,376 @@
/* vector.s */
/*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00167
* -------------------- ----- ----------------------
*
* 04 Jun 93 Bruce Evans Fixed irq_num vs id_num for multiple
* devices configed on the same irq with
* respect to ipending.
*
*/
#include "i386/isa/icu.h"
#include "i386/isa/isa.h"
#include "vector.h"
#define ICU_EOI 0x20 /* XXX - define elsewhere */
#define IRQ_BIT(irq_num) (1 << ((irq_num) % 8))
#define IRQ_BYTE(irq_num) ((irq_num) / 8)
#define ENABLE_ICU1 \
movb $ICU_EOI,%al ; /* as soon as possible send EOI ... */ \
FASTER_NOP ; /* ... ASAP ... */ \
outb %al,$IO_ICU1 /* ... to clear in service bit */
#ifdef AUTO_EOI_1
#undef ENABLE_ICU1 /* we now use auto-EOI to reduce i/o */
#define ENABLE_ICU1
#endif
#define ENABLE_ICU1_AND_2 \
movb $ICU_EOI,%al ; /* as above */ \
FASTER_NOP ; \
outb %al,$IO_ICU2 ; /* but do second icu first */ \
FASTER_NOP ; \
outb %al,$IO_ICU1 /* then first icu */
#ifdef AUTO_EOI_2
#undef ENABLE_ICU1_AND_2 /* data sheet says no auto-EOI on slave ... */
#define ENABLE_ICU1_AND_2 /* ... but it works */
#endif
/*
* Macros for interrupt interrupt entry, call to handler, and exit.
*
* XXX - the interrupt frame is set up to look like a trap frame. This is
* usually a waste of time. The only interrupt handlers that want a frame
* are the clock handler (it wants a clock frame), the npx handler (it's
* easier to do right all in assembler). The interrupt return routine
* needs a trap frame for rare AST's (it could easily convert the frame).
* The direct costs of setting up a trap frame are two pushl's (error
* code and trap number), an addl to get rid of these, and pushing and
* popping the call-saved regs %esi, %edi and %ebp twice, The indirect
* costs are making the driver interface nonuniform so unpending of
* interrupts is more complicated and slower (call_driver(unit) would
* be easier than ensuring an interrupt frame for all handlers. Finally,
* there are some struct copies in the npx handler and maybe in the clock
* handler that could be avoided by working more with pointers to frames
* instead of frames.
*
* XXX - should we do a cld on every system entry to avoid the requirement
* for scattered cld's?
*
* Coding notes for *.s:
*
* If possible, avoid operations that involve an operand size override.
* Word-sized operations might be smaller, but the operand size override
* makes them slower on on 486's and no faster on 386's unless perhaps
* the instruction pipeline is depleted. E.g.,
*
* Use movl to seg regs instead of the equivalent but more descriptive
* movw - gas generates an irelevant (slower) operand size override.
*
* Use movl to ordinary regs in preference to movw and especially
* in preference to movz[bw]l. Use unsigned (long) variables with the
* top bits clear instead of unsigned short variables to provide more
* opportunities for movl.
*
* If possible, use byte-sized operations. They are smaller and no slower.
*
* Use (%reg) instead of 0(%reg) - gas generates larger code for the latter.
*
* If the interrupt frame is made more flexible, INTR can push %eax first
* and decide the ipending case with less overhead, e.g., by avoiding
* loading segregs.
*/
#define FAST_INTR(unit, irq_num, id_num, handler, enable_icus) \
pushl %eax ; /* save only call-used registers */ \
pushl %ecx ; \
pushl %edx ; \
pushl %ds ; \
/* pushl %es ; know compiler doesn't do string insns */ \
movl $KDSEL,%eax ; \
movl %ax,%ds ; \
/* movl %ax,%es ; */ \
SHOW_CLI ; /* although it interferes with "ASAP" */ \
pushl $unit ; \
call handler ; /* do the work ASAP */ \
enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \
addl $4,%esp ; \
incl _cnt+V_INTR ; /* book-keeping can wait */ \
COUNT_EVENT(_intrcnt_actv, id_num) ; \
SHOW_STI ; \
/* popl %es ; */ \
popl %ds ; \
popl %edx; \
popl %ecx; \
popl %eax; \
iret
#define INTR(unit, irq_num, id_num, mask, handler, icu, enable_icus, reg, stray) \
pushl $0 ; /* dummy error code */ \
pushl $T_ASTFLT ; \
pushal ; \
pushl %ds ; /* save our data and extra segments ... */ \
pushl %es ; \
movl $KDSEL,%eax ; /* ... and reload with kernel's own ... */ \
movl %ax,%ds ; /* ... early in case SHOW_A_LOT is on */ \
movl %ax,%es ; \
SHOW_CLI ; /* interrupt did an implicit cli */ \
movb _imen + IRQ_BYTE(irq_num),%al ; \
orb $IRQ_BIT(irq_num),%al ; \
movb %al,_imen + IRQ_BYTE(irq_num) ; \
SHOW_IMEN ; \
FASTER_NOP ; \
outb %al,$icu+1 ; \
enable_icus ; \
incl _cnt+V_INTR ; /* tally interrupts */ \
movl _cpl,%eax ; \
testb $IRQ_BIT(irq_num),%reg ; \
jne 2f ; \
1: ; \
COUNT_EVENT(_intrcnt_actv, id_num) ; \
movl _cpl,%eax ; \
pushl %eax ; \
pushl $unit ; \
orl mask,%eax ; \
movl %eax,_cpl ; \
SHOW_CPL ; \
SHOW_STI ; \
sti ; \
call handler ; \
movb _imen + IRQ_BYTE(irq_num),%al ; \
andb $~IRQ_BIT(irq_num),%al ; \
movb %al,_imen + IRQ_BYTE(irq_num) ; \
SHOW_IMEN ; \
FASTER_NOP ; \
outb %al,$icu+1 ; \
jmp doreti ; \
; \
ALIGN_TEXT ; \
2: ; \
COUNT_EVENT(_intrcnt_pend, id_num) ; \
movl $1b,%eax ; /* register resume address */ \
/* XXX - someday do it at attach time */ \
movl %eax,Vresume + (irq_num) * 4 ; \
orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \
SHOW_IPENDING ; \
popl %es ; \
popl %ds ; \
popal ; \
addl $4+4,%esp ; \
iret
/*
* vector.h has defined a macro 'BUILD_VECTORS' containing a big list of info
* about vectors, including a submacro 'BUILD_VECTOR' that operates on the
* info about each vector. We redefine 'BUILD_VECTOR' to expand the info
* in different ways. Here we expand it to a list of interrupt handlers.
* This order is of course unimportant. Elsewhere we expand it to inline
* linear search code for which the order is a little more important and
* concatenating the code with no holes is very important.
*
* XXX - now there is BUILD_FAST_VECTOR as well as BUILD_VECTOR.
*
* The info consists of the following items for each vector:
*
* name (identifier): name of the vector; used to build labels
* unit (expression): unit number to call the device driver with
* irq_num (number): number of the IRQ to handled (0-15)
* id_num (number): uniq numeric id for handler (assigned by config)
* mask (blank-ident): priority mask used
* handler (blank-ident): interrupt handler to call
* icu_num (number): (1 + irq_num / 8) converted for label building
* icu_enables (number): 1 for icu_num == 1, 1_AND_2 for icu_num == 2
* reg (blank-ident): al for icu_num == 1, ah for icu_num == 2
*
* 'irq_num' is converted in several ways at config time to get around
* limitations in cpp. The macros have blanks after commas iff they would
* not mess up identifiers and numbers.
*/
#undef BUILD_FAST_VECTOR
#define BUILD_FAST_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.globl handler ; \
.text ; \
.globl _V/**/name ; \
SUPERALIGN_TEXT ; \
_V/**/name: ; \
FAST_INTR(unit, irq_num, id_num, handler, ENABLE_ICU/**/icu_enables)
#undef BUILD_VECTOR
#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.globl handler ; \
.text ; \
.globl _V/**/name ; \
SUPERALIGN_TEXT ; \
_V/**/name: ; \
INTR(unit,irq_num,id_num, mask, handler, IO_ICU/**/icu_num, \
ENABLE_ICU/**/icu_enables, reg,)
BUILD_VECTORS
/* hardware interrupt catcher (IDT 32 - 47) */
.globl _isa_strayintr
#define STRAYINTR(irq_num, icu_num, icu_enables, reg) \
IDTVEC(intr/**/irq_num) ; \
INTR(irq_num,irq_num,irq_num, _highmask, _isa_strayintr, \
IO_ICU/**/icu_num, ENABLE_ICU/**/icu_enables, reg,stray)
/*
* XXX - the mask (1 << 2) == IRQ_SLAVE will be generated for IRQ 2, instead
* of the mask IRQ2 (defined as IRQ9 == (1 << 9)). But IRQ 2 "can't happen".
* In fact, all stray interrupts "can't happen" except for bugs. The
* "stray" IRQ 7 is documented behaviour of the 8259. It happens when there
* is a glitch on any of its interrupt inputs. Does it really interrupt when
* IRQ 7 is masked?
*
* XXX - unpend doesn't work for these, it sends them to the real handler.
*
* XXX - the race bug during initialization may be because I changed the
* order of switching from the stray to the real interrupt handler to before
* enabling interrupts. The old order looked unsafe but maybe it is OK with
* the stray interrupt handler installed. But these handlers only reduce
* the window of vulnerability - it is still open at the end of
* isa_configure().
*
* XXX - many comments are stale.
*/
STRAYINTR(0,1,1, al)
STRAYINTR(1,1,1, al)
STRAYINTR(2,1,1, al)
STRAYINTR(3,1,1, al)
STRAYINTR(4,1,1, al)
STRAYINTR(5,1,1, al)
STRAYINTR(6,1,1, al)
STRAYINTR(8,2,1_AND_2, ah)
STRAYINTR(9,2,1_AND_2, ah)
STRAYINTR(10,2,1_AND_2, ah)
STRAYINTR(11,2,1_AND_2, ah)
STRAYINTR(12,2,1_AND_2, ah)
STRAYINTR(13,2,1_AND_2, ah)
STRAYINTR(14,2,1_AND_2, ah)
STRAYINTR(15,2,1_AND_2, ah)
IDTVEC(intrdefault)
STRAYINTR(7,1,1, al) /* XXX */
#if 0
INTRSTRAY(255, _highmask, 255) ; call _isa_strayintr ; INTREXIT2
#endif
/*
* These are the interrupt counters, I moved them here from icu.s so that
* they are with the name table. rgrimes
*
* There are now lots of counters, this has been redone to work with
* Bruce Evans intr-0.1 code, which I modified some more to make it all
* work with vmstat.
*/
.data
Vresume: .space 16 * 4 /* where to resume intr handler after unpend */
.globl _intrcnt
_intrcnt: /* used by vmstat to calc size of table */
.globl _intrcnt_bad7
_intrcnt_bad7: .space 4 /* glitches on irq 7 */
.globl _intrcnt_bad15
_intrcnt_bad15: .space 4 /* glitches on irq 15 */
.globl _intrcnt_stray
_intrcnt_stray: .space 4 /* total count of stray interrupts */
.globl _intrcnt_actv
_intrcnt_actv: .space NR_REAL_INT_HANDLERS * 4 /* active interrupts */
.globl _intrcnt_pend
_intrcnt_pend: .space NR_REAL_INT_HANDLERS * 4 /* pending interrupts */
.globl _intrcnt_spl
_intrcnt_spl: .space 32 * 4 /* XXX 32 should not be hard coded ? */
.globl _intrcnt_show
_intrcnt_show: .space 8 * 4 /* XXX 16 should not be hard coded ? */
.globl _eintrcnt
_eintrcnt: /* used by vmstat to calc size of table */
/*
* Build the interrupt name table for vmstat
*/
#undef BUILD_FAST_VECTOR
#define BUILD_FAST_VECTOR BUILD_VECTOR
#undef BUILD_VECTOR
#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.ascii "name irq" ; \
.asciz "irq_num"
/*
* XXX - use the STRING and CONCAT macros from <sys/cdefs.h> to stringize
* and concatenate names above and elsewhere.
*/
.text
.globl _intrnames, _eintrnames
_intrnames:
BUILD_VECTOR(bad,,7,,,,,,)
BUILD_VECTOR(bad,,15,,,,,,)
BUILD_VECTOR(stray,,,,,,,,)
BUILD_VECTORS
#undef BUILD_FAST_VECTOR
#define BUILD_FAST_VECTOR BUILD_VECTOR
#undef BUILD_VECTOR
#define BUILD_VECTOR(name, unit, irq_num, id_num, mask, handler, \
icu_num, icu_enables, reg) \
.asciz "name pend"
BUILD_VECTORS
/*
* now the spl names
*/
.asciz "unpend_v"
.asciz "doreti"
.asciz "p0!ni"
.asciz "!p0!ni"
.asciz "p0ni"
.asciz "netisr_raw"
.asciz "netisr_ip"
.asciz "netisr_imp"
.asciz "netisr_ns"
.asciz "softclock"
.asciz "trap"
.asciz "doreti_exit2"
.asciz "splbio"
.asciz "splclock"
.asciz "splhigh"
.asciz "splimp"
.asciz "splnet"
.asciz "splsoftclock"
.asciz "spltty"
.asciz "spl0"
.asciz "netisr_raw2"
.asciz "netisr_ip2"
.asciz "splx"
.asciz "splx!0"
.asciz "unpend_V"
.asciz "spl25" /* spl25-spl31 are spares */
.asciz "spl26"
.asciz "spl27"
.asciz "spl28"
.asciz "spl29"
.asciz "spl30"
.asciz "spl31"
/*
* now the mask names
*/
.asciz "cli"
.asciz "cpl"
.asciz "imen"
.asciz "ipending"
.asciz "sti"
.asciz "mask5" /* mask5-mask7 are spares */
.asciz "mask6"
.asciz "mask7"
_eintrnames:
+164
View File
@@ -0,0 +1,164 @@
# Copyright 1990 W. Jolitz
# @(#)Makefile.i386 7.1 5/10/91
# Makefile for 4.3 BSD-Reno
#
# This makefile is constructed from a machine description:
# config machineid
# Most changes should be made in the machine description
# /sys/i386/conf/``machineid''
# after which you should do
# config machineid
# Generic makefile changes should be made in
# /sys/i386/conf/Makefile.i386
# after which config should be rerun for all machines.
#
# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE INVISIBLE TO MAKEFILE
# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
#
# -DTRACE compile in kernel tracing hooks
# -DQUOTA compile in file system quotas
#
# PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
# -------------------- ----- ----------------------
# CURRENT PATCH LEVEL: 3 00158
# -------------------- ----- ----------------------
#
# 29 Jun 92 Chris G. Demetriou Fix vers.o for kernel profiling and
# plain old link
# 25 Mar 93 Sean Eric Fagan Add support for assembler source
# 25 Apr 93 Bruce Evans Support for intr-0.0, and some fixes
# Rodney W. Grimes Added depedencies for conf.o due to
# all the new drivers. And to param.c
# because there were missing.
# 26 May 97 Rodney W. Grimes Remove extra SYSTEM_LD_TAIL
# Redirect stderr from dbsym to null,
# this is bad, but atleast I won't get
# 100's of bug reports about the silly
# warning from dbsym.
#
TOUCH= touch -f -c
LD= /usr/bin/ld
CC= cc
CPP= cpp
S= ../..
I386= ../../i386
INCLUDES= -I. -I$S -I$S/sys
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -Di386 -DNPX
ASFLAGS=
CFLAGS= -O ${COPTS}
NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $<
NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
NORMAL_S= ${CPP} -I. -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o
DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
SYSTEM_OBJS=locore.o ${OBJS} param.o ioconf.o conf.o
SYSTEM_DEP=Makefile symbols.sort ${SYSTEM_OBJS}
SYSTEM_LD_HEAD= @echo loading $@; rm -f $@
SYSTEM_LD= @${LD} -z -T FE000000 -o $@ -X vers.o ${SYSTEM_OBJS}
SYSTEM_LD_TAIL= @echo rearranging symbols; symorder symbols.sort $@; \
dbsym $@ 2>/dev/null || true; size $@; chmod 755 $@
GPROF.EX= /usr/src/lib/csu.i386/gprof.ex
PROFILE_C= ${CC} -S -c ${CFLAGS} $< ; \
ex - $*.s < ${GPROF.EX} ; \
${AS} -o $@ $*.s ; \
rm -f $*.s
%OBJS
%CFILES
%LOAD
clean:
rm -f eddep *386bsd tags *.o locore.i [a-uw-z]*.s \
errs linterrs makelinks genassym
lint: /tmp param.c
@lint -hbxn -I. -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \
${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \
grep -v 'struct/union .* never defined' | \
grep -v 'possible pointer alignment problem'
symbols.sort: ${I386}/i386/symbols.raw
grep -v '^#' ${I386}/i386/symbols.raw \
| sed 's/^ //' | sort -u > symbols.sort
locore.o: assym.s ${I386}/i386/locore.s machine/trap.h machine/psl.h \
machine/pte.h ${I386}/isa/vector.s ${I386}/isa/icu.s \
$S/sys/errno.h machine/specialreg.h ${I386}/isa/debug.h \
${I386}/isa/icu.h ${I386}/isa/isa.h vector.h $S/net/netisr.h
${CPP} -I. -DLOCORE ${COPTS} ${I386}/i386/locore.s | \
${AS} ${ASFLAGS} -o locore.o
# the following is necessary because autoconf.o depends on #if GENERIC
autoconf.o: Makefile
# depend on network configuration
af.o uipc_proto.o locore.o: Makefile
# depend on maxusers
assym.s machdep.o: Makefile
# depends on KDB (cons.o also depends on GENERIC)
trap.o cons.o: Makefile
assym.s: $S/sys/param.h machine/pte.h $S/sys/buf.h \
$S/sys/vmmeter.h \
$S/sys/proc.h $S/sys/msgbuf.h machine/vmparam.h
assym.s: genassym
./genassym >assym.s
genassym:
${CC} ${INCLUDES} -DKERNEL ${IDENT} ${PARAM} \
${I386}/i386/genassym.c -o genassym
depend: assym.s param.c
sh /usr/bin/mkdep ${COPTS} ${CFILES} ioconf.c
sh /usr/bin/mkdep -a -p ${INCLUDES} ${IDENT} ${PARAM} ${I386}/i386/genassym.c
links:
egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
sort -u | comm -23 - dontlink | \
sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks
sh makelinks && rm -f dontlink
tags:
@echo "see $S/kern/Makefile for tags"
ioconf.o: ioconf.c $S/sys/param.h machine/pte.h $S/sys/buf.h \
${I386}/isa/isa_device.h ${I386}/isa/isa.h ${I386}/isa/icu.h
${CC} -c ${CFLAGS} ioconf.c
conf.o: $S/sys/param.h $S/sys/systm.h $S/sys/buf.h $S/sys/ioctl.h \
$S/sys/tty.h $S/sys/conf.h \
as.h bpfilter.h cd.h ch.h com.h dcfclk.h fd.h lpa.h \
lpt.h pty.h sd.h speaker.h st.h wd.h wt.h \
${I386}/i386/conf.c
${CC} -traditional -c ${CFLAGS} ${I386}/i386/conf.c
param.c: $S/conf/param.c \
$S/sys/param.h $S/sys/systm.h $S/sys/socket.h $S/sys/proc.h \
$S/sys/vnode.h $S/sys/file.h $S/sys/callout.h $S/sys/clist.h \
$S/sys/mbuf.h $S/ufs/quota.h $S/sys/kernel.h machine/vmparam.h \
$S/sys/shm.h
-rm -f param.c
cp $S/conf/param.c .
param.o: param.c Makefile
${CC} -c ${CFLAGS} ${PARAM} param.c
newvers:
sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT}
${CC} ${CFLAGS} -c vers.c
%RULES
# DO NOT DELETE THIS LINE -- make depend uses it
+164
View File
@@ -0,0 +1,164 @@
# Copyright 1990 W. Jolitz
# @(#)Makefile.i386 7.1 5/10/91
# Makefile for 4.3 BSD-Reno
#
# This makefile is constructed from a machine description:
# config machineid
# Most changes should be made in the machine description
# /sys/i386/conf/``machineid''
# after which you should do
# config machineid
# Generic makefile changes should be made in
# /sys/i386/conf/Makefile.i386
# after which config should be rerun for all machines.
#
# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE INVISIBLE TO MAKEFILE
# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
#
# -DTRACE compile in kernel tracing hooks
# -DQUOTA compile in file system quotas
#
# PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
# -------------------- ----- ----------------------
# CURRENT PATCH LEVEL: 3 00158
# -------------------- ----- ----------------------
#
# 29 Jun 92 Chris G. Demetriou Fix vers.o for kernel profiling and
# plain old link
# 25 Mar 93 Sean Eric Fagan Add support for assembler source
# 25 Apr 93 Bruce Evans Support for intr-0.0, and some fixes
# Rodney W. Grimes Added depedencies for conf.o due to
# all the new drivers. And to param.c
# because there were missing.
# 26 May 97 Rodney W. Grimes Remove extra SYSTEM_LD_TAIL
# Redirect stderr from dbsym to null,
# this is bad, but atleast I won't get
# 100's of bug reports about the silly
# warning from dbsym.
#
TOUCH= touch -f -c
LD= /usr/bin/ld
CC= cc
CPP= cpp
S= ../..
I386= ../../i386
INCLUDES= -I. -I$S -I$S/sys
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -Di386 -DNPX
ASFLAGS=
CFLAGS= -O ${COPTS}
NORMAL_C= ${CC} -c ${CFLAGS} ${PROF} $<
NORMAL_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
NORMAL_S= ${CPP} -I. -DLOCORE ${COPTS} $< | ${AS} ${ASFLAGS} -o $*.o
DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
SYSTEM_OBJS=locore.o ${OBJS} param.o ioconf.o conf.o
SYSTEM_DEP=Makefile symbols.sort ${SYSTEM_OBJS}
SYSTEM_LD_HEAD= @echo loading $@; rm -f $@
SYSTEM_LD= @${LD} -z -T FE000000 -o $@ -X vers.o ${SYSTEM_OBJS}
SYSTEM_LD_TAIL= @echo rearranging symbols; symorder symbols.sort $@; \
dbsym $@ 2>/dev/null || true; size $@; chmod 755 $@
GPROF.EX= /usr/src/lib/csu.i386/gprof.ex
PROFILE_C= ${CC} -S -c ${CFLAGS} $< ; \
ex - $*.s < ${GPROF.EX} ; \
${AS} -o $@ $*.s ; \
rm -f $*.s
%OBJS
%CFILES
%LOAD
clean:
rm -f eddep *386bsd tags *.o locore.i [a-uw-z]*.s \
errs linterrs makelinks genassym
lint: /tmp param.c
@lint -hbxn -I. -DGENERIC -Dvolatile= ${COPTS} ${PARAM} \
${I386}/i386/Locore.c ${CFILES} ioconf.c param.c | \
grep -v 'struct/union .* never defined' | \
grep -v 'possible pointer alignment problem'
symbols.sort: ${I386}/i386/symbols.raw
grep -v '^#' ${I386}/i386/symbols.raw \
| sed 's/^ //' | sort -u > symbols.sort
locore.o: assym.s ${I386}/i386/locore.s machine/trap.h machine/psl.h \
machine/pte.h ${I386}/isa/vector.s ${I386}/isa/icu.s \
$S/sys/errno.h machine/specialreg.h ${I386}/isa/debug.h \
${I386}/isa/icu.h ${I386}/isa/isa.h vector.h $S/net/netisr.h
${CPP} -I. -DLOCORE ${COPTS} ${I386}/i386/locore.s | \
${AS} ${ASFLAGS} -o locore.o
# the following is necessary because autoconf.o depends on #if GENERIC
autoconf.o: Makefile
# depend on network configuration
af.o uipc_proto.o locore.o: Makefile
# depend on maxusers
assym.s machdep.o: Makefile
# depends on KDB (cons.o also depends on GENERIC)
trap.o cons.o: Makefile
assym.s: $S/sys/param.h machine/pte.h $S/sys/buf.h \
$S/sys/vmmeter.h \
$S/sys/proc.h $S/sys/msgbuf.h machine/vmparam.h
assym.s: genassym
./genassym >assym.s
genassym:
${CC} ${INCLUDES} -DKERNEL ${IDENT} ${PARAM} \
${I386}/i386/genassym.c -o genassym
depend: assym.s param.c
sh /usr/bin/mkdep ${COPTS} ${CFILES} ioconf.c
sh /usr/bin/mkdep -a -p ${INCLUDES} ${IDENT} ${PARAM} ${I386}/i386/genassym.c
links:
egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
sort -u | comm -23 - dontlink | \
sed 's,../.*/\(.*.o\),rm -f \1;ln -s ../GENERIC/\1 \1,' > makelinks
sh makelinks && rm -f dontlink
tags:
@echo "see $S/kern/Makefile for tags"
ioconf.o: ioconf.c $S/sys/param.h machine/pte.h $S/sys/buf.h \
${I386}/isa/isa_device.h ${I386}/isa/isa.h ${I386}/isa/icu.h
${CC} -c ${CFLAGS} ioconf.c
conf.o: $S/sys/param.h $S/sys/systm.h $S/sys/buf.h $S/sys/ioctl.h \
$S/sys/tty.h $S/sys/conf.h \
as.h bpfilter.h cd.h ch.h com.h dcfclk.h fd.h lpa.h \
lpt.h pty.h sd.h speaker.h st.h wd.h wt.h \
${I386}/i386/conf.c
${CC} -traditional -c ${CFLAGS} ${I386}/i386/conf.c
param.c: $S/conf/param.c \
$S/sys/param.h $S/sys/systm.h $S/sys/socket.h $S/sys/proc.h \
$S/sys/vnode.h $S/sys/file.h $S/sys/callout.h $S/sys/clist.h \
$S/sys/mbuf.h $S/ufs/quota.h $S/sys/kernel.h machine/vmparam.h \
$S/sys/shm.h
-rm -f param.c
cp $S/conf/param.c .
param.o: param.c Makefile
${CC} -c ${CFLAGS} ${PARAM} param.c
newvers:
sh $S/conf/newvers.sh ${KERN_IDENT} ${IDENT}
${CC} ${CFLAGS} -c vers.c
%RULES
# DO NOT DELETE THIS LINE -- make depend uses it
+71
View File
@@ -0,0 +1,71 @@
#
# PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
# -------------------- ----- ----------------------
# CURRENT PATCH LEVEL: 3 00160
# -------------------- ----- ----------------------
#
# 17 Feb 93 Julian Elischer Added files for scsi
# 10 Mar 93 Rodney W. Grimes Added files for lpt and lpa
# 25 Mar 93 Sean Eric Fagan Added microtime.s routine
# 08 Apr 93 Rodney W. Grimes Cleaned up the tabs, sorted file names
# Added ix, speaker, dcfclock
# 23 Apr 93 Holger Veit Added codrv
# 26 May 93 Rodney W. Grimes Rename of Bruce Evans com driver to sio
# Gene Stark Add xten power controler driver (tw)
# David Greenman Add ethernet driver (SMC/WD/3COM) (ed)
# Rick Macklem Add bus mouse driver (mse)
#
i386/i386/autoconf.c standard device-driver
i386/i386/cons.c standard
i386/i386/db_disasm.c optional ddb
i386/i386/db_interface.c optional ddb
i386/i386/db_trace.c optional ddb
i386/i386/in_cksum.c optional inet
i386/i386/machdep.c standard config-dependent
i386/i386/math_emulate.c standard
i386/i386/mem.c standard
i386/i386/microtime.s standard
i386/i386/ns_cksum.c optional ns
i386/i386/pmap.c standard
i386/i386/sys_machdep.c standard
i386/i386/trap.c standard
i386/i386/vm_machdep.c standard
i386/isa/aha1542.c optional aha device-driver
i386/isa/aha1742.c optional ahb device-driver
i386/isa/as.c optional as device-driver
i386/isa/bt742a.c optional bt device-driver
i386/isa/clock.c standard
i386/isa/codrv/co_cons.c optional co device-driver
i386/isa/codrv/co_kbd.c optional co device-driver
i386/isa/codrv/co_vga.c optional co device-driver
i386/isa/codrv/co_codrv1.c optional co device-driver
i386/isa/codrv/co_vty.c optional vty
i386/isa/codrv/co_pc3.c optional vtemul
i386/isa/codrv/co_mini.c optional vtemul
i386/isa/com.c optional com device-driver
i386/isa/dcfclk.c optional dcfclk device-driver
i386/isa/fd.c optional fd device-driver
i386/isa/if_ec.c optional ec device-driver
i386/isa/if_ed.c optional ed device-driver
i386/isa/if_is.c optional is device-driver
i386/isa/if_ix.c optional ix device-driver
i386/isa/if_ne.c optional ne device-driver
i386/isa/if_we.c optional we device-driver
i386/isa/isa.c optional isa device-driver
i386/isa/lpa.c optional lpa device-driver
i386/isa/lpt.c optional lpt device-driver
i386/isa/mse.c optional mse device-driver
i386/isa/npx.c optional npx device-driver
i386/isa/pccons.c optional pc device-driver
i386/isa/sio.c optional sio device-driver
i386/isa/spkr.c optional speaker
i386/isa/tw.c optional tw device-driver
i386/isa/ultra14f.c optional uha device-driver
i386/isa/wd.c optional wd device-driver
i386/isa/wt.c optional wt device-driver
scsi/cd.c optional cd
scsi/ch.c optional ch
scsi/scsiconf.c optional scbus
scsi/sd.c optional sd
scsi/st.c optional st
+116
View File
@@ -0,0 +1,116 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_access.c,v $
* Revision 1.1 1992/03/25 21:44:50 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:05:44 mrt
* Changed to new Mach copyright
* [91/01/31 16:16:22 mrt]
*
* Revision 2.2 90/08/27 21:48:20 dbg
* Fix type declarations.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h> /* type definitions */
/*
* Access unaligned data items on aligned (longword)
* boundaries.
*/
extern void db_read_bytes(); /* machine-dependent */
extern void db_write_bytes(); /* machine-dependent */
int db_extend[] = { /* table for sign-extending */
0,
0xFFFFFF80,
0xFFFF8000,
0xFF800000
};
db_expr_t
db_get_value(addr, size, is_signed)
db_addr_t addr;
register int size;
boolean_t is_signed;
{
char data[sizeof(int)];
register db_expr_t value;
register int i;
db_read_bytes(addr, size, data);
value = 0;
#if BYTE_MSF
for (i = 0; i < size; i++)
#else /* BYTE_LSF */
for (i = size - 1; i >= 0; i--)
#endif
{
value = (value << 8) + (data[i] & 0xFF);
}
if (size < 4) {
if (is_signed && (value & db_extend[size]) != 0)
value |= db_extend[size];
}
return (value);
}
void
db_put_value(addr, size, value)
db_addr_t addr;
register int size;
register db_expr_t value;
{
char data[sizeof(int)];
register int i;
#if BYTE_MSF
for (i = size - 1; i >= 0; i--)
#else /* BYTE_LSF */
for (i = 0; i < size; i++)
#endif
{
data[i] = value & 0xFF;
value >>= 8;
}
db_write_bytes(addr, size, data);
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_access.h,v $
* Revision 1.1 1992/03/25 21:44:53 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:05:49 mrt
* Changed to new Mach copyright
* [91/01/31 16:16:37 mrt]
*
* Revision 2.2 90/08/27 21:48:27 dbg
* Created.
* [90/08/07 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Data access functions for debugger.
*/
#include <machine/db_machdep.h> /* expression types */
extern db_expr_t db_get_value(/* db_addr_t addr,
int size,
boolean_t is_signed */);
extern void db_put_value(/* db_addr_t addr,
int size,
db_expr_t value */);
+309
View File
@@ -0,0 +1,309 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_aout.c,v $
* Revision 1.1 1992/03/25 21:44:55 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:05:55 mrt
* Changed to new Mach copyright
* [91/01/31 16:16:44 mrt]
*
* Revision 2.2 90/08/27 21:48:35 dbg
* Created.
* [90/08/17 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Symbol table routines for a.out format files.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h> /* data types */
#include <ddb/db_sym.h>
#ifndef DB_NO_AOUT
#define _AOUT_INCLUDE_
#include "nlist.h"
/*
* An a.out symbol table as loaded into the kernel debugger:
*
* symtab -> size of symbol entries, in bytes
* sp -> first symbol entry
* ...
* ep -> last symbol entry + 1
* strtab == start of string table
* size of string table in bytes,
* including this word
* -> strings
*/
/*
* Find pointers to the start and end of the symbol entries,
* given a pointer to the start of the symbol table.
*/
#define db_get_aout_symtab(symtab, sp, ep) \
(sp = (struct nlist *)((symtab) + 1), \
ep = (struct nlist *)((char *)sp + *(symtab)))
#define SYMTAB_SPACE 63000
int db_symtabsize = SYMTAB_SPACE;
char db_symtab[SYMTAB_SPACE] = { 1 };
X_db_sym_init(symtab, esymtab, name)
int * symtab; /* pointer to start of symbol table */
char * esymtab; /* pointer to end of string table,
for checking - rounded up to integer
boundary */
char * name;
{
register struct nlist *sym_start, *sym_end;
register struct nlist *sp;
register char * strtab;
register int strlen;
if (*symtab < 4) {
printf ("DDB: no symbols\n");
return;
}
db_get_aout_symtab(symtab, sym_start, sym_end);
strtab = (char *)sym_end;
strlen = *(int *)strtab;
#if 0
if (strtab + ((strlen + sizeof(int) - 1) & ~(sizeof(int)-1))
!= esymtab)
{
db_printf("[ %s symbol table not valid ]\n", name);
return;
}
db_printf("[ preserving %#x bytes of %s symbol table ]\n",
esymtab - (char *)symtab, name);
#endif
for (sp = sym_start; sp < sym_end; sp++) {
register int strx;
strx = sp->n_un.n_strx;
if (strx != 0) {
if (strx > strlen) {
db_printf("Bad string table index (%#x)\n", strx);
sp->n_un.n_name = 0;
continue;
}
sp->n_un.n_name = strtab + strx;
}
}
db_add_symbol_table(sym_start, sym_end, name, (char *)symtab);
}
db_sym_t
X_db_lookup(stab, symstr)
db_symtab_t *stab;
char * symstr;
{
register struct nlist *sp, *ep;
sp = (struct nlist *)stab->start;
ep = (struct nlist *)stab->end;
for (; sp < ep; sp++) {
if (sp->n_un.n_name == 0)
continue;
if ((sp->n_type & N_STAB) == 0 &&
sp->n_un.n_name != 0 &&
db_eqname(sp->n_un.n_name, symstr, '_'))
{
return ((db_sym_t)sp);
}
}
return ((db_sym_t)0);
}
db_sym_t
X_db_search_symbol(symtab, off, strategy, diffp)
db_symtab_t * symtab;
register
db_addr_t off;
db_strategy_t strategy;
db_expr_t *diffp; /* in/out */
{
register unsigned int diff = *diffp;
register struct nlist *symp = 0;
register struct nlist *sp, *ep;
sp = (struct nlist *)symtab->start;
ep = (struct nlist *)symtab->end;
for (; sp < ep; sp++) {
if (sp->n_un.n_name == 0)
continue;
if ((sp->n_type & N_STAB) != 0)
continue;
if (off >= sp->n_value) {
if (off - sp->n_value < diff) {
diff = off - sp->n_value;
symp = sp;
if (diff == 0)
break;
}
else if (off - sp->n_value == diff) {
if (symp == 0)
symp = sp;
else if ((symp->n_type & N_EXT) == 0 &&
(sp->n_type & N_EXT) != 0)
symp = sp; /* pick the external symbol */
}
}
}
if (symp == 0) {
*diffp = off;
}
else {
*diffp = diff;
}
return ((db_sym_t)symp);
}
/*
* Return the name and value for a symbol.
*/
void
X_db_symbol_values(sym, namep, valuep)
db_sym_t sym;
char **namep;
db_expr_t *valuep;
{
register struct nlist *sp;
sp = (struct nlist *)sym;
if (namep)
*namep = sp->n_un.n_name;
if (valuep)
*valuep = sp->n_value;
}
boolean_t
X_db_line_at_pc()
{
return (FALSE);
}
/*
* Initialization routine for a.out files.
*/
kdb_init()
{
#if 0
extern char *esym;
extern int end;
if (esym > (char *)&end) {
X_db_sym_init((int *)&end, esym, "mach");
}
#endif
X_db_sym_init (db_symtab, 0, "mach");
}
#if 0
/*
* Read symbol table from file.
* (should be somewhere else)
*/
#include <boot_ufs/file_io.h>
#include <vm/vm_kern.h>
read_symtab_from_file(fp, symtab_name)
struct file *fp;
char * symtab_name;
{
vm_size_t resid;
kern_return_t result;
vm_offset_t symoff;
vm_size_t symsize;
vm_offset_t stroff;
vm_size_t strsize;
vm_size_t table_size;
vm_offset_t symtab;
if (!get_symtab(fp, &symoff, &symsize)) {
boot_printf("[ error %d reading %s file header ]\n",
result, symtab_name);
return;
}
stroff = symoff + symsize;
result = read_file(fp, (vm_offset_t)stroff,
(vm_offset_t)&strsize, sizeof(strsize), &resid);
if (result || resid) {
boot_printf("[ no valid symbol table present for %s ]\n",
symtab_name);
return;
}
table_size = sizeof(int) + symsize + strsize;
table_size = (table_size + sizeof(int)-1) & ~(sizeof(int)-1);
symtab = kmem_alloc_wired(kernel_map, table_size);
*(int *)symtab = symsize;
result = read_file(fp, symoff,
symtab + sizeof(int), symsize, &resid);
if (result || resid) {
boot_printf("[ error %d reading %s symbol table ]\n",
result, symtab_name);
return;
}
result = read_file(fp, stroff,
symtab + sizeof(int) + symsize, strsize, &resid);
if (result || resid) {
boot_printf("[ error %d reading %s string table ]\n",
result, symtab_name);
return;
}
X_db_sym_init((int *)symtab,
(char *)(symtab + table_size),
symtab_name);
}
#endif
#endif /* DB_NO_AOUT */
+387
View File
@@ -0,0 +1,387 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_break.c,v $
* Revision 1.1 1992/03/25 21:44:57 pace
* Initial revision
*
* Revision 2.7 91/02/05 17:06:00 mrt
* Changed to new Mach copyright
* [91/01/31 16:17:01 mrt]
*
* Revision 2.6 91/01/08 15:09:03 rpd
* Added db_map_equal, db_map_current, db_map_addr.
* [90/11/10 rpd]
*
* Revision 2.5 90/11/05 14:26:32 rpd
* Initialize db_breakpoints_inserted to TRUE.
* [90/11/04 rpd]
*
* Revision 2.4 90/10/25 14:43:33 rwd
* Added map field to breakpoints.
* Added map argument to db_set_breakpoint, db_delete_breakpoint,
* db_find_breakpoint. Added db_find_breakpoint_here.
* [90/10/18 rpd]
*
* Revision 2.3 90/09/28 16:57:07 jsb
* Fixed db_breakpoint_free.
* [90/09/18 rpd]
*
* Revision 2.2 90/08/27 21:49:53 dbg
* Reflected changes in db_printsym()'s calling seq.
* [90/08/20 af]
* Clear breakpoints only if inserted.
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Breakpoints.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h> /* type definitions */
#include <ddb/db_lex.h>
#include <ddb/db_break.h>
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <ddb/db_break.h>
extern boolean_t db_map_equal();
extern boolean_t db_map_current();
extern vm_map_t db_map_addr();
#define NBREAKPOINTS 100
struct db_breakpoint db_break_table[NBREAKPOINTS];
db_breakpoint_t db_next_free_breakpoint = &db_break_table[0];
db_breakpoint_t db_free_breakpoints = 0;
db_breakpoint_t db_breakpoint_list = 0;
db_breakpoint_t
db_breakpoint_alloc()
{
register db_breakpoint_t bkpt;
if ((bkpt = db_free_breakpoints) != 0) {
db_free_breakpoints = bkpt->link;
return (bkpt);
}
if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) {
db_printf("All breakpoints used.\n");
return (0);
}
bkpt = db_next_free_breakpoint;
db_next_free_breakpoint++;
return (bkpt);
}
void
db_breakpoint_free(bkpt)
register db_breakpoint_t bkpt;
{
bkpt->link = db_free_breakpoints;
db_free_breakpoints = bkpt;
}
void
db_set_breakpoint(map, addr, count)
vm_map_t map;
db_addr_t addr;
int count;
{
register db_breakpoint_t bkpt;
if (db_find_breakpoint(map, addr)) {
db_printf("Already set.\n");
return;
}
bkpt = db_breakpoint_alloc();
if (bkpt == 0) {
db_printf("Too many breakpoints.\n");
return;
}
bkpt->map = map;
bkpt->address = addr;
bkpt->flags = 0;
bkpt->init_count = count;
bkpt->count = count;
bkpt->link = db_breakpoint_list;
db_breakpoint_list = bkpt;
}
void
db_delete_breakpoint(map, addr)
vm_map_t map;
db_addr_t addr;
{
register db_breakpoint_t bkpt;
register db_breakpoint_t *prev;
for (prev = &db_breakpoint_list;
(bkpt = *prev) != 0;
prev = &bkpt->link) {
if (db_map_equal(bkpt->map, map) &&
(bkpt->address == addr)) {
*prev = bkpt->link;
break;
}
}
if (bkpt == 0) {
db_printf("Not set.\n");
return;
}
db_breakpoint_free(bkpt);
}
db_breakpoint_t
db_find_breakpoint(map, addr)
vm_map_t map;
db_addr_t addr;
{
register db_breakpoint_t bkpt;
for (bkpt = db_breakpoint_list;
bkpt != 0;
bkpt = bkpt->link)
{
if (db_map_equal(bkpt->map, map) &&
(bkpt->address == addr))
return (bkpt);
}
return (0);
}
db_breakpoint_t
db_find_breakpoint_here(addr)
db_addr_t addr;
{
return db_find_breakpoint(db_map_addr(addr), addr);
}
boolean_t db_breakpoints_inserted = TRUE;
void
db_set_breakpoints()
{
register db_breakpoint_t bkpt;
if (!db_breakpoints_inserted) {
for (bkpt = db_breakpoint_list;
bkpt != 0;
bkpt = bkpt->link)
if (db_map_current(bkpt->map)) {
bkpt->bkpt_inst = db_get_value(bkpt->address,
BKPT_SIZE,
FALSE);
db_put_value(bkpt->address,
BKPT_SIZE,
BKPT_SET(bkpt->bkpt_inst));
}
db_breakpoints_inserted = TRUE;
}
}
void
db_clear_breakpoints()
{
register db_breakpoint_t bkpt;
if (db_breakpoints_inserted) {
for (bkpt = db_breakpoint_list;
bkpt != 0;
bkpt = bkpt->link)
if (db_map_current(bkpt->map)) {
db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
}
db_breakpoints_inserted = FALSE;
}
}
/*
* Set a temporary breakpoint.
* The instruction is changed immediately,
* so the breakpoint does not have to be on the breakpoint list.
*/
db_breakpoint_t
db_set_temp_breakpoint(addr)
db_addr_t addr;
{
register db_breakpoint_t bkpt;
bkpt = db_breakpoint_alloc();
if (bkpt == 0) {
db_printf("Too many breakpoints.\n");
return 0;
}
bkpt->map = NULL;
bkpt->address = addr;
bkpt->flags = BKPT_TEMP;
bkpt->init_count = 1;
bkpt->count = 1;
bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE);
db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst));
return bkpt;
}
void
db_delete_temp_breakpoint(bkpt)
db_breakpoint_t bkpt;
{
db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
db_breakpoint_free(bkpt);
}
/*
* List breakpoints.
*/
void
db_list_breakpoints()
{
register db_breakpoint_t bkpt;
if (db_breakpoint_list == 0) {
db_printf("No breakpoints set\n");
return;
}
db_printf(" Map Count Address\n");
for (bkpt = db_breakpoint_list;
bkpt != 0;
bkpt = bkpt->link)
{
db_printf("%s%8x %5d ",
db_map_current(bkpt->map) ? "*" : " ",
bkpt->map, bkpt->init_count);
db_printsym(bkpt->address, DB_STGY_PROC);
db_printf("\n");
}
}
/* Delete breakpoint */
/*ARGSUSED*/
void
db_delete_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr);
}
/* Set breakpoint with skip count */
/*ARGSUSED*/
void
db_breakpoint_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
if (count == -1)
count = 1;
db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count);
}
/* list breakpoints */
void
db_listbreak_cmd()
{
db_list_breakpoints();
}
#include <vm/vm_kern.h>
/*
* We want ddb to be usable before most of the kernel has been
* initialized. In particular, current_thread() or kernel_map
* (or both) may be null.
*/
boolean_t
db_map_equal(map1, map2)
vm_map_t map1, map2;
{
return ((map1 == map2) ||
((map1 == NULL) && (map2 == kernel_map)) ||
((map1 == kernel_map) && (map2 == NULL)));
}
boolean_t
db_map_current(map)
vm_map_t map;
{
#if 0
thread_t thread;
return ((map == NULL) ||
(map == kernel_map) ||
(((thread = current_thread()) != NULL) &&
(map == thread->task->map)));
#else
return (1);
#endif
}
vm_map_t
db_map_addr(addr)
vm_offset_t addr;
{
#if 0
thread_t thread;
/*
* We want to return kernel_map for all
* non-user addresses, even when debugging
* kernel tasks with their own maps.
*/
if ((VM_MIN_ADDRESS <= addr) &&
(addr < VM_MAX_ADDRESS) &&
((thread = current_thread()) != NULL))
return thread->task->map;
else
#endif
return kernel_map;
}
+84
View File
@@ -0,0 +1,84 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_break.h,v $
* Revision 1.1 1992/03/25 21:44:59 pace
* Initial revision
*
* Revision 2.4 91/02/05 17:06:06 mrt
* Changed to new Mach copyright
* [91/01/31 16:17:10 mrt]
*
* Revision 2.3 90/10/25 14:43:40 rwd
* Added map field to breakpoints.
* [90/10/18 rpd]
*
* Revision 2.2 90/08/27 21:50:00 dbg
* Modularized typedef names.
* [90/08/20 af]
* Add external defintions.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#ifndef _DDB_DB_BREAK_H_
#define _DDB_DB_BREAK_H_
#include <vm/vm_map.h>
#include <machine/db_machdep.h>
/*
* Breakpoint.
*/
struct db_breakpoint {
vm_map_t map; /* in this map */
db_addr_t address; /* set here */
int init_count; /* number of times to skip bkpt */
int count; /* current count */
int flags; /* flags: */
#define BKPT_SINGLE_STEP 0x2 /* to simulate single step */
#define BKPT_TEMP 0x4 /* temporary */
int bkpt_inst; /* saved instruction at bkpt */
struct db_breakpoint *link; /* link in in-use or free chain */
};
typedef struct db_breakpoint *db_breakpoint_t;
extern db_breakpoint_t db_find_breakpoint();
extern db_breakpoint_t db_find_breakpoint_here();
extern void db_set_breakpoints();
extern void db_clear_breakpoints();
extern db_breakpoint_t db_set_temp_breakpoint(/* db_addr_t addr */);
extern void db_delete_temp_breakpoint(/* db_breakpoint_t bkpt */);
#endif _DDB_DB_BREAK_H_
+526
View File
@@ -0,0 +1,526 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_command.c,v $
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00081
* -------------------- ----- ----------------------
*
* 01 Feb 93 Julian Elischer move strcmp to a more general
* part of the kernel.
*
* Revision 1.1 1992/03/25 21:45:02 pace
* Initial revision
*
* Revision 2.6 91/02/05 17:06:10 mrt
* Changed to new Mach copyright
* [91/01/31 16:17:18 mrt]
*
* Revision 2.5 91/01/08 17:31:54 rpd
* Forward reference for db_fncall();
* [91/01/04 12:35:17 rvb]
*
* Add call as a synonym for ! and match for next
* [91/01/04 12:14:48 rvb]
*
* Revision 2.4 90/11/07 16:49:15 rpd
* Added search.
* [90/11/06 rpd]
*
* Revision 2.3 90/10/25 14:43:45 rwd
* Changed db_fncall to print the result unsigned.
* [90/10/19 rpd]
*
* Added CS_MORE to db_watchpoint_cmd.
* [90/10/17 rpd]
* Added watchpoint commands: watch, dwatch, show watches.
* [90/10/16 rpd]
*
* Revision 2.2 90/08/27 21:50:10 dbg
* Remove 'listbreaks' - use 'show breaks' instead. Change 'show
* threads' to 'show all threads' to avoid clash with 'show thread'.
* Set 'dot' here from db_prev or db_next, depending on 'db_ed_style'
* flag and syntax table.
* [90/08/22 dbg]
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Command dispatcher.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h> /* type definitions */
#include <ddb/db_lex.h>
#include <ddb/db_output.h>
#include <setjmp.h>
/*
* Exported global variables
*/
boolean_t db_cmd_loop_done;
jmp_buf db_jmpbuf;
db_addr_t db_dot;
db_addr_t db_last_addr;
db_addr_t db_prev;
db_addr_t db_next;
/*
* if 'ed' style: 'dot' is set at start of last item printed,
* and '+' points to next line.
* Otherwise: 'dot' points to next item, '..' points to last.
*/
boolean_t db_ed_style = TRUE;
/*
* Utility routine - discard tokens through end-of-line.
*/
void
db_skip_to_eol()
{
int t;
do {
t = db_read_token();
} while (t != tEOL);
}
/*
* Command table
*/
struct command {
char * name; /* command name */
void (*fcn)(); /* function to call */
int flag; /* extra info: */
#define CS_OWN 0x1 /* non-standard syntax */
#define CS_MORE 0x2 /* standard syntax, but may have other
words at end */
#define CS_SET_DOT 0x100 /* set dot after command */
struct command *more; /* another level of command */
};
/*
* Results of command search.
*/
#define CMD_UNIQUE 0
#define CMD_FOUND 1
#define CMD_NONE 2
#define CMD_AMBIGUOUS 3
#define CMD_HELP 4
/*
* Search for command prefix.
*/
int
db_cmd_search(name, table, cmdp)
char * name;
struct command *table;
struct command **cmdp; /* out */
{
struct command *cmd;
int result = CMD_NONE;
for (cmd = table; cmd->name != 0; cmd++) {
register char *lp;
register char *rp;
register int c;
lp = name;
rp = cmd->name;
while ((c = *lp) == *rp) {
if (c == 0) {
/* complete match */
*cmdp = cmd;
return (CMD_UNIQUE);
}
lp++;
rp++;
}
if (c == 0) {
/* end of name, not end of command -
partial match */
if (result == CMD_FOUND) {
result = CMD_AMBIGUOUS;
/* but keep looking for a full match -
this lets us match single letters */
}
else {
*cmdp = cmd;
result = CMD_FOUND;
}
}
}
if (result == CMD_NONE) {
/* check for 'help' */
if (name[0] == 'h' && name[1] == 'e'
&& name[2] == 'l' && name[3] == 'p')
result = CMD_HELP;
}
return (result);
}
void
db_cmd_list(table)
struct command *table;
{
register struct command *cmd;
for (cmd = table; cmd->name != 0; cmd++) {
db_printf("%-12s", cmd->name);
db_end_line();
}
}
void
db_command(last_cmdp, cmd_table)
struct command **last_cmdp; /* IN_OUT */
struct command *cmd_table;
{
struct command *cmd;
int t;
char modif[TOK_STRING_SIZE];
db_expr_t addr, count;
boolean_t have_addr;
int result;
t = db_read_token();
if (t == tEOL) {
/* empty line repeats last command, at 'next' */
cmd = *last_cmdp;
addr = (db_expr_t)db_next;
have_addr = FALSE;
count = 1;
modif[0] = '\0';
}
else if (t == tEXCL) {
void db_fncall();
db_fncall();
return;
}
else if (t != tIDENT) {
db_printf("?\n");
db_flush_lex();
return;
}
else {
/*
* Search for command
*/
while (cmd_table) {
result = db_cmd_search(db_tok_string,
cmd_table,
&cmd);
switch (result) {
case CMD_NONE:
db_printf("No such command\n");
db_flush_lex();
return;
case CMD_AMBIGUOUS:
db_printf("Ambiguous\n");
db_flush_lex();
return;
case CMD_HELP:
db_cmd_list(cmd_table);
db_flush_lex();
return;
default:
break;
}
if ((cmd_table = cmd->more) != 0) {
t = db_read_token();
if (t != tIDENT) {
db_cmd_list(cmd_table);
db_flush_lex();
return;
}
}
}
if ((cmd->flag & CS_OWN) == 0) {
/*
* Standard syntax:
* command [/modifier] [addr] [,count]
*/
t = db_read_token();
if (t == tSLASH) {
t = db_read_token();
if (t != tIDENT) {
db_printf("Bad modifier\n");
db_flush_lex();
return;
}
db_strcpy(modif, db_tok_string);
}
else {
db_unread_token(t);
modif[0] = '\0';
}
if (db_expression(&addr)) {
db_dot = (db_addr_t) addr;
db_last_addr = db_dot;
have_addr = TRUE;
}
else {
addr = (db_expr_t) db_dot;
have_addr = FALSE;
}
t = db_read_token();
if (t == tCOMMA) {
if (!db_expression(&count)) {
db_printf("Count missing\n");
db_flush_lex();
return;
}
}
else {
db_unread_token(t);
count = -1;
}
if ((cmd->flag & CS_MORE) == 0) {
db_skip_to_eol();
}
}
}
*last_cmdp = cmd;
if (cmd != 0) {
/*
* Execute the command.
*/
(*cmd->fcn)(addr, have_addr, count, modif);
if (cmd->flag & CS_SET_DOT) {
/*
* If command changes dot, set dot to
* previous address displayed (if 'ed' style).
*/
if (db_ed_style) {
db_dot = db_prev;
}
else {
db_dot = db_next;
}
}
else {
/*
* If command does not change dot,
* set 'next' location to be the same.
*/
db_next = db_dot;
}
}
}
/*
* 'show' commands
*/
extern void db_listbreak_cmd();
extern void db_listwatch_cmd();
extern void db_show_regs(), db_show_one_thread(), db_show_all_threads();
extern void vm_map_print(), vm_object_print(), vm_page_print();
extern void ipc_port_print();
void db_show_help();
struct command db_show_all_cmds[] = {
#if 0
{ "threads", db_show_all_threads,0, 0 },
#endif
{ (char *)0 }
};
struct command db_show_cmds[] = {
{ "all", 0, 0, db_show_all_cmds },
{ "registers", db_show_regs, 0, 0 },
{ "breaks", db_listbreak_cmd, 0, 0 },
{ "watches", db_listwatch_cmd, 0, 0 },
#if 0
{ "thread", db_show_one_thread, 0, 0 },
#endif
{ "map", vm_map_print, 0, 0 },
{ "object", vm_object_print, 0, 0 },
#if 0
{ "page", vm_page_print, 0, 0 },
#endif
#if 0
{ "port", ipc_port_print, 0, 0 },
#endif
{ (char *)0, }
};
extern void db_print_cmd(), db_examine_cmd(), db_set_cmd();
extern void db_search_cmd();
extern void db_write_cmd();
extern void db_delete_cmd(), db_breakpoint_cmd();
extern void db_deletewatch_cmd(), db_watchpoint_cmd();
extern void db_single_step_cmd(), db_trace_until_call_cmd(),
db_trace_until_matching_cmd(), db_continue_cmd();
extern void db_stack_trace_cmd();
void db_help_cmd();
void db_fncall();
struct command db_command_table[] = {
{ "print", db_print_cmd, 0, 0 },
{ "examine", db_examine_cmd, CS_SET_DOT, 0 },
{ "x", db_examine_cmd, CS_SET_DOT, 0 },
{ "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 },
{ "set", db_set_cmd, CS_OWN, 0 },
{ "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
{ "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
{ "delete", db_delete_cmd, 0, 0 },
{ "d", db_delete_cmd, 0, 0 },
{ "break", db_breakpoint_cmd, 0, 0 },
{ "dwatch", db_deletewatch_cmd, 0, 0 },
{ "watch", db_watchpoint_cmd, CS_MORE,0 },
{ "step", db_single_step_cmd, 0, 0 },
{ "s", db_single_step_cmd, 0, 0 },
{ "continue", db_continue_cmd, 0, 0 },
{ "c", db_continue_cmd, 0, 0 },
{ "until", db_trace_until_call_cmd,0, 0 },
{ "next", db_trace_until_matching_cmd,0, 0 },
{ "match", db_trace_until_matching_cmd,0, 0 },
{ "trace", db_stack_trace_cmd, 0, 0 },
{ "call", db_fncall, CS_OWN, 0 },
{ "show", 0, 0, db_show_cmds },
{ (char *)0, }
};
struct command *db_last_command = 0;
void
db_help_cmd()
{
struct command *cmd = db_command_table;
while (cmd->name != 0) {
db_printf("%-12s", cmd->name);
db_end_line();
cmd++;
}
}
void
db_command_loop()
{
/*
* Initialize 'prev' and 'next' to dot.
*/
db_prev = db_dot;
db_next = db_dot;
db_cmd_loop_done = 0;
while (!db_cmd_loop_done) {
(void) setjmp(db_jmpbuf);
if (db_print_position() != 0)
db_printf("\n");
db_printf("db> ");
(void) db_read_line();
db_command(&db_last_command, db_command_table);
}
}
void
db_error(s)
char *s;
{
if (s)
db_printf(s);
db_flush_lex();
longjmp(db_jmpbuf, 1);
}
/*
* Call random function:
* !expr(arg,arg,arg)
*/
void
db_fncall()
{
db_expr_t fn_addr;
#define MAXARGS 11
db_expr_t args[MAXARGS];
int nargs = 0;
db_expr_t retval;
db_expr_t (*func)();
int t;
if (!db_expression(&fn_addr)) {
db_printf("Bad function\n");
db_flush_lex();
return;
}
func = (db_expr_t (*) ()) fn_addr;
t = db_read_token();
if (t == tLPAREN) {
if (db_expression(&args[0])) {
nargs++;
while ((t = db_read_token()) == tCOMMA) {
if (nargs == MAXARGS) {
db_printf("Too many arguments\n");
db_flush_lex();
return;
}
if (!db_expression(&args[nargs])) {
db_printf("Argument missing\n");
db_flush_lex();
return;
}
nargs++;
}
db_unread_token(t);
}
if (db_read_token() != tRPAREN) {
db_printf("?\n");
db_flush_lex();
return;
}
}
db_skip_to_eol();
while (nargs < MAXARGS) {
args[nargs++] = 0;
}
retval = (*func)(args[0], args[1], args[2], args[3], args[4],
args[5], args[6], args[7], args[8], args[9] );
db_printf("%#n\n", retval);
}
+67
View File
@@ -0,0 +1,67 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_command.h,v $
* Revision 1.1 1992/03/25 21:45:05 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:06:15 mrt
* Changed to new Mach copyright
* [91/01/31 16:17:28 mrt]
*
* Revision 2.2 90/08/27 21:50:19 dbg
* Replace db_last_address_examined with db_prev, db_next.
* [90/08/22 dbg]
* Created.
* [90/08/07 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Command loop declarations.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
extern void db_command_loop();
extern void db_skip_to_eol();
extern void db_error(/* char * */); /* report error */
extern db_addr_t db_dot; /* current location */
extern db_addr_t db_last_addr; /* last explicit address typed */
extern db_addr_t db_prev; /* last address examined
or written */
extern db_addr_t db_next; /* next address to be examined
or written */
+364
View File
@@ -0,0 +1,364 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_examine.c,v $
* Revision 1.1 1992/03/25 21:45:07 pace
* Initial revision
*
* Revision 2.4 91/02/05 17:06:20 mrt
* Changed to new Mach copyright
* [91/01/31 16:17:37 mrt]
*
* Revision 2.3 90/11/07 16:49:23 rpd
* Added db_search_cmd, db_search.
* [90/11/06 rpd]
*
* Revision 2.2 90/08/27 21:50:38 dbg
* Add 'r', 'z' to print and examine formats.
* Change calling sequence of db_disasm.
* db_examine sets db_prev and db_next instead of explicitly
* advancing dot.
* [90/08/20 dbg]
* Reflected changes in db_printsym()'s calling seq.
* [90/08/20 af]
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h> /* type definitions */
#include <ddb/db_lex.h>
#include <ddb/db_output.h>
#include <ddb/db_command.h>
#include <ddb/db_sym.h>
char db_examine_format[TOK_STRING_SIZE] = "x";
extern db_addr_t db_disasm(/* db_addr_t, boolean_t */);
/* instruction disassembler */
/*
* Examine (print) data.
*/
/*ARGSUSED*/
void
db_examine_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
if (modif[0] != '\0')
db_strcpy(db_examine_format, modif);
if (count == -1)
count = 1;
db_examine((db_addr_t) addr, db_examine_format, count);
}
db_examine(addr, fmt, count)
register
db_addr_t addr;
char * fmt; /* format string */
int count; /* repeat count */
{
int c;
db_expr_t value;
int size;
int width;
char * fp;
while (--count >= 0) {
fp = fmt;
size = 4;
width = 16;
while ((c = *fp++) != 0) {
switch (c) {
case 'b':
size = 1;
width = 4;
break;
case 'h':
size = 2;
width = 8;
break;
case 'l':
size = 4;
width = 16;
break;
case 'a': /* address */
/* always forces a new line */
if (db_print_position() != 0)
db_printf("\n");
db_prev = addr;
db_printsym(addr, DB_STGY_ANY);
db_printf(":\t");
break;
default:
if (db_print_position() == 0) {
/* If we hit a new symbol, print it */
char * name;
db_expr_t off;
db_find_sym_and_offset(addr, &name, &off);
if (off == 0)
db_printf("%s:\t", name);
else
db_printf("\t\t");
db_prev = addr;
}
switch (c) {
case 'r': /* signed, current radix */
value = db_get_value(addr, size, TRUE);
addr += size;
db_printf("%-*r", width, value);
break;
case 'x': /* unsigned hex */
value = db_get_value(addr, size, FALSE);
addr += size;
db_printf("%-*x", width, value);
break;
case 'z': /* signed hex */
value = db_get_value(addr, size, TRUE);
addr += size;
db_printf("%-*z", width, value);
break;
case 'd': /* signed decimal */
value = db_get_value(addr, size, TRUE);
addr += size;
db_printf("%-*d", width, value);
break;
case 'u': /* unsigned decimal */
value = db_get_value(addr, size, FALSE);
addr += size;
db_printf("%-*u", width, value);
break;
case 'o': /* unsigned octal */
value = db_get_value(addr, size, FALSE);
addr += size;
db_printf("%-*o", width, value);
break;
case 'c': /* character */
value = db_get_value(addr, 1, FALSE);
addr += 1;
if (value >= ' ' && value <= '~')
db_printf("%c", value);
else
db_printf("\\%03o", value);
break;
case 's': /* null-terminated string */
for (;;) {
value = db_get_value(addr, 1, FALSE);
addr += 1;
if (value == 0)
break;
if (value >= ' ' && value <= '~')
db_printf("%c", value);
else
db_printf("\\%03o", value);
}
break;
case 'i': /* instruction */
addr = db_disasm(addr, FALSE);
break;
case 'I': /* instruction, alternate form */
addr = db_disasm(addr, TRUE);
break;
default:
break;
}
if (db_print_position() != 0)
db_end_line();
break;
}
}
}
db_next = addr;
}
/*
* Print value.
*/
char db_print_format = 'x';
/*ARGSUSED*/
void
db_print_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
db_expr_t value;
if (modif[0] != '\0')
db_print_format = modif[0];
switch (db_print_format) {
case 'a':
db_printsym((db_addr_t)addr, DB_STGY_ANY);
break;
case 'r':
db_printf("%11r", addr);
break;
case 'x':
db_printf("%8x", addr);
break;
case 'z':
db_printf("%8z", addr);
break;
case 'd':
db_printf("%11d", addr);
break;
case 'u':
db_printf("%11u", addr);
break;
case 'o':
db_printf("%16o", addr);
break;
case 'c':
value = addr & 0xFF;
if (value >= ' ' && value <= '~')
db_printf("%c", value);
else
db_printf("\\%03o", value);
break;
}
db_printf("\n");
}
db_print_loc_and_inst(loc)
db_addr_t loc;
{
db_printsym(loc, DB_STGY_PROC);
db_printf(":\t");
(void) db_disasm(loc, TRUE);
}
db_strcpy(dst, src)
register char *dst;
register char *src;
{
while (*dst++ = *src++)
;
}
/*
* Search for a value in memory.
* Syntax: search [/bhl] addr value [mask] [,count]
*/
void
db_search_cmd()
{
int t;
db_addr_t addr;
int size;
db_expr_t value;
db_expr_t mask;
unsigned int count;
t = db_read_token();
if (t == tSLASH) {
t = db_read_token();
if (t != tIDENT) {
bad_modifier:
db_printf("Bad modifier\n");
db_flush_lex();
return;
}
if (!strcmp(db_tok_string, "b"))
size = 1;
else if (!strcmp(db_tok_string, "h"))
size = 2;
else if (!strcmp(db_tok_string, "l"))
size = 4;
else
goto bad_modifier;
} else {
db_unread_token(t);
size = 4;
}
if (!db_expression(&addr)) {
db_printf("Address missing\n");
db_flush_lex();
return;
}
if (!db_expression(&value)) {
db_printf("Value missing\n");
db_flush_lex();
return;
}
if (!db_expression(&mask))
mask = 0xffffffff;
t = db_read_token();
if (t == tCOMMA) {
if (!db_expression(&count)) {
db_printf("Count missing\n");
db_flush_lex();
return;
}
} else {
db_unread_token(t);
count = -1; /* effectively forever */
}
db_skip_to_eol();
db_search(addr, size, value, mask, count);
}
db_search(addr, size, value, mask, count)
register
db_addr_t addr;
int size;
db_expr_t value;
db_expr_t mask;
unsigned int count;
{
while (count-- != 0) {
db_prev = addr;
if ((db_get_value(addr, size, FALSE) & mask) == value)
break;
addr += size;
}
db_next = addr;
}
+248
View File
@@ -0,0 +1,248 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_expr.c,v $
* Revision 1.1 1992/03/25 21:45:09 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:06:25 mrt
* Changed to new Mach copyright
* [91/01/31 16:17:46 mrt]
*
* Revision 2.2 90/08/27 21:50:57 dbg
* Use '..' instead of '$$' for db_prev.
* Use '+' for db_next.
* [90/08/22 dbg]
*
* Allow repeated unary operators.
* [90/08/20 dbg]
*
* Reflected back rename of db_symbol_value->db_value_of_name
* [90/08/20 af]
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_lex.h>
#include <ddb/db_access.h>
#include <ddb/db_command.h>
boolean_t
db_term(valuep)
db_expr_t *valuep;
{
int t;
t = db_read_token();
if (t == tIDENT) {
if (!db_value_of_name(db_tok_string, valuep)) {
db_error("Symbol not found\n");
/*NOTREACHED*/
}
return (TRUE);
}
if (t == tNUMBER) {
*valuep = (db_expr_t)db_tok_number;
return (TRUE);
}
if (t == tDOT) {
*valuep = (db_expr_t)db_dot;
return (TRUE);
}
if (t == tDOTDOT) {
*valuep = (db_expr_t)db_prev;
return (TRUE);
}
if (t == tPLUS) {
*valuep = (db_expr_t) db_next;
return (TRUE);
}
if (t == tDITTO) {
*valuep = (db_expr_t)db_last_addr;
return (TRUE);
}
if (t == tDOLLAR) {
if (!db_get_variable(valuep))
return (FALSE);
return (TRUE);
}
if (t == tLPAREN) {
if (!db_expression(valuep)) {
db_error("Syntax error\n");
/*NOTREACHED*/
}
t = db_read_token();
if (t != tRPAREN) {
db_error("Syntax error\n");
/*NOTREACHED*/
}
return (TRUE);
}
db_unread_token(t);
return (FALSE);
}
boolean_t
db_unary(valuep)
db_expr_t *valuep;
{
int t;
t = db_read_token();
if (t == tMINUS) {
if (!db_unary(valuep)) {
db_error("Syntax error\n");
/*NOTREACHED*/
}
*valuep = -*valuep;
return (TRUE);
}
if (t == tSTAR) {
/* indirection */
if (!db_unary(valuep)) {
db_error("Syntax error\n");
/*NOTREACHED*/
}
*valuep = db_get_value((db_addr_t)*valuep, sizeof(int), FALSE);
return (TRUE);
}
db_unread_token(t);
return (db_term(valuep));
}
boolean_t
db_mult_expr(valuep)
db_expr_t *valuep;
{
db_expr_t lhs, rhs;
int t;
if (!db_unary(&lhs))
return (FALSE);
t = db_read_token();
while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) {
if (!db_term(&rhs)) {
db_error("Syntax error\n");
/*NOTREACHED*/
}
if (t == tSTAR)
lhs *= rhs;
else {
if (rhs == 0) {
db_error("Divide by 0\n");
/*NOTREACHED*/
}
if (t == tSLASH)
lhs /= rhs;
else if (t == tPCT)
lhs %= rhs;
else
lhs = ((lhs+rhs-1)/rhs)*rhs;
}
t = db_read_token();
}
db_unread_token(t);
*valuep = lhs;
return (TRUE);
}
boolean_t
db_add_expr(valuep)
db_expr_t *valuep;
{
db_expr_t lhs, rhs;
int t;
if (!db_mult_expr(&lhs))
return (FALSE);
t = db_read_token();
while (t == tPLUS || t == tMINUS) {
if (!db_mult_expr(&rhs)) {
db_error("Syntax error\n");
/*NOTREACHED*/
}
if (t == tPLUS)
lhs += rhs;
else
lhs -= rhs;
t = db_read_token();
}
db_unread_token(t);
*valuep = lhs;
return (TRUE);
}
boolean_t
db_shift_expr(valuep)
db_expr_t *valuep;
{
db_expr_t lhs, rhs;
int t;
if (!db_add_expr(&lhs))
return (FALSE);
t = db_read_token();
while (t == tSHIFT_L || t == tSHIFT_R) {
if (!db_add_expr(&rhs)) {
db_error("Syntax error\n");
/*NOTREACHED*/
}
if (rhs < 0) {
db_error("Negative shift amount\n");
/*NOTREACHED*/
}
if (t == tSHIFT_L)
lhs <<= rhs;
else {
/* Shift right is unsigned */
lhs = (unsigned) lhs >> rhs;
}
t = db_read_token();
}
db_unread_token(t);
*valuep = lhs;
return (TRUE);
}
int
db_expression(valuep)
db_expr_t *valuep;
{
return (db_shift_expr(valuep));
}
+268
View File
@@ -0,0 +1,268 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_input.c,v $
* Revision 1.1 1992/03/25 21:45:10 pace
* Initial revision
*
* Revision 2.4 91/02/14 14:41:53 mrt
* Add input line editing.
* [90/11/11 dbg]
*
* Revision 2.3 91/02/05 17:06:32 mrt
* Changed to new Mach copyright
* [91/01/31 16:18:13 mrt]
*
* Revision 2.2 90/08/27 21:51:03 dbg
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#include "param.h"
#include "proc.h"
#include <ddb/db_output.h>
/*
* Character input and editing.
*/
/*
* We don't track output position while editing input,
* since input always ends with a new-line. We just
* reset the line position at the end.
*/
char * db_lbuf_start; /* start of input line buffer */
char * db_lbuf_end; /* end of input line buffer */
char * db_lc; /* current character */
char * db_le; /* one past last character */
#define CTRL(c) ((c) & 0x1f)
#define isspace(c) ((c) == ' ' || (c) == '\t')
#define BLANK ' '
#define BACKUP '\b'
void
db_putstring(s, count)
char *s;
int count;
{
while (--count >= 0)
cnputc(*s++);
}
void
db_putnchars(c, count)
int c;
int count;
{
while (--count >= 0)
cnputc(c);
}
/*
* Delete N characters, forward or backward
*/
#define DEL_FWD 0
#define DEL_BWD 1
void
db_delete(n, bwd)
int n;
int bwd;
{
register char *p;
if (bwd) {
db_lc -= n;
db_putnchars(BACKUP, n);
}
for (p = db_lc; p < db_le-n; p++) {
*p = *(p+n);
cnputc(*p);
}
db_putnchars(BLANK, n);
db_putnchars(BACKUP, db_le - db_lc);
db_le -= n;
}
/* returns TRUE at end-of-line */
int
db_inputchar(c)
int c;
{
switch (c) {
case CTRL('b'):
/* back up one character */
if (db_lc > db_lbuf_start) {
cnputc(BACKUP);
db_lc--;
}
break;
case CTRL('f'):
/* forward one character */
if (db_lc < db_le) {
cnputc(*db_lc);
db_lc++;
}
break;
case CTRL('a'):
/* beginning of line */
while (db_lc > db_lbuf_start) {
cnputc(BACKUP);
db_lc--;
}
break;
case CTRL('e'):
/* end of line */
while (db_lc < db_le) {
cnputc(*db_lc);
db_lc++;
}
break;
case CTRL('h'):
case 0177:
/* erase previous character */
if (db_lc > db_lbuf_start)
db_delete(1, DEL_BWD);
break;
case CTRL('d'):
/* erase next character */
if (db_lc < db_le)
db_delete(1, DEL_FWD);
break;
case CTRL('k'):
/* delete to end of line */
if (db_lc < db_le)
db_delete(db_le - db_lc, DEL_FWD);
break;
case CTRL('t'):
/* twiddle last 2 characters */
if (db_lc >= db_lbuf_start + 2) {
c = db_lc[-2];
db_lc[-2] = db_lc[-1];
db_lc[-1] = c;
cnputc(BACKUP);
cnputc(BACKUP);
cnputc(db_lc[-2]);
cnputc(db_lc[-1]);
}
break;
case CTRL('r'):
db_putstring("^R\n", 3);
if (db_le > db_lbuf_start) {
db_putstring(db_lbuf_start, db_le - db_lbuf_start);
db_putnchars(BACKUP, db_le - db_lc);
}
break;
case '\n':
case '\r':
*db_le++ = c;
return (1);
default:
if (db_le == db_lbuf_end) {
cnputc('\007');
}
else if (c >= ' ' && c <= '~') {
register char *p;
for (p = db_le; p > db_lc; p--)
*p = *(p-1);
*db_lc++ = c;
db_le++;
cnputc(c);
db_putstring(db_lc, db_le - db_lc);
db_putnchars(BACKUP, db_le - db_lc);
}
break;
}
return (0);
}
int
db_readline(lstart, lsize)
char * lstart;
int lsize;
{
db_force_whitespace(); /* synch output position */
db_lbuf_start = lstart;
db_lbuf_end = lstart + lsize;
db_lc = lstart;
db_le = lstart;
while (!db_inputchar(cngetc()))
continue;
db_putchar('\n'); /* synch output position */
*db_le = 0;
return (db_le - db_lbuf_start);
}
void
db_check_interrupt()
{
register int c;
c = cnmaygetc();
switch (c) {
case -1: /* no character */
return;
case CTRL('c'):
db_error((char *)0);
/*NOTREACHED*/
case CTRL('s'):
do {
c = cnmaygetc();
if (c == CTRL('c'))
db_error((char *)0);
} while (c != CTRL('q'));
break;
default:
/* drop on floor */
break;
}
}
cnmaygetc ()
{
return (-1);
}
/* called from kdb_trap in db_interface.c */
cnpollc (flag)
{
}
+295
View File
@@ -0,0 +1,295 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_lex.c,v $
* Revision 1.1 1992/03/25 21:45:13 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:06:36 mrt
* Changed to new Mach copyright
* [91/01/31 16:18:20 mrt]
*
* Revision 2.2 90/08/27 21:51:10 dbg
* Add 'dotdot' token.
* [90/08/22 dbg]
*
* Allow backslash to quote any character into an identifier.
* Allow colon in identifier for symbol table qualification.
* [90/08/16 dbg]
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Lexical analyzer.
*/
#include <ddb/db_lex.h>
char db_line[120];
char * db_lp, *db_endlp;
int
db_read_line()
{
int i;
i = db_readline(db_line, sizeof(db_line));
if (i == 0)
return (0); /* EOI */
db_lp = db_line;
db_endlp = db_lp + i;
return (i);
}
void
db_flush_line()
{
db_lp = db_line;
db_endlp = db_line;
}
int db_look_char = 0;
int
db_read_char()
{
int c;
if (db_look_char != 0) {
c = db_look_char;
db_look_char = 0;
}
else if (db_lp >= db_endlp)
c = -1;
else
c = *db_lp++;
return (c);
}
void
db_unread_char(c)
{
db_look_char = c;
}
int db_look_token = 0;
void
db_unread_token(t)
int t;
{
db_look_token = t;
}
int
db_read_token()
{
int t;
if (db_look_token) {
t = db_look_token;
db_look_token = 0;
}
else
t = db_lex();
return (t);
}
int db_tok_number;
char db_tok_string[TOK_STRING_SIZE];
int db_radix = 16;
void
db_flush_lex()
{
db_flush_line();
db_look_char = 0;
db_look_token = 0;
}
int
db_lex()
{
int c;
c = db_read_char();
while (c <= ' ' || c > '~') {
if (c == '\n' || c == -1)
return (tEOL);
c = db_read_char();
}
if (c >= '0' && c <= '9') {
/* number */
int r, digit;
if (c > '0')
r = db_radix;
else {
c = db_read_char();
if (c == 'O' || c == 'o')
r = 8;
else if (c == 'T' || c == 't')
r = 10;
else if (c == 'X' || c == 'x')
r = 16;
else {
r = db_radix;
db_unread_char(c);
}
c = db_read_char();
}
db_tok_number = 0;
for (;;) {
if (c >= '0' && c <= ((r == 8) ? '7' : '9'))
digit = c - '0';
else if (r == 16 && ((c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f'))) {
if (c >= 'a')
digit = c - 'a' + 10;
else if (c >= 'A')
digit = c - 'A' + 10;
}
else
break;
db_tok_number = db_tok_number * r + digit;
c = db_read_char();
}
if ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c == '_'))
{
db_error("Bad character in number\n");
db_flush_lex();
return (tEOF);
}
db_unread_char(c);
return (tNUMBER);
}
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
c == '_' || c == '\\')
{
/* string */
char *cp;
cp = db_tok_string;
if (c == '\\') {
c = db_read_char();
if (c == '\n' || c == -1)
db_error("Bad escape\n");
}
*cp++ = c;
while (1) {
c = db_read_char();
if ((c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
c == '_' || c == '\\' || c == ':')
{
if (c == '\\') {
c = db_read_char();
if (c == '\n' || c == -1)
db_error("Bad escape\n");
}
*cp++ = c;
if (cp == db_tok_string+sizeof(db_tok_string)) {
db_error("String too long\n");
db_flush_lex();
return (tEOF);
}
continue;
}
else {
*cp = '\0';
break;
}
}
db_unread_char(c);
return (tIDENT);
}
switch (c) {
case '+':
return (tPLUS);
case '-':
return (tMINUS);
case '.':
c = db_read_char();
if (c == '.')
return (tDOTDOT);
db_unread_char(c);
return (tDOT);
case '*':
return (tSTAR);
case '/':
return (tSLASH);
case '=':
return (tEQ);
case '%':
return (tPCT);
case '#':
return (tHASH);
case '(':
return (tLPAREN);
case ')':
return (tRPAREN);
case ',':
return (tCOMMA);
case '"':
return (tDITTO);
case '$':
return (tDOLLAR);
case '!':
return (tEXCL);
case '<':
c = db_read_char();
if (c == '<')
return (tSHIFT_L);
db_unread_char(c);
break;
case '>':
c = db_read_char();
if (c == '>')
return (tSHIFT_R);
db_unread_char(c);
break;
case -1:
return (tEOF);
}
db_printf("Bad character\n");
db_flush_lex();
return (tEOF);
}
+89
View File
@@ -0,0 +1,89 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_lex.h,v $
* Revision 1.1 1992/03/25 21:45:15 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:06:41 mrt
* Changed to new Mach copyright
* [91/01/31 16:18:28 mrt]
*
* Revision 2.2 90/08/27 21:51:16 dbg
* Add 'dotdot' token.
* [90/08/22 dbg]
* Export db_flush_lex.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Lexical analyzer.
*/
extern int db_read_line();
extern void db_flush_line();
extern int db_read_char();
extern void db_unread_char(/* char c */);
extern int db_read_token();
extern void db_unread_token(/* int t */);
extern void db_flush_lex();
extern int db_tok_number;
#define TOK_STRING_SIZE 120
extern char db_tok_string[TOK_STRING_SIZE];
extern int db_radix;
#define tEOF (-1)
#define tEOL 1
#define tNUMBER 2
#define tIDENT 3
#define tPLUS 4
#define tMINUS 5
#define tDOT 6
#define tSTAR 7
#define tSLASH 8
#define tEQ 9
#define tLPAREN 10
#define tRPAREN 11
#define tPCT 12
#define tHASH 13
#define tCOMMA 14
#define tDITTO 15
#define tDOLLAR 16
#define tEXCL 17
#define tSHIFT_L 18
#define tSHIFT_R 19
#define tDOTDOT 20
+389
View File
@@ -0,0 +1,389 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 4 00083
* -------------------- ----- ----------------------
*
* 14 Mar 93 Chris G. Demetriou Fixed so that tab is not output,
* use spaces instead.
*/
/*
* HISTORY
* $Log: db_output.c,v $
* Revision 1.1 1992/03/25 21:45:18 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:06:45 mrt
* Changed to new Mach copyright
* [91/01/31 16:18:41 mrt]
*
* Revision 2.2 90/08/27 21:51:25 dbg
* Put extra features of db_doprnt in _doprnt.
* [90/08/20 dbg]
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Printf and character output for debugger.
*/
#include "param.h"
#include <machine/stdarg.h>
/*
* Character output - tracks position in line.
* To do this correctly, we should know how wide
* the output device is - then we could zero
* the line position when the output device wraps
* around to the start of the next line.
*
* Instead, we count the number of spaces printed
* since the last printing character so that we
* don't print trailing spaces. This avoids most
* of the wraparounds.
*/
int db_output_position = 0; /* output column */
int db_last_non_space = 0; /* last non-space character */
int db_tab_stop_width = 8; /* how wide are tab stops? */
#define NEXT_TAB(i) \
((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width)
int db_max_width = 80; /* output line width */
extern void db_check_interrupt();
/*
* Force pending whitespace.
*/
void
db_force_whitespace()
{
register int last_print, next_tab;
last_print = db_last_non_space;
while (last_print < db_output_position) {
next_tab = NEXT_TAB(last_print);
if (next_tab <= db_output_position) {
while (last_print < next_tab) { /* DON'T send a tab!!! */
cnputc(' ');
last_print++;
}
}
else {
cnputc(' ');
last_print++;
}
}
db_last_non_space = db_output_position;
}
/*
* Output character. Buffer whitespace.
*/
db_putchar(c)
int c; /* character to output */
{
if (c > ' ' && c <= '~') {
/*
* Printing character.
* If we have spaces to print, print them first.
* Use tabs if possible.
*/
db_force_whitespace();
cnputc(c);
db_output_position++;
db_last_non_space = db_output_position;
}
else if (c == '\n') {
/* Return */
cnputc(c);
db_output_position = 0;
db_last_non_space = 0;
db_check_interrupt();
}
else if (c == '\t') {
/* assume tabs every 8 positions */
db_output_position = NEXT_TAB(db_output_position);
}
else if (c == ' ') {
/* space */
db_output_position++;
}
else if (c == '\007') {
/* bell */
cnputc(c);
}
/* other characters are assumed non-printing */
}
/*
* Return output position
*/
int
db_print_position()
{
return (db_output_position);
}
/*
* End line if too long.
*/
void
db_end_line()
{
if (db_output_position >= db_max_width)
db_printf("\n");
}
/*
* Printing
*/
extern int db_radix;
/*VARARGS1*/
db_printf(char *fmt, ...)
{
va_list listp;
va_start(listp, fmt);
db_printf_guts (fmt, listp);
va_end(listp);
}
/* alternate name */
/*VARARGS1*/
kdbprintf(char *fmt, ...)
{
va_list listp;
va_start(listp, fmt);
db_printf_guts (fmt, listp);
va_end(listp);
}
/*
* Put a number (base <= 16) in a buffer in reverse order; return an
* optional length and a pointer to the NULL terminated (preceded?)
* buffer.
*/
static char *
db_ksprintn(ul, base, lenp)
register u_long ul;
register int base, *lenp;
{ /* A long in base 8, plus NULL. */
static char buf[sizeof(long) * NBBY / 3 + 2];
register char *p;
p = buf;
do {
*++p = "0123456789abcdef"[ul % base];
} while (ul /= base);
if (lenp)
*lenp = p - buf;
return (p);
}
db_printf_guts(fmt, ap)
register const char *fmt;
va_list ap;
{
register char *p;
register int ch, n;
u_long ul;
int base, lflag, tmp, width;
char padc;
int ladjust;
int sharpflag;
int neg;
for (;;) {
padc = ' ';
width = 0;
while ((ch = *(u_char *)fmt++) != '%') {
if (ch == '\0')
return;
db_putchar(ch);
}
lflag = 0;
ladjust = 0;
sharpflag = 0;
neg = 0;
reswitch: switch (ch = *(u_char *)fmt++) {
case '0':
padc = '0';
goto reswitch;
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
for (width = 0;; ++fmt) {
width = width * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
goto reswitch;
case 'l':
lflag = 1;
goto reswitch;
case '-':
ladjust = 1;
goto reswitch;
case '#':
sharpflag = 1;
goto reswitch;
case 'b':
ul = va_arg(ap, int);
p = va_arg(ap, char *);
for (p = db_ksprintn(ul, *p++, NULL); ch = *p--;)
db_putchar(ch);
if (!ul)
break;
for (tmp = 0; n = *p++;) {
if (ul & (1 << (n - 1))) {
db_putchar(tmp ? ',' : '<');
for (; (n = *p) > ' '; ++p)
db_putchar(n);
tmp = 1;
} else
for (; *p > ' '; ++p);
}
if (tmp)
db_putchar('>');
break;
case '*':
width = va_arg (ap, int);
if (width < 0) {
ladjust = !ladjust;
width = -width;
}
goto reswitch;
case 'c':
db_putchar(va_arg(ap, int));
break;
case 's':
p = va_arg(ap, char *);
width -= strlen (p);
if (!ladjust && width > 0)
while (width--)
db_putchar (padc);
while (ch = *p++)
db_putchar(ch);
if (ladjust && width > 0)
while (width--)
db_putchar (padc);
break;
case 'r':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
if ((long)ul < 0) {
neg = 1;
ul = -(long)ul;
}
base = db_radix;
if (base < 8 || base > 16)
base = 10;
goto number;
case 'n':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = db_radix;
if (base < 8 || base > 16)
base = 10;
goto number;
case 'd':
ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
if ((long)ul < 0) {
neg = 1;
ul = -(long)ul;
}
base = 10;
goto number;
case 'o':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 8;
goto number;
case 'u':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 10;
goto number;
case 'z':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
if ((long)ul < 0) {
neg = 1;
ul = -(long)ul;
}
base = 16;
goto number;
case 'x':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 16;
number: p = (char *)db_ksprintn(ul, base, &tmp);
if (sharpflag && ul != 0) {
if (base == 8)
tmp++;
else if (base == 16)
tmp += 2;
}
if (neg)
tmp++;
if (!ladjust && width && (width -= tmp) > 0)
while (width--)
db_putchar(padc);
if (neg)
db_putchar ('-');
if (sharpflag && ul != 0) {
if (base == 8) {
db_putchar ('0');
} else if (base == 16) {
db_putchar ('0');
db_putchar ('x');
}
}
if (ladjust && width && (width -= tmp) > 0)
while (width--)
db_putchar(padc);
while (ch = *p--)
db_putchar(ch);
break;
default:
db_putchar('%');
if (lflag)
db_putchar('l');
/* FALLTHROUGH */
case '%':
db_putchar(ch);
}
}
}
+53
View File
@@ -0,0 +1,53 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_output.h,v $
* Revision 1.1 1992/03/25 21:45:20 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:06:49 mrt
* Changed to new Mach copyright
* [91/01/31 16:18:48 mrt]
*
* Revision 2.2 90/08/27 21:51:32 dbg
* Created.
* [90/08/07 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 8/90
*/
/*
* Printing routines for kernel debugger.
*/
extern void db_force_whitespace();
extern int db_print_position();
extern void db_end_line();
extern int db_printf();
+104
View File
@@ -0,0 +1,104 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_print.c,v $
* Revision 1.1 1992/03/25 21:45:22 pace
* Initial revision
*
* Revision 2.5 91/02/05 17:06:53 mrt
* Changed to new Mach copyright
* [91/01/31 16:18:56 mrt]
*
* Revision 2.4 90/10/25 14:43:54 rwd
* Changed db_show_regs to print unsigned.
* [90/10/19 rpd]
* Generalized the watchpoint support.
* [90/10/16 rwd]
*
* Revision 2.3 90/09/09 23:19:52 rpd
* Avoid totally incorrect guesses of symbol names for small values.
* [90/08/30 17:39:08 af]
*
* Revision 2.2 90/08/27 21:51:49 dbg
* Insist that 'show thread' be called with an explicit address.
* [90/08/22 dbg]
*
* Fix type for db_maxoff.
* [90/08/20 dbg]
*
* Do not dereference the "valuep" field of a variable directly,
* call the new db_read/write_variable functions instead.
* Reflected changes in symbol lookup functions.
* [90/08/20 af]
* Reduce lint.
* [90/08/10 14:33:44 dbg]
*
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Miscellaneous printing.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_lex.h>
#include <ddb/db_variables.h>
#include <ddb/db_sym.h>
extern unsigned int db_maxoff;
void
db_show_regs()
{
int (*func)();
register struct db_variable *regp;
db_expr_t value, offset;
char * name;
for (regp = db_regs; regp < db_eregs; regp++) {
db_read_variable(regp, &value);
db_printf("%-12s%#10n", regp->name, value);
db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset);
if (name != 0 && offset <= db_maxoff && offset != value) {
db_printf("\t%s", name);
if (offset != 0)
db_printf("+%#r", offset);
}
db_printf("\n");
}
db_print_loc_and_inst(PC_REGS(DDB_REGS));
}
+426
View File
@@ -0,0 +1,426 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_run.c,v $
* Revision 1.1 1992/03/25 21:45:24 pace
* Initial revision
*
* Revision 2.5 91/02/05 17:06:58 mrt
* Changed to new Mach copyright
* [91/01/31 16:19:05 mrt]
*
* Revision 2.4 91/01/08 15:09:10 rpd
* Fixed bug in db_restart_at_pc.
* [90/12/07 rpd]
* Added STEP_COUNT and count option to db_continue_cmd.
* Changed db_stop_at_pc to return (modified) is_breakpoint.
* Fixed db_stop_at_pc to print newlines in the right places.
* [90/11/27 rpd]
*
* Revision 2.3 90/10/25 14:43:59 rwd
* Changed db_find_breakpoint to db_find_breakpoint_here.
* [90/10/18 rpd]
*
* Fixed db_set_single_step to pass regs to branch_taken.
* Added watchpoint argument to db_restart_at_pc.
* [90/10/17 rpd]
* Generalized the watchpoint support.
* [90/10/16 rwd]
* Added watchpoint support.
* [90/10/16 rpd]
*
* Revision 2.2 90/08/27 21:51:59 dbg
* Fixed names for single-step functions.
* [90/08/20 af]
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Commands to run process.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_lex.h>
#include <ddb/db_break.h>
#include <ddb/db_access.h>
int db_run_mode;
#define STEP_NONE 0
#define STEP_ONCE 1
#define STEP_RETURN 2
#define STEP_CALLT 3
#define STEP_CONTINUE 4
#define STEP_INVISIBLE 5
#define STEP_COUNT 6
boolean_t db_sstep_print;
int db_loop_count;
int db_call_depth;
int db_inst_count;
int db_load_count;
int db_store_count;
#ifndef db_set_single_step
void db_set_single_step(/* db_regs_t *regs */); /* forward */
#endif
#ifndef db_clear_single_step
void db_clear_single_step(/* db_regs_t *regs */);
#endif
boolean_t
db_stop_at_pc(is_breakpoint)
boolean_t *is_breakpoint;
{
register db_addr_t pc;
register db_breakpoint_t bkpt;
db_clear_single_step(DDB_REGS);
db_clear_breakpoints();
db_clear_watchpoints();
pc = PC_REGS(DDB_REGS);
#ifdef FIXUP_PC_AFTER_BREAK
if (*is_breakpoint) {
/*
* Breakpoint trap. Fix up the PC if the
* machine requires it.
*/
FIXUP_PC_AFTER_BREAK
pc = PC_REGS(DDB_REGS);
}
#endif
/*
* Now check for a breakpoint at this address.
*/
bkpt = db_find_breakpoint_here(pc);
if (bkpt) {
if (--bkpt->count == 0) {
bkpt->count = bkpt->init_count;
*is_breakpoint = TRUE;
return (TRUE); /* stop here */
}
} else if (*is_breakpoint) {
ddb_regs.tf_eip += 1;
}
*is_breakpoint = FALSE;
if (db_run_mode == STEP_INVISIBLE) {
db_run_mode = STEP_CONTINUE;
return (FALSE); /* continue */
}
if (db_run_mode == STEP_COUNT) {
return (FALSE); /* continue */
}
if (db_run_mode == STEP_ONCE) {
if (--db_loop_count > 0) {
if (db_sstep_print) {
db_printf("\t\t");
db_print_loc_and_inst(pc);
db_printf("\n");
}
return (FALSE); /* continue */
}
}
if (db_run_mode == STEP_RETURN) {
db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);
/* continue until matching return */
if (!inst_trap_return(ins) &&
(!inst_return(ins) || --db_call_depth != 0)) {
if (db_sstep_print) {
if (inst_call(ins) || inst_return(ins)) {
register int i;
db_printf("[after %6d] ", db_inst_count);
for (i = db_call_depth; --i > 0; )
db_printf(" ");
db_print_loc_and_inst(pc);
db_printf("\n");
}
}
if (inst_call(ins))
db_call_depth++;
return (FALSE); /* continue */
}
}
if (db_run_mode == STEP_CALLT) {
db_expr_t ins = db_get_value(pc, sizeof(int), FALSE);
/* continue until call or return */
if (!inst_call(ins) &&
!inst_return(ins) &&
!inst_trap_return(ins)) {
return (FALSE); /* continue */
}
}
db_run_mode = STEP_NONE;
return (TRUE);
}
void
db_restart_at_pc(watchpt)
boolean_t watchpt;
{
register db_addr_t pc = PC_REGS(DDB_REGS);
if ((db_run_mode == STEP_COUNT) ||
(db_run_mode == STEP_RETURN) ||
(db_run_mode == STEP_CALLT)) {
db_expr_t ins;
/*
* We are about to execute this instruction,
* so count it now.
*/
ins = db_get_value(pc, sizeof(int), FALSE);
db_inst_count++;
db_load_count += inst_load(ins);
db_store_count += inst_store(ins);
#ifdef SOFTWARE_SSTEP
/* XXX works on mips, but... */
if (inst_branch(ins) || inst_call(ins)) {
ins = db_get_value(next_instr_address(pc,1),
sizeof(int), FALSE);
db_inst_count++;
db_load_count += inst_load(ins);
db_store_count += inst_store(ins);
}
#endif SOFTWARE_SSTEP
}
if (db_run_mode == STEP_CONTINUE) {
if (watchpt || db_find_breakpoint_here(pc)) {
/*
* Step over breakpoint/watchpoint.
*/
db_run_mode = STEP_INVISIBLE;
db_set_single_step(DDB_REGS);
} else {
db_set_breakpoints();
db_set_watchpoints();
}
} else {
db_set_single_step(DDB_REGS);
}
}
void
db_single_step(regs)
db_regs_t *regs;
{
if (db_run_mode == STEP_CONTINUE) {
db_run_mode = STEP_INVISIBLE;
db_set_single_step(regs);
}
}
#ifdef SOFTWARE_SSTEP
/*
* Software implementation of single-stepping.
* If your machine does not have a trace mode
* similar to the vax or sun ones you can use
* this implementation, done for the mips.
* Just define the above conditional and provide
* the functions/macros defined below.
*
* extern boolean_t
* inst_branch(), returns true if the instruction might branch
* extern unsigned
* branch_taken(), return the address the instruction might
* branch to
* db_getreg_val(); return the value of a user register,
* as indicated in the hardware instruction
* encoding, e.g. 8 for r8
*
* next_instr_address(pc,bd) returns the address of the first
* instruction following the one at "pc",
* which is either in the taken path of
* the branch (bd==1) or not. This is
* for machines (mips) with branch delays.
*
* A single-step may involve at most 2 breakpoints -
* one for branch-not-taken and one for branch taken.
* If one of these addresses does not already have a breakpoint,
* we allocate a breakpoint and save it here.
* These breakpoints are deleted on return.
*/
db_breakpoint_t db_not_taken_bkpt = 0;
db_breakpoint_t db_taken_bkpt = 0;
void
db_set_single_step(regs)
register db_regs_t *regs;
{
db_addr_t pc = PC_REGS(regs);
register unsigned inst, brpc;
/*
* User was stopped at pc, e.g. the instruction
* at pc was not executed.
*/
inst = db_get_value(pc, sizeof(int), FALSE);
if (inst_branch(inst) || inst_call(inst)) {
extern unsigned getreg_val();
brpc = branch_taken(inst, pc, getreg_val, regs);
if (brpc != pc) { /* self-branches are hopeless */
db_taken_bkpt = db_set_temp_breakpoint(brpc);
}
pc = next_instr_address(pc,1);
}
pc = next_instr_address(pc,0);
db_not_taken_bkpt = db_set_temp_breakpoint(pc);
}
void
db_clear_single_step(regs)
db_regs_t *regs;
{
register db_breakpoint_t bkpt;
if (db_taken_bkpt != 0) {
db_delete_temp_breakpoint(db_taken_bkpt);
db_taken_bkpt = 0;
}
if (db_not_taken_bkpt != 0) {
db_delete_temp_breakpoint(db_not_taken_bkpt);
db_not_taken_bkpt = 0;
}
}
#endif SOFTWARE_SSTEP
extern int db_cmd_loop_done;
/* single-step */
/*ARGSUSED*/
void
db_single_step_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
boolean_t print = FALSE;
if (count == -1)
count = 1;
if (modif[0] == 'p')
print = TRUE;
db_run_mode = STEP_ONCE;
db_loop_count = count;
db_sstep_print = print;
db_inst_count = 0;
db_load_count = 0;
db_store_count = 0;
db_cmd_loop_done = 1;
}
/* trace and print until call/return */
/*ARGSUSED*/
void
db_trace_until_call_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
boolean_t print = FALSE;
if (modif[0] == 'p')
print = TRUE;
db_run_mode = STEP_CALLT;
db_sstep_print = print;
db_inst_count = 0;
db_load_count = 0;
db_store_count = 0;
db_cmd_loop_done = 1;
}
/*ARGSUSED*/
void
db_trace_until_matching_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
boolean_t print = FALSE;
if (modif[0] == 'p')
print = TRUE;
db_run_mode = STEP_RETURN;
db_call_depth = 1;
db_sstep_print = print;
db_inst_count = 0;
db_load_count = 0;
db_store_count = 0;
db_cmd_loop_done = 1;
}
/* continue */
/*ARGSUSED*/
void
db_continue_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
if (modif[0] == 'c')
db_run_mode = STEP_COUNT;
else
db_run_mode = STEP_CONTINUE;
db_inst_count = 0;
db_load_count = 0;
db_store_count = 0;
db_cmd_loop_done = 1;
}
+360
View File
@@ -0,0 +1,360 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_sym.c,v $
* Revision 1.1 1992/03/25 21:45:27 pace
* Initial revision
*
* Revision 2.5 91/02/05 17:07:07 mrt
* Changed to new Mach copyright
* [91/01/31 16:19:17 mrt]
*
* Revision 2.4 90/10/25 14:44:05 rwd
* Changed db_printsym to print unsigned.
* [90/10/19 rpd]
*
* Revision 2.3 90/09/09 23:19:56 rpd
* Avoid totally incorrect guesses of symbol names for small values.
* [90/08/30 17:39:48 af]
*
* Revision 2.2 90/08/27 21:52:18 dbg
* Removed nlist.h. Fixed some type declarations.
* Qualifier character is ':'.
* [90/08/20 dbg]
* Modularized symtab info into a new db_symtab_t type.
* Modified db_add_symbol_table and others accordingly.
* Defined db_sym_t, a new (opaque) type used to represent
* symbols. This should support all sort of future symtable
* formats. Functions like db_qualify take a db_sym_t now.
* New db_symbol_values() function to explode the content
* of a db_sym_t.
* db_search_symbol() replaces db_find_sym_and_offset(), which is
* now a macro defined in our (new) header file. This new
* function accepts more restrictive searches, which are
* entirely delegated to the symtab-specific code.
* Accordingly, db_printsym() accepts a strategy parameter.
* New db_line_at_pc() function.
* Renamed misleading db_eqsym into db_eqname.
* [90/08/20 10:47:06 af]
*
* Created.
* [90/07/25 dbg]
*
* Revision 2.1 90/07/26 16:43:52 dbg
* Created.
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_sym.h>
/*
* We import from the symbol-table dependent routines:
*/
extern db_sym_t X_db_lookup();
extern db_sym_t X_db_search_symbol();
extern boolean_t X_db_line_at_pc();
extern void X_db_symbol_values();
/*
* Multiple symbol tables
*/
#define MAXNOSYMTABS 3 /* mach, ux, emulator */
db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
int db_nsymtab = 0;
db_symtab_t *db_last_symtab;
db_sym_t db_lookup(); /* forward */
/*
* Add symbol table, with given name, to list of symbol tables.
*/
void
db_add_symbol_table(start, end, name, ref)
char *start;
char *end;
char *name;
char *ref;
{
if (db_nsymtab >= MAXNOSYMTABS) {
printf ("No slots left for %s symbol table", name);
panic ("db_sym.c: db_add_symbol_table");
}
db_symtabs[db_nsymtab].start = start;
db_symtabs[db_nsymtab].end = end;
db_symtabs[db_nsymtab].name = name;
db_symtabs[db_nsymtab].private = ref;
db_nsymtab++;
}
/*
* db_qualify("vm_map", "ux") returns "unix:vm_map".
*
* Note: return value points to static data whose content is
* overwritten by each call... but in practice this seems okay.
*/
static char *
db_qualify(sym, symtabname)
db_sym_t sym;
register char *symtabname;
{
char *symname;
static char tmp[256];
register char *s;
db_symbol_values(sym, &symname, 0);
s = tmp;
while (*s++ = *symtabname++) {
}
s[-1] = ':';
while (*s++ = *symname++) {
}
return tmp;
}
boolean_t
db_eqname(src, dst, c)
char *src;
char *dst;
char c;
{
if (!strcmp(src, dst))
return (TRUE);
if (src[0] == c)
return (!strcmp(src+1,dst));
return (FALSE);
}
boolean_t
db_value_of_name(name, valuep)
char *name;
db_expr_t *valuep;
{
db_sym_t sym;
sym = db_lookup(name);
if (sym == DB_SYM_NULL)
return (FALSE);
db_symbol_values(sym, &name, valuep);
return (TRUE);
}
/*
* Lookup a symbol.
* If the symbol has a qualifier (e.g., ux:vm_map),
* then only the specified symbol table will be searched;
* otherwise, all symbol tables will be searched.
*/
db_sym_t
db_lookup(symstr)
char *symstr;
{
db_sym_t sp;
register int i;
int symtab_start = 0;
int symtab_end = db_nsymtab;
register char *cp;
/*
* Look for, remove, and remember any symbol table specifier.
*/
for (cp = symstr; *cp; cp++) {
if (*cp == ':') {
*cp = '\0';
for (i = 0; i < db_nsymtab; i++) {
if (! strcmp(symstr, db_symtabs[i].name)) {
symtab_start = i;
symtab_end = i + 1;
break;
}
}
*cp = ':';
if (i == db_nsymtab) {
db_error("invalid symbol table name");
}
symstr = cp+1;
}
}
/*
* Look in the specified set of symbol tables.
* Return on first match.
*/
for (i = symtab_start; i < symtab_end; i++) {
if (sp = X_db_lookup(&db_symtabs[i], symstr)) {
db_last_symtab = &db_symtabs[i];
return sp;
}
}
return 0;
}
/*
* Does this symbol name appear in more than one symbol table?
* Used by db_symbol_values to decide whether to qualify a symbol.
*/
boolean_t db_qualify_ambiguous_names = FALSE;
boolean_t
db_symbol_is_ambiguous(sym)
db_sym_t sym;
{
char *sym_name;
register int i;
register
boolean_t found_once = FALSE;
if (!db_qualify_ambiguous_names)
return FALSE;
db_symbol_values(sym, &sym_name, 0);
for (i = 0; i < db_nsymtab; i++) {
if (X_db_lookup(&db_symtabs[i], sym_name)) {
if (found_once)
return TRUE;
found_once = TRUE;
}
}
return FALSE;
}
/*
* Find the closest symbol to val, and return its name
* and the difference between val and the symbol found.
*/
db_sym_t
db_search_symbol( val, strategy, offp)
register db_addr_t val;
db_strategy_t strategy;
db_expr_t *offp;
{
register
unsigned int diff;
unsigned int newdiff;
register int i;
db_sym_t ret = DB_SYM_NULL, sym;
newdiff = diff = ~0;
db_last_symtab = 0;
for (i = 0; i < db_nsymtab; i++) {
sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
if (newdiff < diff) {
db_last_symtab = &db_symtabs[i];
diff = newdiff;
ret = sym;
}
}
*offp = diff;
return ret;
}
/*
* Return name and value of a symbol
*/
void
db_symbol_values(sym, namep, valuep)
db_sym_t sym;
char **namep;
db_expr_t *valuep;
{
db_expr_t value;
if (sym == DB_SYM_NULL) {
*namep = 0;
return;
}
X_db_symbol_values(sym, namep, &value);
if (db_symbol_is_ambiguous(sym))
*namep = db_qualify(sym, db_last_symtab->name);
if (valuep)
*valuep = value;
}
/*
* Print a the closest symbol to value
*
* After matching the symbol according to the given strategy
* we print it in the name+offset format, provided the symbol's
* value is close enough (eg smaller than db_maxoff).
* We also attempt to print [filename:linenum] when applicable
* (eg for procedure names).
*
* If we could not find a reasonable name+offset representation,
* then we just print the value in hex. Small values might get
* bogus symbol associations, e.g. 3 might get some absolute
* value like _INCLUDE_VERSION or something, therefore we do
* not accept symbols whose value is zero (and use plain hex).
*/
unsigned int db_maxoff = 0x10000000;
void
db_printsym(off, strategy)
db_expr_t off;
db_strategy_t strategy;
{
db_expr_t d;
char *filename;
char *name;
db_expr_t value;
int linenum;
db_sym_t cursym;
cursym = db_search_symbol(off, strategy, &d);
db_symbol_values(cursym, &name, &value);
if (name == 0 || d >= db_maxoff || value == 0) {
db_printf("%#n", off);
return;
}
db_printf("%s", name);
if (d)
db_printf("+%#r", d);
if (strategy == DB_STGY_PROC) {
if (db_line_at_pc(cursym, &filename, &linenum, off))
db_printf(" [%s:%d]", filename, linenum);
}
}
boolean_t
db_line_at_pc( sym, filename, linenum, pc)
{
return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc);
}
+114
View File
@@ -0,0 +1,114 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_sym.h,v $
* Revision 1.1 1992/03/25 21:45:29 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:07:12 mrt
* Changed to new Mach copyright
* [91/01/31 16:19:27 mrt]
*
* Revision 2.2 90/08/27 21:52:39 dbg
* Changed type of db_sym_t to char * - it's a better type for an
* opaque pointer.
* [90/08/22 dbg]
*
* Created.
* [90/08/19 af]
*
*/
/*
* Author: Alessandro Forin, Carnegie Mellon University
* Date: 8/90
*/
/*
* This module can handle multiple symbol tables
*/
typedef struct {
char *name; /* symtab name */
char *start; /* symtab location */
char *end;
char *private; /* optional machdep pointer */
} db_symtab_t;
extern db_symtab_t *db_last_symtab; /* where last symbol was found */
/*
* Symbol representation is specific to the symtab style:
* BSD compilers use dbx' nlist, other compilers might use
* a different one
*/
typedef char * db_sym_t; /* opaque handle on symbols */
#define DB_SYM_NULL ((db_sym_t)0)
/*
* Non-stripped symbol tables will have duplicates, for instance
* the same string could match a parameter name, a local var, a
* global var, etc.
* We are most concern with the following matches.
*/
typedef int db_strategy_t; /* search strategy */
#define DB_STGY_ANY 0 /* anything goes */
#define DB_STGY_XTRN 1 /* only external symbols */
#define DB_STGY_PROC 2 /* only procedures */
extern boolean_t db_qualify_ambiguous_names;
/* if TRUE, check across symbol tables
* for multiple occurrences of a name.
* Might slow down quite a bit */
/*
* Functions exported by the symtable module
*/
extern void db_add_symbol_table();
/* extend the list of symbol tables */
extern int db_value_of_name(/* char*, db_expr_t* */);
/* find symbol value given name */
extern db_sym_t db_search_symbol(/* db_expr_t, db_strategy_t, int* */);
/* find symbol given value */
extern void db_symbol_values(/* db_sym_t, char**, db_expr_t* */);
/* return name and value of symbol */
#define db_find_sym_and_offset(val,namep,offp) \
db_symbol_values(db_search_symbol(val,DB_STGY_ANY,offp),namep,0)
/* find name&value given approx val */
#define db_find_xtrn_sym_and_offset(val,namep,offp) \
db_symbol_values(db_search_symbol(val,DB_STGY_XTRN,offp),namep,0)
/* ditto, but no locals */
extern int db_eqname(/* char*, char*, char */);
/* strcmp, modulo leading char */
extern void db_printsym(/* db_expr_t, db_strategy_t */);
/* print closest symbol to a value */
+106
View File
@@ -0,0 +1,106 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_trap.c,v $
* Revision 1.1 1992/03/25 21:45:31 pace
* Initial revision
*
* Revision 2.5 91/02/05 17:07:16 mrt
* Changed to new Mach copyright
* [91/01/31 16:19:35 mrt]
*
* Revision 2.4 91/01/08 15:09:17 rpd
* Changed db_stop_at_pc's arguments.
* Print db_inst_count, db_load_count, db_store_count.
* [90/11/27 rpd]
*
* Revision 2.3 90/10/25 14:44:11 rwd
* From rpd.
* [90/10/19 17:03:17 rwd]
*
* Generalized the watchpoint support.
* [90/10/16 rwd]
* Added watchpoint support.
* [90/10/16 rpd]
*
* Revision 2.2 90/08/27 21:52:52 dbg
* Assign to db_dot before calling the print function.
* [90/08/20 af]
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Trap entry point to kernel debugger.
*/
#include "param.h"
#include "proc.h"
#include <ddb/db_command.h>
#include <ddb/db_break.h>
extern void db_restart_at_pc();
extern boolean_t db_stop_at_pc();
extern int db_inst_count;
extern int db_load_count;
extern int db_store_count;
db_trap(type, code)
int type, code;
{
boolean_t bkpt;
boolean_t watchpt;
bkpt = IS_BREAKPOINT_TRAP(type, code);
watchpt = IS_WATCHPOINT_TRAP(type, code);
if (db_stop_at_pc(&bkpt)) {
if (db_inst_count) {
db_printf("After %d instructions (%d loads, %d stores),\n",
db_inst_count, db_load_count, db_store_count);
}
if (bkpt)
db_printf("Breakpoint at\t");
else if (watchpt)
db_printf("Watchpoint at\t");
else
db_printf("Stopped at\t");
db_dot = PC_REGS(DDB_REGS);
db_print_loc_and_inst(db_dot);
db_command_loop();
}
db_restart_at_pc(watchpt);
}
+186
View File
@@ -0,0 +1,186 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_variables.c,v $
* Revision 1.1 1992/03/25 21:45:33 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:07:19 mrt
* Changed to new Mach copyright
* [91/01/31 16:19:46 mrt]
*
* Revision 2.2 90/08/27 21:53:24 dbg
* New db_read/write_variable functions. Should be used instead
* of dereferencing valuep directly, which might not be a true
* pointer if there is an fcn() access function.
* [90/08/20 af]
*
* Fix declarations.
* Check for trailing garbage after last expression on command line.
* [90/08/10 14:34:54 dbg]
*
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_lex.h>
#include <ddb/db_variables.h>
extern unsigned int db_maxoff;
extern int db_radix;
extern int db_max_width;
extern int db_tab_stop_width;
struct db_variable db_vars[] = {
{ "radix", &db_radix, FCN_NULL },
{ "maxoff", (int *)&db_maxoff, FCN_NULL },
{ "maxwidth", &db_max_width, FCN_NULL },
{ "tabstops", &db_tab_stop_width, FCN_NULL },
};
struct db_variable *db_evars = db_vars + sizeof(db_vars)/sizeof(db_vars[0]);
int
db_find_variable(varp)
struct db_variable **varp;
{
int t;
struct db_variable *vp;
t = db_read_token();
if (t == tIDENT) {
for (vp = db_vars; vp < db_evars; vp++) {
if (!strcmp(db_tok_string, vp->name)) {
*varp = vp;
return (1);
}
}
for (vp = db_regs; vp < db_eregs; vp++) {
if (!strcmp(db_tok_string, vp->name)) {
*varp = vp;
return (1);
}
}
}
db_error("Unknown variable\n");
return (0);
}
int
db_get_variable(valuep)
db_expr_t *valuep;
{
struct db_variable *vp;
if (!db_find_variable(&vp))
return (0);
db_read_variable(vp, valuep);
return (1);
}
int
db_set_variable(value)
db_expr_t value;
{
struct db_variable *vp;
if (!db_find_variable(&vp))
return (0);
db_write_variable(vp, &value);
return (1);
}
db_read_variable(vp, valuep)
struct db_variable *vp;
db_expr_t *valuep;
{
int (*func)() = vp->fcn;
if (func == FCN_NULL)
*valuep = *(vp->valuep);
else
(*func)(vp, valuep, DB_VAR_GET);
}
db_write_variable(vp, valuep)
struct db_variable *vp;
db_expr_t *valuep;
{
int (*func)() = vp->fcn;
if (func == FCN_NULL)
*(vp->valuep) = *valuep;
else
(*func)(vp, valuep, DB_VAR_SET);
}
void
db_set_cmd()
{
db_expr_t value;
int (*func)();
struct db_variable *vp;
int t;
t = db_read_token();
if (t != tDOLLAR) {
db_error("Unknown variable\n");
return;
}
if (!db_find_variable(&vp)) {
db_error("Unknown variable\n");
return;
}
t = db_read_token();
if (t != tEQ)
db_unread_token(t);
if (!db_expression(&value)) {
db_error("No value\n");
return;
}
if (db_read_token() != tEOL) {
db_error("?\n");
}
db_write_variable(vp, &value);
}
+72
View File
@@ -0,0 +1,72 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_variables.h,v $
* Revision 1.1 1992/03/25 21:45:35 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:07:23 mrt
* Changed to new Mach copyright
* [91/01/31 16:19:54 mrt]
*
* Revision 2.2 90/08/27 21:53:40 dbg
* Modularized typedef name. Documented the calling sequence of
* the (optional) access function of a variable. Now the valuep
* field can be made opaque, eg be an offset that fcn() resolves.
* [90/08/20 af]
*
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#ifndef _DB_VARIABLES_H_
#define _DB_VARIABLES_H_
/*
* Debugger variables.
*/
struct db_variable {
char *name; /* Name of variable */
int *valuep; /* value of variable */
/* function to call when reading/writing */
int (*fcn)(/* db_variable *vp, db_expr_t *valuep, int op */);
#define DB_VAR_GET 0
#define DB_VAR_SET 1
};
#define FCN_NULL ((int (*)())0)
extern struct db_variable db_vars[]; /* debugger variables */
extern struct db_variable *db_evars;
extern struct db_variable db_regs[]; /* machine registers */
extern struct db_variable *db_eregs;
#endif /* _DB_VARIABLES_H_ */
+294
View File
@@ -0,0 +1,294 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_watch.c,v $
* Revision 1.1 1992/03/25 21:45:37 pace
* Initial revision
*
* Revision 2.5 91/02/05 17:07:27 mrt
* Changed to new Mach copyright
* [91/01/31 16:20:02 mrt]
*
* Revision 2.4 91/01/08 15:09:24 rpd
* Use db_map_equal, db_map_current, db_map_addr.
* [90/11/10 rpd]
*
* Revision 2.3 90/11/05 14:26:39 rpd
* Initialize db_watchpoints_inserted to TRUE.
* [90/11/04 rpd]
*
* Revision 2.2 90/10/25 14:44:16 rwd
* Made db_watchpoint_cmd parse a size argument.
* [90/10/17 rpd]
* Generalized the watchpoint support.
* [90/10/16 rwd]
* Created.
* [90/10/16 rpd]
*
*/
/*
* Author: Richard P. Draves, Carnegie Mellon University
* Date: 10/90
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <vm/vm_map.h>
#include <ddb/db_lex.h>
#include <ddb/db_watch.h>
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <machine/db_machdep.h>
/*
* Watchpoints.
*/
extern boolean_t db_map_equal();
extern boolean_t db_map_current();
extern vm_map_t db_map_addr();
boolean_t db_watchpoints_inserted = TRUE;
#define NWATCHPOINTS 100
struct db_watchpoint db_watch_table[NWATCHPOINTS];
db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0];
db_watchpoint_t db_free_watchpoints = 0;
db_watchpoint_t db_watchpoint_list = 0;
db_watchpoint_t
db_watchpoint_alloc()
{
register db_watchpoint_t watch;
if ((watch = db_free_watchpoints) != 0) {
db_free_watchpoints = watch->link;
return (watch);
}
if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) {
db_printf("All watchpoints used.\n");
return (0);
}
watch = db_next_free_watchpoint;
db_next_free_watchpoint++;
return (watch);
}
void
db_watchpoint_free(watch)
register db_watchpoint_t watch;
{
watch->link = db_free_watchpoints;
db_free_watchpoints = watch;
}
void
db_set_watchpoint(map, addr, size)
vm_map_t map;
db_addr_t addr;
vm_size_t size;
{
register db_watchpoint_t watch;
if (map == NULL) {
db_printf("No map.\n");
return;
}
/*
* Should we do anything fancy with overlapping regions?
*/
for (watch = db_watchpoint_list;
watch != 0;
watch = watch->link)
if (db_map_equal(watch->map, map) &&
(watch->loaddr == addr) &&
(watch->hiaddr == addr+size)) {
db_printf("Already set.\n");
return;
}
watch = db_watchpoint_alloc();
if (watch == 0) {
db_printf("Too many watchpoints.\n");
return;
}
watch->map = map;
watch->loaddr = addr;
watch->hiaddr = addr+size;
watch->link = db_watchpoint_list;
db_watchpoint_list = watch;
db_watchpoints_inserted = FALSE;
}
void
db_delete_watchpoint(map, addr)
vm_map_t map;
db_addr_t addr;
{
register db_watchpoint_t watch;
register db_watchpoint_t *prev;
for (prev = &db_watchpoint_list;
(watch = *prev) != 0;
prev = &watch->link)
if (db_map_equal(watch->map, map) &&
(watch->loaddr <= addr) &&
(addr < watch->hiaddr)) {
*prev = watch->link;
db_watchpoint_free(watch);
return;
}
db_printf("Not set.\n");
}
void
db_list_watchpoints()
{
register db_watchpoint_t watch;
if (db_watchpoint_list == 0) {
db_printf("No watchpoints set\n");
return;
}
db_printf(" Map Address Size\n");
for (watch = db_watchpoint_list;
watch != 0;
watch = watch->link)
db_printf("%s%8x %8x %x\n",
db_map_current(watch->map) ? "*" : " ",
watch->map, watch->loaddr,
watch->hiaddr - watch->loaddr);
}
/* Delete watchpoint */
/*ARGSUSED*/
void
db_deletewatch_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
db_delete_watchpoint(db_map_addr(addr), addr);
}
/* Set watchpoint */
/*ARGSUSED*/
void
db_watchpoint_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char * modif;
{
vm_size_t size;
db_expr_t value;
if (db_expression(&value))
size = (vm_size_t) value;
else
size = 4;
db_skip_to_eol();
db_set_watchpoint(db_map_addr(addr), addr, size);
}
/* list watchpoints */
void
db_listwatch_cmd()
{
db_list_watchpoints();
}
void
db_set_watchpoints()
{
register db_watchpoint_t watch;
if (!db_watchpoints_inserted) {
for (watch = db_watchpoint_list;
watch != 0;
watch = watch->link)
pmap_protect(watch->map->pmap,
trunc_page(watch->loaddr),
round_page(watch->hiaddr),
VM_PROT_READ);
db_watchpoints_inserted = TRUE;
}
}
void
db_clear_watchpoints()
{
db_watchpoints_inserted = FALSE;
}
boolean_t
db_find_watchpoint(map, addr, regs)
vm_map_t map;
db_addr_t addr;
db_regs_t *regs;
{
register db_watchpoint_t watch;
db_watchpoint_t found = 0;
for (watch = db_watchpoint_list;
watch != 0;
watch = watch->link)
if (db_map_equal(watch->map, map)) {
if ((watch->loaddr <= addr) &&
(addr < watch->hiaddr))
return (TRUE);
else if ((trunc_page(watch->loaddr) <= addr) &&
(addr < round_page(watch->hiaddr)))
found = watch;
}
/*
* We didn't hit exactly on a watchpoint, but we are
* in a protected region. We want to single-step
* and then re-protect.
*/
if (found) {
db_watchpoints_inserted = FALSE;
db_single_step(regs);
}
return (FALSE);
}
+74
View File
@@ -0,0 +1,74 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_watch.h,v $
* Revision 1.1 1992/03/25 21:45:40 pace
* Initial revision
*
* Revision 2.3 91/02/05 17:07:31 mrt
* Changed to new Mach copyright
* [91/01/31 16:20:09 mrt]
*
* Revision 2.2 90/10/25 14:44:21 rwd
* Generalized the watchpoint support.
* [90/10/16 rwd]
* Created.
* [90/10/16 rpd]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 10/90
*/
#ifndef _DDB_DB_WATCH_
#define _DDB_DB_WATCH_
#include <vm/vm_map.h>
#include <machine/db_machdep.h>
/*
* Watchpoint.
*/
typedef struct db_watchpoint {
vm_map_t map; /* in this map */
db_addr_t loaddr; /* from this address */
db_addr_t hiaddr; /* to this address */
struct db_watchpoint *link; /* link in in-use or free chain */
} *db_watchpoint_t;
extern boolean_t db_find_watchpoint(/* vm_map_t map, db_addr_t addr,
db_regs_t *regs */);
extern void db_set_watchpoints();
extern void db_clear_watchpoints();
extern void db_set_watchpoint(/* vm_map_t map, db_addr_t addr, vm_size_t size */);
extern void db_delete_watchpoint(/* vm_map_t map, db_addr_t addr */);
extern void db_list_watchpoints();
#endif _DDB_DB_WATCH_
+120
View File
@@ -0,0 +1,120 @@
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_write_cmd.c,v $
* Revision 1.1 1992/03/25 21:45:42 pace
* Initial revision
*
* Revision 2.4 91/02/05 17:07:35 mrt
* Changed to new Mach copyright
* [91/01/31 16:20:19 mrt]
*
* Revision 2.3 90/10/25 14:44:26 rwd
* Changed db_write_cmd to print unsigned.
* [90/10/19 rpd]
*
* Revision 2.2 90/08/27 21:53:54 dbg
* Set db_prev and db_next instead of explicitly advancing dot.
* [90/08/22 dbg]
* Reflected changes in db_printsym()'s calling seq.
* [90/08/20 af]
* Warn user if nothing was written.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_lex.h>
#include <ddb/db_access.h>
#include <ddb/db_command.h>
#include <ddb/db_sym.h>
/*
* Write to file.
*/
/*ARGSUSED*/
void
db_write_cmd(address, have_addr, count, modif)
db_expr_t address;
boolean_t have_addr;
db_expr_t count;
char * modif;
{
register
db_addr_t addr;
register
db_expr_t old_value;
db_expr_t new_value;
register int size;
boolean_t wrote_one = FALSE;
addr = (db_addr_t) address;
switch (modif[0]) {
case 'b':
size = 1;
break;
case 'h':
size = 2;
break;
case 'l':
case '\0':
size = 4;
break;
default:
db_error("Unknown size\n");
return;
}
while (db_expression(&new_value)) {
old_value = db_get_value(addr, size, FALSE);
db_printsym(addr, DB_STGY_ANY);
db_printf("\t\t%#8n\t=\t%#8n\n", old_value, new_value);
db_put_value(addr, size, new_value);
addr += size;
wrote_one = TRUE;
}
if (!wrote_one)
db_error("Nothing written.\n");
db_next = addr;
db_prev = addr - size;
db_skip_to_eol();
}
+903
View File
@@ -0,0 +1,903 @@
/*#define DEBUG 1*/
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Don Ahn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)fd.c 7.4 (Berkeley) 5/25/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00153
* -------------------- ----- ----------------------
*
* 20 Apr 93 Julian Elischer Heavily re worked, see notes below
*
* Largely rewritten to handle multiple controllers and drives
* By Julian Elischer, Sun Apr 4 16:34:33 WST 1993
*/
char rev[] = "$Revision: 1.10 $";
/*
* $Header: /usr/src/sys.386bsd/i386/isa/RCS/fd.c,v 1.10 93/04/13 16:53:29 root Exp $
*/
/*
* $Log: fd.c,v $
* Revision 1.10 93/04/13 16:53:29 root
* make sure turning off a drive motor doesn't deselect another
* drive active at the time.
* Also added a pointer from the fd_data to it's fd_type.
*
* Revision 1.9 93/04/13 15:31:02 root
* make all seeks go through DOSEEK state so are sure of being done right.
*
* Revision 1.8 93/04/12 21:20:13 root
* only check if old fd is the one we are working on if there IS
* an old fd pointer. (in fdstate())
*
* Revision 1.7 93/04/11 17:05:35 root
* cleanup timeouts etc.
* also fix bug to select teh correct drive when running > 1 drive
* at a time.
*
* Revision 1.6 93/04/05 00:48:45 root
* change a timeout and add version to banner message
*
* Revision 1.5 93/04/04 16:39:08 root
* first working version.. some floppy controllers don't seem to
* like 2 int. status inquiries in a row.
*
*/
#include "fd.h"
#if NFD > 0
#include "param.h"
#include "dkbad.h"
#include "systm.h"
#include "conf.h"
#include "file.h"
#include "ioctl.h"
#include "buf.h"
#include "uio.h"
#include "i386/isa/isa.h"
#include "i386/isa/isa_device.h"
#include "i386/isa/fdreg.h"
#include "i386/isa/icu.h"
#include "i386/isa/rtc.h"
#undef NFD
#define NFD 2
#define FDUNIT(s) ((s>>3)&1)
#define FDTYPE(s) ((s)&7)
#define b_cylin b_resid
#define FDBLK 512
#define NUMTYPES 4
struct fd_type {
int sectrac; /* sectors per track */
int secsize; /* size code for sectors */
int datalen; /* data len when secsize = 0 */
int gap; /* gap len between sectors */
int tracks; /* total num of tracks */
int size; /* size of disk in sectors */
int steptrac; /* steps per cylinder */
int trans; /* transfer speed code */
int heads; /* number of heads */
};
struct fd_type fd_types[NUMTYPES] =
{
{ 18,2,0xFF,0x1B,80,2880,1,0,2 }, /* 1.44 meg HD 3.5in floppy */
{ 15,2,0xFF,0x1B,80,2400,1,0,2 }, /* 1.2 meg HD floppy */
{ 9,2,0xFF,0x23,40,720,2,1,2 }, /* 360k floppy in 1.2meg drive */
{ 9,2,0xFF,0x2A,40,720,1,1,2 }, /* 360k floppy in DD drive */
};
#define DRVS_PER_CTLR 2
/***********************************************************************\
* Per controller structure. *
\***********************************************************************/
struct fdc_data
{
int fdcu; /* our unit number */
int baseport;
int dmachan;
int flags;
#define FDC_ATTACHED 0x01
struct fd_data *fd;
int fdu; /* the active drive */
struct buf head; /* Head of buf chain */
struct buf rhead; /* Raw head of buf chain */
int state;
int retry;
int status[7]; /* copy of the registers */
}fdc_data[(NFD+1)/DRVS_PER_CTLR];
/***********************************************************************\
* Per drive structure. *
* N per controller (presently 2) (DRVS_PER_CTLR) *
\***********************************************************************/
struct fd_data {
struct fdc_data *fdc;
int fdu; /* this unit number */
int fdsu; /* this units number on this controller */
int type; /* Drive type (HD, DD */
struct fd_type *ft; /* pointer to the type descriptor */
int flags;
#define FD_OPEN 0x01 /* it's open */
#define FD_ACTIVE 0x02 /* it's active */
#define FD_MOTOR 0x04 /* motor should be on */
#define FD_MOTOR_WAIT 0x08 /* motor coming up */
int skip;
int hddrv;
int track; /* where we think the head is */
} fd_data[NFD];
/***********************************************************************\
* Throughout this file the following conventions will be used: *
* fd is a pointer to the fd_data struct for the drive in question *
* fdc is a pointer to the fdc_data struct for the controller *
* fdu is the floppy drive unit number *
* fdcu is the floppy controller unit number *
* fdsu is the floppy drive unit number on that controller. (sub-unit) *
\***********************************************************************/
typedef int fdu_t;
typedef int fdcu_t;
typedef int fdsu_t;
typedef struct fd_data *fd_p;
typedef struct fdc_data *fdc_p;
#define DEVIDLE 0
#define FINDWORK 1
#define DOSEEK 2
#define SEEKCOMPLETE 3
#define IOCOMPLETE 4
#define RECALCOMPLETE 5
#define STARTRECAL 6
#define RESETCTLR 7
#define SEEKWAIT 8
#define RECALWAIT 9
#define MOTORWAIT 10
#define IOTIMEDOUT 11
#ifdef DEBUG
char *fdstates[] =
{
"DEVIDLE",
"FINDWORK",
"DOSEEK",
"SEEKCOMPLETE",
"IOCOMPLETE",
"RECALCOMPLETE",
"STARTRECAL",
"RESETCTLR",
"SEEKWAIT",
"RECALWAIT",
"MOTORWAIT",
"IOTIMEDOUT"
};
int fd_debug = 1;
#define TRACE0(arg) if(fd_debug) printf(arg)
#define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2)
#else DEBUG
#define TRACE0(arg)
#define TRACE1(arg1,arg2)
#endif DEBUG
extern int hz;
/* state needed for current transfer */
/****************************************************************************/
/* autoconfiguration stuff */
/****************************************************************************/
int fdprobe(), fdattach(), fd_turnoff();
struct isa_driver fddriver = {
fdprobe, fdattach, "fd",
};
/*
* probe for existance of controller
*/
fdprobe(dev)
struct isa_device *dev;
{
fdcu_t fdcu = dev->id_unit;
if(fdc_data[fdcu].flags & FDC_ATTACHED)
{
printf("fdc: same unit (%d) used multiple times\n",fdcu);
return 0;
}
fdc_data[fdcu].baseport = dev->id_iobase;
/* see if it can handle a command */
if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0)
{
return(0);
}
out_fdc(fdcu,0xDF);
out_fdc(fdcu,2);
return (IO_FDCSIZE);
}
/*
* wire controller into system, look for floppy units
*/
fdattach(dev)
struct isa_device *dev;
{
unsigned fdt,st0, cyl;
int hdr;
fdu_t fdu;
fdcu_t fdcu = dev->id_unit;
fdc_p fdc = fdc_data + fdcu;
fd_p fd;
int fdsu;
fdc->fdcu = fdcu;
fdc->flags |= FDC_ATTACHED;
fdc->dmachan = dev->id_drq;
fdc->state = DEVIDLE;
fdt = rtcin(RTC_FDISKETTE);
hdr = 0;
/* check for each floppy drive */
for (fdu = (fdcu * DRVS_PER_CTLR),fdsu = 0;
((fdu < NFD) && (fdsu < DRVS_PER_CTLR));
fdu++,fdsu++)
{
/* is there a unit? */
if ((fdt & 0xf0) == RTCFDT_NONE)
continue;
#ifdef notyet
/* select it */
fd_turnon1(fdu);
spinwait(1000); /* 1 sec */
out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */
out_fdc(fdcu,fdsu);
spinwait(1000); /* 1 sec */
/* anything responding */
out_fdc(fdcu,NE7CMD_SENSEI);
st0 = in_fdc(fdcu);
cyl = in_fdc(fdcu);
if (st0 & 0xd0)
continue;
#endif
fd_data[fdu].track = -2;
fd_data[fdu].fdc = fdc;
fd_data[fdu].fdsu = fdsu;
/* yes, announce it */
if (!hdr)
printf(" drives ");
else
printf(", ");
printf("%d: ", fdu);
if ((fdt & 0xf0) == RTCFDT_12M) {
printf("1.2M");
fd_data[fdu].type = 1;
fd_data[fdu].ft = fd_types + 1;
}
if ((fdt & 0xf0) == RTCFDT_144M) {
printf("1.44M");
fd_data[fdu].type = 0;
fd_data[fdu].ft = fd_types + 0;
}
fdt <<= 4;
fd_turnoff(fdu);
hdr = 1;
}
printf(" %s ",rev);
/* Set transfer to 500kbps */
outb(fdc->baseport+fdctl,0); /*XXX*/
}
int
fdsize(dev)
dev_t dev;
{
return(0);
}
/****************************************************************************/
/* fdstrategy */
/****************************************************************************/
fdstrategy(bp)
register struct buf *bp; /* IO operation to perform */
{
register struct buf *dp,*dp0,*dp1;
long nblocks,blknum;
int s;
fdcu_t fdcu;
fdu_t fdu;
fdc_p fdc;
fd_p fd;
fdu = FDUNIT(minor(bp->b_dev));
fd = &fd_data[fdu];
fdc = fd->fdc;
fdcu = fdc->fdcu;
/*type = FDTYPE(minor(bp->b_dev));*/
if ((fdu >= NFD) || (bp->b_blkno < 0)) {
printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n",
fdu, bp->b_blkno, bp->b_bcount);
pg("fd:error in fdstrategy");
bp->b_error = EINVAL;
bp->b_flags |= B_ERROR;
goto bad;
}
/*
* Set up block calculations.
*/
blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK;
nblocks = fd->ft->size;
if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
if (blknum == nblocks) {
bp->b_resid = bp->b_bcount;
} else {
bp->b_error = ENOSPC;
bp->b_flags |= B_ERROR;
}
goto bad;
}
bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads);
dp = &(fdc->head);
s = splbio();
disksort(dp, bp);
untimeout(fd_turnoff,fdu); /* a good idea */
fdstart(fdcu);
splx(s);
return;
bad:
biodone(bp);
}
/****************************************************************************/
/* motor control stuff */
/* remember to not deselect the drive we're working on */
/****************************************************************************/
set_motor(fdcu_t fdcu, fdu_t fdu, int reset)
{
int m0,m1;
int selunit;
fd_p fd;
if(fd = fdc_data[fdcu].fd)/* yes an assign! */
{
selunit = fd->fdsu;
}
else
{
selunit = 0;
}
m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR;
m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR;
outb(fdc_data[fdcu].baseport+fdout,
selunit
| (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
| (m0 ? FDO_MOEN0 : 0)
| (m1 ? FDO_MOEN1 : 0));
TRACE1("[0x%x->fdout]",(
selunit
| (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
| (m0 ? FDO_MOEN0 : 0)
| (m1 ? FDO_MOEN1 : 0)));
}
fd_turnoff(fdu_t fdu)
{
fd_p fd = fd_data + fdu;
fd->flags &= ~FD_MOTOR;
set_motor(fd->fdc->fdcu,fd->fdsu,0);
}
fd_motor_on(fdu_t fdu)
{
fd_p fd = fd_data + fdu;
fd->flags &= ~FD_MOTOR_WAIT;
if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
{
fd_pseudointr(fd->fdc->fdcu);
}
}
fd_turnon(fdu_t fdu)
{
fd_p fd = fd_data + fdu;
if(!(fd->flags & FD_MOTOR))
{
fd_turnon1(fdu);
fd->flags |= FD_MOTOR_WAIT;
timeout(fd_motor_on,fdu,hz); /* in 1 sec its ok */
}
}
fd_turnon1(fdu_t fdu)
{
fd_p fd = fd_data + fdu;
fd->flags |= FD_MOTOR;
set_motor(fd->fdc->fdcu,fd->fdsu,0);
}
/****************************************************************************/
/* fdc in/out */
/****************************************************************************/
int
in_fdc(fdcu_t fdcu)
{
int baseport = fdc_data[fdcu].baseport;
int i, j = 100000;
while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM))
!= (NE7_DIO|NE7_RQM) && j-- > 0)
if (i == NE7_RQM) return -1;
if (j <= 0)
return(-1);
#ifdef DEBUG
i = inb(baseport+fddata);
TRACE1("[fddata->0x%x]",(unsigned char)i);
return(i);
#else
return inb(baseport+fddata);
#endif
}
out_fdc(fdcu_t fdcu,int x)
{
int baseport = fdc_data[fdcu].baseport;
int i = 100000;
while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0);
while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0);
if (i <= 0) return (-1);
outb(baseport+fddata,x);
TRACE1("[0x%x->fddata]",x);
return (0);
}
static fdopenf;
/****************************************************************************/
/* fdopen/fdclose */
/****************************************************************************/
Fdopen(dev, flags)
dev_t dev;
int flags;
{
fdu_t fdu = FDUNIT(minor(dev));
/*int type = FDTYPE(minor(dev));*/
int s;
/* check bounds */
if (fdu >= NFD) return(ENXIO);
/*if (type >= NUMTYPES) return(ENXIO);*/
fd_data[fdu].flags |= FD_OPEN;
return 0;
}
fdclose(dev, flags)
dev_t dev;
{
fdu_t fdu = FDUNIT(minor(dev));
fd_data[fdu].flags &= ~FD_OPEN;
return(0);
}
/***************************************************************\
* fdstart *
* We have just queued something.. if the controller is not busy *
* then simulate the case where it has just finished a command *
* So that it (the interrupt routine) looks on the queue for more*
* work to do and picks up what we just added. *
* If the controller is already busy, we need do nothing, as it *
* will pick up our work when the present work completes *
\***************************************************************/
fdstart(fdcu_t fdcu)
{
register struct buf *dp,*bp;
int s;
fdu_t fdu;
s = splbio();
if(fdc_data[fdcu].state == DEVIDLE)
{
fdintr(fdcu);
}
splx(s);
}
fd_timeout(fdcu_t fdcu)
{
fdu_t fdu = fdc_data[fdcu].fdu;
int st0, st3, cyl;
struct buf *dp,*bp;
dp = &fdc_data[fdcu].head;
bp = dp->b_actf;
out_fdc(fdcu,NE7CMD_SENSED);
out_fdc(fdcu,fd_data[fdu].hddrv);
st3 = in_fdc(fdcu);
out_fdc(fdcu,NE7CMD_SENSEI);
st0 = in_fdc(fdcu);
cyl = in_fdc(fdcu);
printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n",
fdu,
st0,
NE7_ST0BITS,
cyl,
st3,
NE7_ST3BITS);
if (bp)
{
retrier(fdcu);
fdc_data[fdcu].status[0] = 0xc0;
fdc_data[fdcu].state = IOTIMEDOUT;
if( fdc_data[fdcu].retry < 6)
fdc_data[fdcu].retry = 6;
}
else
{
fdc_data[fdcu].fd = (fd_p) 0;
fdc_data[fdcu].fdu = -1;
fdc_data[fdcu].state = DEVIDLE;
}
fd_pseudointr(fdcu);
}
/* just ensure it has the right spl */
fd_pseudointr(fdcu_t fdcu)
{
int s;
s = splbio();
fdintr(fdcu);
splx(s);
}
/***********************************************************************\
* fdintr *
* keep calling the state machine until it returns a 0 *
* ALWAYS called at SPLBIO *
\***********************************************************************/
fdintr(fdcu_t fdcu)
{
fdc_p fdc = fdc_data + fdcu;
while(fdstate(fdcu, fdc));
}
/***********************************************************************\
* The controller state machine. *
* if it returns a non zero value, it should be called again immediatly *
\***********************************************************************/
int fdstate(fdcu_t fdcu, fdc_p fdc)
{
int read,head,trac,sec,i,s,sectrac,cyl,st0;
unsigned long blknum;
fdu_t fdu = fdc->fdu;
fd_p fd;
register struct buf *dp,*bp;
dp = &(fdc->head);
bp = dp->b_actf;
if(!bp)
{
/***********************************************\
* nothing left for this controller to do *
* Force into the IDLE state, *
\***********************************************/
fdc->state = DEVIDLE;
if(fdc->fd)
{
printf("unexpected valid fd pointer (fdu = %d)\n"
,fdc->fdu);
fdc->fd = (fd_p) 0;
fdc->fdu = -1;
}
TRACE1("[fdc%d IDLE]",fdcu);
return(0);
}
fdu = FDUNIT(minor(bp->b_dev));
fd = fd_data + fdu;
if (fdc->fd && (fd != fdc->fd))
{
printf("confused fd pointers\n");
}
read = bp->b_flags & B_READ;
TRACE1("fd%d",fdu);
TRACE1("[%s]",fdstates[fdc->state]);
TRACE1("(0x%x)",fd->flags);
untimeout(fd_turnoff, fdu);
timeout(fd_turnoff,fdu,4 * hz);
switch (fdc->state)
{
case DEVIDLE:
case FINDWORK: /* we have found new work */
fdc->retry = 0;
fd->skip = 0;
fdc->fd = fd;
fdc->fdu = fdu;
/*******************************************************\
* If the next drive has a motor startup pending, then *
* it will start up in it's own good time *
\*******************************************************/
if(fd->flags & FD_MOTOR_WAIT)
{
fdc->state = MOTORWAIT;
return(0); /* come back later */
}
/*******************************************************\
* Maybe if it's not starting, it SHOULD be starting *
\*******************************************************/
if (!(fd->flags & FD_MOTOR))
{
fdc->state = MOTORWAIT;
fd_turnon(fdu);
return(0);
}
else /* at least make sure we are selected */
{
set_motor(fdcu,fd->fdsu,0);
}
fdc->state = DOSEEK;
break;
case DOSEEK:
if (bp->b_cylin == fd->track)
{
fdc->state = SEEKCOMPLETE;
break;
}
out_fdc(fdcu,NE7CMD_SEEK); /* Seek function */
out_fdc(fdcu,fd->fdsu); /* Drive number */
out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac);
fd->track = -2;
fdc->state = SEEKWAIT;
return(0); /* will return later */
case SEEKWAIT:
/* allow heads to settle */
timeout(fd_pseudointr,fdcu,hz/50);
fdc->state = SEEKCOMPLETE;
return(0); /* will return later */
break;
case SEEKCOMPLETE : /* SEEK DONE, START DMA */
/* Make sure seek really happened*/
if(fd->track == -2)
{
int descyl = bp->b_cylin * fd->ft->steptrac;
out_fdc(fdcu,NE7CMD_SENSEI);
i = in_fdc(fdcu);
cyl = in_fdc(fdcu);
if (cyl != descyl)
{
printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu,
descyl, cyl, i, NE7_ST0BITS);
return(retrier(fdcu));
}
}
fd->track = bp->b_cylin;
isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip,
FDBLK, fdc->dmachan);
blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
+ fd->skip/FDBLK;
sectrac = fd->ft->sectrac;
sec = blknum % (sectrac * fd->ft->heads);
head = sec / sectrac;
sec = sec % sectrac + 1;
/*XXX*/ fd->hddrv = ((head&1)<<2)+fdu;
if (read)
{
out_fdc(fdcu,NE7CMD_READ); /* READ */
}
else
{
out_fdc(fdcu,NE7CMD_WRITE); /* WRITE */
}
out_fdc(fdcu,head << 2 | fdu); /* head & unit */
out_fdc(fdcu,fd->track); /* track */
out_fdc(fdcu,head);
out_fdc(fdcu,sec); /* sector XXX +1? */
out_fdc(fdcu,fd->ft->secsize); /* sector size */
out_fdc(fdcu,sectrac); /* sectors/track */
out_fdc(fdcu,fd->ft->gap); /* gap size */
out_fdc(fdcu,fd->ft->datalen); /* data length */
fdc->state = IOCOMPLETE;
timeout(fd_timeout,fdcu,2 * hz);
return(0); /* will return later */
case IOCOMPLETE: /* IO DONE, post-analyze */
untimeout(fd_timeout,fdcu);
for(i=0;i<7;i++)
{
fdc->status[i] = in_fdc(fdcu);
}
case IOTIMEDOUT: /*XXX*/
isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip,
FDBLK, fdc->dmachan);
if (fdc->status[0]&0xF8)
{
return(retrier(fdcu));
}
/* All OK */
fd->skip += FDBLK;
if (fd->skip < bp->b_bcount)
{
/* set up next transfer */
blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
+ fd->skip/FDBLK;
bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads));
fdc->state = DOSEEK;
}
else
{
/* ALL DONE */
fd->skip = 0;
bp->b_resid = 0;
dp->b_actf = bp->av_forw;
biodone(bp);
fdc->fd = (fd_p) 0;
fdc->fdu = -1;
fdc->state = FINDWORK;
}
return(1);
case RESETCTLR:
/* Try a reset, keep motor on */
set_motor(fdcu,fd->fdsu,1);
DELAY(100);
set_motor(fdcu,fd->fdsu,0);
outb(fdc->baseport+fdctl,fd->ft->trans);
TRACE1("[0x%x->fdctl]",fd->ft->trans);
fdc->retry++;
fdc->state = STARTRECAL;
break;
case STARTRECAL:
out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */
out_fdc(fdcu,0xDF);
out_fdc(fdcu,2);
out_fdc(fdcu,NE7CMD_RECAL); /* Recalibrate Function */
out_fdc(fdcu,fdu);
fdc->state = RECALWAIT;
return(0); /* will return later */
case RECALWAIT:
/* allow heads to settle */
timeout(fd_pseudointr,fdcu,hz/30);
fdc->state = RECALCOMPLETE;
return(0); /* will return later */
case RECALCOMPLETE:
out_fdc(fdcu,NE7CMD_SENSEI);
st0 = in_fdc(fdcu);
cyl = in_fdc(fdcu);
if (cyl != 0)
{
printf("fd%d: recal failed ST0 %b cyl %d\n", fdu,
st0, NE7_ST0BITS, cyl);
return(retrier(fdcu));
}
fd->track = 0;
/* Seek (probably) necessary */
fdc->state = DOSEEK;
return(1); /* will return immediatly */
case MOTORWAIT:
if(fd->flags & FD_MOTOR_WAIT)
{
return(0); /* time's not up yet */
}
fdc->state = DOSEEK;
return(1); /* will return immediatly */
default:
printf("Unexpected FD int->");
out_fdc(fdcu,NE7CMD_SENSEI);
st0 = in_fdc(fdcu);
cyl = in_fdc(fdcu);
printf("ST0 = %lx, PCN = %lx\n",i,sec);
out_fdc(fdcu,0x4A);
out_fdc(fdcu,fd->fdsu);
for(i=0;i<7;i++) {
fdc->status[i] = in_fdc(fdcu);
}
printf("intr status :%lx %lx %lx %lx %lx %lx %lx ",
fdc->status[0],
fdc->status[1],
fdc->status[2],
fdc->status[3],
fdc->status[4],
fdc->status[5],
fdc->status[6] );
return(0);
}
return(1); /* Come back immediatly to new state */
}
retrier(fdcu_t fdcu)
{
fdc_p fdc = fdc_data + fdcu;
register struct buf *dp,*bp;
dp = &(fdc->head);
bp = dp->b_actf;
switch(fdc->retry)
{
case 0: case 1: case 2:
fdc->state = SEEKCOMPLETE;
break;
case 3: case 4: case 5:
fdc->state = STARTRECAL;
break;
case 6:
fdc->state = RESETCTLR;
break;
case 7:
break;
default:
{
printf("fd%d: hard error (ST0 %b ",
fdc->fdu, fdc->status[0], NE7_ST0BITS);
printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS);
printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS);
printf(" ST3 %b ", fdc->status[3], NE7_ST3BITS);
printf("cyl %d hd %d sec %d)\n",
fdc->status[4], fdc->status[5], fdc->status[6]);
}
bp->b_flags |= B_ERROR;
bp->b_error = EIO;
bp->b_resid = bp->b_bcount - fdc->fd->skip;
dp->b_actf = bp->av_forw;
fdc->fd->skip = 0;
biodone(bp);
fdc->state = FINDWORK;
fdc->fd = (fd_p) 0;
fdc->fdu = -1;
return(1);
}
fdc->retry++;
return(1);
}
#endif
+72
View File
@@ -0,0 +1,72 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)fdreg.h 7.1 (Berkeley) 5/9/91
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00153
* -------------------- ----- ----------------------
*
* 20 Apr 93 Julian Elischer Heavily re worked, see notes below
*/
/*
* AT floppy controller registers and bitfields
*/
/* uses NEC765 controller */
#include "../i386/isa/ic/nec765.h"
/* registers */
#define fdout 2 /* Digital Output Register (W) */
#define FDO_FDSEL 0x03 /* floppy device select */
#define FDO_FRST 0x04 /* floppy controller reset */
#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */
#define FDO_MOEN0 0x10 /* motor enable drive 0 */
#define FDO_MOEN1 0x20 /* motor enable drive 1 */
#define FDO_MOEN2 0x30 /* motor enable drive 2 */
#define FDO_MOEN3 0x40 /* motor enable drive 3 */
#define fdsts 4 /* NEC 765 Main Status Register (R) */
#define fddata 5 /* NEC 765 Data Register (R/W) */
#define fdctl 7 /* Control Register (W) */
#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */
#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */
#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */
#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */
#define fdin 7 /* Digital Input Register (R) */
#define FDI_DCHG 0x80 /* diskette has been changed */
+9
View File
@@ -0,0 +1,9 @@
/*
* Intel 8237 DMA Controller
*/
#define DMA37MD_SINGLE 0x40 /* single pass mode */
#define DMA37MD_CASCADE 0xc0 /* cascade mode */
#define DMA37MD_WRITE 0x04 /* read the device, write memory operation */
#define DMA37MD_READ 0x08 /* write the device, read memory operation */
+71
View File
@@ -0,0 +1,71 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)nec765.h 7.1 (Berkeley) 5/9/91
*/
/*
* Nec 765 floppy disc controller definitions
*/
/* Main status register */
#define NE7_DAB 0x01 /* Diskette drive A is seeking, thus busy */
#define NE7_DBB 0x02 /* Diskette drive B is seeking, thus busy */
#define NE7_CB 0x10 /* Diskette Controller Busy */
#define NE7_NDM 0x20 /* Diskette Controller in Non Dma Mode */
#define NE7_DIO 0x40 /* Diskette Controller Data register I/O */
#define NE7_RQM 0x80 /* Diskette Controller ReQuest for Master */
/* Status register ST0 */
#define NE7_ST0BITS "\020\010invld\007abnrml\006seek_cmplt\005drv_chck\004drive_rdy\003top_head"
/* Status register ST1 */
#define NE7_ST1BITS "\020\010end_of_cyl\006bad_crc\005data_overrun\003sec_not_fnd\002write_protect\001no_am"
/* Status register ST2 */
#define NE7_ST2BITS "\020\007ctrl_mrk\006bad_crc\005wrong_cyl\004scn_eq\003scn_not_fnd\002bad_cyl\001no_dam"
/* Status register ST3 */
#define NE7_ST3BITS "\020\010fault\007write_protect\006drdy\005tk0\004two_side\003side_sel\002"
/* Commands */
#define NE7CMD_SPECIFY 3 /* specify drive parameters - requires unit
parameters byte */
#define NE7CMD_SENSED 4 /* sense drive - requires unit select byte */
#define NE7CMD_WRITE 0xc5 /* write - requires eight additional bytes */
#define NE7CMD_READ 0xe6 /* read - requires eight additional bytes */
#define NE7CMD_FORMAT 0x4c /* format - requires five additional bytes */
#define NE7CMD_RECAL 7 /* recalibrate drive - requires
unit select byte */
#define NE7CMD_SENSEI 8 /* sense controller interrupt status */
#define NE7CMD_SEEK 15 /* seek drive - requires unit select byte
and new cyl byte */
+50
View File
@@ -0,0 +1,50 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ns16550.h 7.1 (Berkeley) 5/9/91
*/
/*
* NS16550 UART registers
*/
#define com_data 0 /* data register (R/W) */
#define com_dlbl 0 /* divisor latch low (W) */
#define com_dlbh 1 /* divisor latch high (W) */
#define com_ier 1 /* interrupt enable (W) */
#define com_iir 2 /* interrupt identification (R) */
#define com_fifo 2 /* FIFO control (W) */
#define com_lctl 3 /* line control register (R/W) */
#define com_cfcr 3 /* line control register (R/W) */
#define com_mcr 4 /* modem control register (R/W) */
#define com_lsr 5 /* line status register (R/W) */
#define com_msr 6 /* modem status register (R/W) */
+1721
View File
File diff suppressed because it is too large Load Diff
+113
View File
@@ -0,0 +1,113 @@
/*-
* Copyright (c) 1991 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)comreg.h 7.2 (Berkeley) 5/9/91
*/
/* 16 bit baud rate divisor (lower byte in dca_data, upper in dca_ier) */
#define COMBRD(x) (1843200 / (16*(x)))
/* interrupt enable register */
#define IER_ERXRDY 0x1
#define IER_ETXRDY 0x2
#define IER_ERLS 0x4
#define IER_EMSC 0x8
/* interrupt identification register */
#define IIR_IMASK 0xf
#define IIR_RXTOUT 0xc
#define IIR_RLS 0x6
#define IIR_RXRDY 0x4
#define IIR_TXRDY 0x2
#define IIR_NOPEND 0x1
#define IIR_MLSC 0x0
#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
/* fifo control register */
#define FIFO_ENABLE 0x01
#define FIFO_RCV_RST 0x02
#define FIFO_XMT_RST 0x04
#define FIFO_DMA_MODE 0x08
#define FIFO_TRIGGER_1 0x00
#define FIFO_TRIGGER_4 0x40
#define FIFO_TRIGGER_8 0x80
#define FIFO_TRIGGER_14 0xc0
/* character format control register */
#define CFCR_DLAB 0x80
#define CFCR_SBREAK 0x40
#define CFCR_PZERO 0x30
#define CFCR_PONE 0x20
#define CFCR_PEVEN 0x10
#define CFCR_PODD 0x00
#define CFCR_PENAB 0x08
#define CFCR_STOPB 0x04
#define CFCR_8BITS 0x03
#define CFCR_7BITS 0x02
#define CFCR_6BITS 0x01
#define CFCR_5BITS 0x00
/* modem control register */
#define MCR_LOOPBACK 0x10
#define MCR_IENABLE 0x08
#define MCR_DRS 0x04
#define MCR_RTS 0x02
#define MCR_DTR 0x01
/* line status register */
#define LSR_RCV_FIFO 0x80
#define LSR_TSRE 0x40
#define LSR_TXRDY 0x20
#define LSR_BI 0x10
#define LSR_FE 0x08
#define LSR_PE 0x04
#define LSR_OE 0x02
#define LSR_RXRDY 0x01
#define LSR_RCV_MASK 0x1f
/* modem status register */
#define MSR_DCD 0x80
#define MSR_RI 0x40
#define MSR_DSR 0x20
#define MSR_CTS 0x10
#define MSR_DDCD 0x08
#define MSR_TERI 0x04
#define MSR_DDSR 0x02
#define MSR_DCTS 0x01
/*
* WARNING: Serial console is assumed to be at COM1 address
* and CONUNIT must be 0.
*/
#define CONADDR (0x3f8)
#define CONUNIT (0)
+520
View File
@@ -0,0 +1,520 @@
/*
* spkr.c -- device driver for console speaker on 80386
*
* v1.1 by Eric S. Raymond (esr@snark.thyrsus.com) Feb 1990
* modified for 386bsd by Andrew A. Chernov <ache@astral.msk.su>
* 386bsd only clean version, all SYSV stuff removed
* use hz value from param.c
*/
#include "speaker.h"
#if NSPEAKER > 0
#include "param.h"
#include "kernel.h"
#include "errno.h"
#include "buf.h"
#include "uio.h"
#include "spkr.h"
/**************** MACHINE DEPENDENT PART STARTS HERE *************************
*
* This section defines a function tone() which causes a tone of given
* frequency and duration from the 80x86's console speaker.
* Another function endtone() is defined to force sound off, and there is
* also a rest() entry point to do pauses.
*
* Audible sound is generated using the Programmable Interval Timer (PIT) and
* Programmable Peripheral Interface (PPI) attached to the 80x86's speaker. The
* PPI controls whether sound is passed through at all; the PIT's channel 2 is
* used to generate clicks (a square wave) of whatever frequency is desired.
*/
/*
* PIT and PPI port addresses and control values
*
* Most of the magic is hidden in the TIMER_PREP value, which selects PIT
* channel 2, frequency LSB first, square-wave mode and binary encoding.
* The encoding is as follows:
*
* +----------+----------+---------------+-----+
* | 1 0 | 1 1 | 0 1 1 | 0 |
* | SC1 SC0 | RW1 RW0 | M2 M1 M0 | BCD |
* +----------+----------+---------------+-----+
* Counter Write Mode 3 Binary
* Channel 2 LSB first, (Square Wave) Encoding
* MSB second
*/
#define PPI 0x61 /* port of Programmable Peripheral Interface */
#define PPI_SPKR 0x03 /* turn these PPI bits on to pass sound */
#define PIT_CTRL 0x43 /* PIT control address */
#define PIT_COUNT 0x42 /* PIT count address */
#define PIT_MODE 0xB6 /* set timer mode for sound generation */
/*
* Magic numbers for timer control.
*/
#define TIMER_CLK 1193180L /* corresponds to 18.2 MHz tick rate */
static int endtone()
/* turn off the speaker, ending current tone */
{
wakeup((caddr_t)endtone);
outb(PPI, inb(PPI) & ~PPI_SPKR);
}
static void tone(hz, ticks)
/* emit tone of frequency hz for given number of ticks */
unsigned int hz, ticks;
{
unsigned int divisor = TIMER_CLK / hz;
int sps;
#ifdef DEBUG
printf("tone: hz=%d ticks=%d\n", hz, ticks);
#endif /* DEBUG */
/* set timer to generate clicks at given frequency in Hertz */
sps = spltty();
outb(PIT_CTRL, PIT_MODE); /* prepare timer */
outb(PIT_COUNT, (unsigned char) divisor); /* send lo byte */
outb(PIT_COUNT, (divisor >> 8)); /* send hi byte */
splx(sps);
/* turn the speaker on */
outb(PPI, inb(PPI) | PPI_SPKR);
/*
* Set timeout to endtone function, then give up the timeslice.
* This is so other processes can execute while the tone is being
* emitted.
*/
timeout((caddr_t)endtone, (caddr_t)NULL, ticks);
sleep((caddr_t)endtone, PZERO - 1);
}
static int endrest()
/* end a rest */
{
wakeup((caddr_t)endrest);
}
static void rest(ticks)
/* rest for given number of ticks */
int ticks;
{
/*
* Set timeout to endrest function, then give up the timeslice.
* This is so other processes can execute while the rest is being
* waited out.
*/
#ifdef DEBUG
printf("rest: %d\n", ticks);
#endif /* DEBUG */
timeout((caddr_t)endrest, (caddr_t)NULL, ticks);
sleep((caddr_t)endrest, PZERO - 1);
}
/**************** PLAY STRING INTERPRETER BEGINS HERE **********************
*
* Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement;
* M[LNS] are missing and the ~ synonym and octave-tracking facility is added.
* Requires tone(), rest(), and endtone(). String play is not interruptible
* except possibly at physical block boundaries.
*/
typedef int bool;
#define TRUE 1
#define FALSE 0
#define toupper(c) ((c) - ' ' * (((c) >= 'a') && ((c) <= 'z')))
#define isdigit(c) (((c) >= '0') && ((c) <= '9'))
#define dtoi(c) ((c) - '0')
static int octave; /* currently selected octave */
static int whole; /* whole-note time at current tempo, in ticks */
static int value; /* whole divisor for note time, quarter note = 1 */
static int fill; /* controls spacing of notes */
static bool octtrack; /* octave-tracking on? */
static bool octprefix; /* override current octave-tracking state? */
/*
* Magic number avoidance...
*/
#define SECS_PER_MIN 60 /* seconds per minute */
#define WHOLE_NOTE 4 /* quarter notes per whole note */
#define MIN_VALUE 64 /* the most we can divide a note by */
#define DFLT_VALUE 4 /* default value (quarter-note) */
#define FILLTIME 8 /* for articulation, break note in parts */
#define STACCATO 6 /* 6/8 = 3/4 of note is filled */
#define NORMAL 7 /* 7/8ths of note interval is filled */
#define LEGATO 8 /* all of note interval is filled */
#define DFLT_OCTAVE 4 /* default octave */
#define MIN_TEMPO 32 /* minimum tempo */
#define DFLT_TEMPO 120 /* default tempo */
#define MAX_TEMPO 255 /* max tempo */
#define NUM_MULT 3 /* numerator of dot multiplier */
#define DENOM_MULT 2 /* denominator of dot multiplier */
/* letter to half-tone: A B C D E F G */
static int notetab[8] = {9, 11, 0, 2, 4, 5, 7};
/*
* This is the American Standard A440 Equal-Tempered scale with frequencies
* rounded to nearest integer. Thank Goddess for the good ol' CRC Handbook...
* our octave 0 is standard octave 2.
*/
#define OCTAVE_NOTES 12 /* semitones per octave */
static int pitchtab[] =
{
/* C C# D D# E F F# G G# A A# B*/
/* 0 */ 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123,
/* 1 */ 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
/* 2 */ 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
/* 3 */ 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,
/* 4 */ 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1975,
/* 5 */ 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
/* 6 */ 4186, 4435, 4698, 4978, 5274, 5588, 5920, 6272, 6644, 7040, 7459, 7902,
};
static void playinit()
{
octave = DFLT_OCTAVE;
whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO;
fill = NORMAL;
value = DFLT_VALUE;
octtrack = FALSE;
octprefix = TRUE; /* act as though there was an initial O(n) */
}
static void playtone(pitch, value, sustain)
/* play tone of proper duration for current rhythm signature */
int pitch, value, sustain;
{
register int sound, silence, snum = 1, sdenom = 1;
/* this weirdness avoids floating-point arithmetic */
for (; sustain; sustain--)
{
snum *= NUM_MULT;
sdenom *= DENOM_MULT;
}
if (pitch == -1)
rest(whole * snum / (value * sdenom));
else
{
sound = (whole * snum) / (value * sdenom)
- (whole * (FILLTIME - fill)) / (value * FILLTIME);
silence = whole * (FILLTIME-fill) * snum / (FILLTIME * value * sdenom);
#ifdef DEBUG
printf("playtone: pitch %d for %d ticks, rest for %d ticks\n",
pitch, sound, silence);
#endif /* DEBUG */
tone(pitchtab[pitch], sound);
if (fill != LEGATO)
rest(silence);
}
}
static int abs(n)
int n;
{
if (n < 0)
return(-n);
else
return(n);
}
static void playstring(cp, slen)
/* interpret and play an item from a notation string */
char *cp;
size_t slen;
{
int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE;
#define GETNUM(cp, v) for(v=0; isdigit(cp[1]) && slen > 0; ) \
{v = v * 10 + (*++cp - '0'); slen--;}
for (; slen--; cp++)
{
int sustain, timeval, tempo;
register char c = toupper(*cp);
#ifdef DEBUG
printf("playstring: %c (%x)\n", c, c);
#endif /* DEBUG */
switch (c)
{
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
/* compute pitch */
pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES;
/* this may be followed by an accidental sign */
if (cp[1] == '#' || cp[1] == '+')
{
++pitch;
++cp;
slen--;
}
else if (cp[1] == '-')
{
--pitch;
++cp;
slen--;
}
/*
* If octave-tracking mode is on, and there has been no octave-
* setting prefix, find the version of the current letter note
* closest to the last regardless of octave.
*/
if (octtrack && !octprefix)
{
if (abs(pitch-lastpitch) > abs(pitch+OCTAVE_NOTES-lastpitch))
{
++octave;
pitch += OCTAVE_NOTES;
}
if (abs(pitch-lastpitch) > abs((pitch-OCTAVE_NOTES)-lastpitch))
{
--octave;
pitch -= OCTAVE_NOTES;
}
}
octprefix = FALSE;
lastpitch = pitch;
/* ...which may in turn be followed by an override time value */
GETNUM(cp, timeval);
if (timeval <= 0 || timeval > MIN_VALUE)
timeval = value;
/* ...and/or sustain dots */
for (sustain = 0; cp[1] == '.'; cp++)
{
slen--;
sustain++;
}
/* time to emit the actual tone */
playtone(pitch, timeval, sustain);
break;
case 'O':
if (cp[1] == 'N' || cp[1] == 'n')
{
octprefix = octtrack = FALSE;
++cp;
slen--;
}
else if (cp[1] == 'L' || cp[1] == 'l')
{
octtrack = TRUE;
++cp;
slen--;
}
else
{
GETNUM(cp, octave);
if (octave >= sizeof(pitchtab) / OCTAVE_NOTES)
octave = DFLT_OCTAVE;
octprefix = TRUE;
}
break;
case '>':
if (octave < sizeof(pitchtab) / OCTAVE_NOTES - 1)
octave++;
octprefix = TRUE;
break;
case '<':
if (octave > 0)
octave--;
octprefix = TRUE;
break;
case 'N':
GETNUM(cp, pitch);
for (sustain = 0; cp[1] == '.'; cp++)
{
slen--;
sustain++;
}
playtone(pitch - 1, value, sustain);
break;
case 'L':
GETNUM(cp, value);
if (value <= 0 || value > MIN_VALUE)
value = DFLT_VALUE;
break;
case 'P':
case '~':
/* this may be followed by an override time value */
GETNUM(cp, timeval);
if (timeval <= 0 || timeval > MIN_VALUE)
timeval = value;
for (sustain = 0; cp[1] == '.'; cp++)
{
slen--;
sustain++;
}
playtone(-1, timeval, sustain);
break;
case 'T':
GETNUM(cp, tempo);
if (tempo < MIN_TEMPO || tempo > MAX_TEMPO)
tempo = DFLT_TEMPO;
whole = (hz * SECS_PER_MIN * WHOLE_NOTE) / tempo;
break;
case 'M':
if (cp[1] == 'N' || cp[1] == 'n')
{
fill = NORMAL;
++cp;
slen--;
}
else if (cp[1] == 'L' || cp[1] == 'l')
{
fill = LEGATO;
++cp;
slen--;
}
else if (cp[1] == 'S' || cp[1] == 's')
{
fill = STACCATO;
++cp;
slen--;
}
break;
}
}
}
/******************* UNIX DRIVER HOOKS BEGIN HERE **************************
*
* This section implements driver hooks to run playstring() and the tone(),
* endtone(), and rest() functions defined above.
*/
static int spkr_active; /* exclusion flag */
static struct buf *spkr_inbuf; /* incoming buf */
int spkropen(dev)
dev_t dev;
{
#ifdef DEBUG
printf("spkropen: entering with dev = %x\n", dev);
#endif /* DEBUG */
if (minor(dev) != 0)
return(ENXIO);
else if (spkr_active)
return(EBUSY);
else
{
playinit();
spkr_inbuf = geteblk(DEV_BSIZE);
spkr_active = 1;
}
return(0);
}
int spkrwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
register unsigned n;
char *cp;
int error;
#ifdef DEBUG
printf("spkrwrite: entering with dev = %x, count = %d\n",
dev, uio->uio_resid);
#endif /* DEBUG */
if (minor(dev) != 0)
return(ENXIO);
else
{
n = MIN(DEV_BSIZE, uio->uio_resid);
cp = spkr_inbuf->b_un.b_addr;
error = uiomove(cp, n, uio);
if (!error)
playstring(cp, n);
return(error);
}
}
int spkrclose(dev)
dev_t dev;
{
#ifdef DEBUG
printf("spkrclose: entering with dev = %x\n", dev);
#endif /* DEBUG */
if (minor(dev) != 0)
return(ENXIO);
else
{
endtone();
brelse(spkr_inbuf);
spkr_active = 0;
}
return(0);
}
int spkrioctl(dev, cmd, cmdarg)
dev_t dev;
int cmd;
caddr_t cmdarg;
{
#ifdef DEBUG
printf("spkrioctl: entering with dev = %x, cmd = %x\n", dev, cmd);
#endif /* DEBUG */
if (minor(dev) != 0)
return(ENXIO);
else if (cmd == SPKRTONE)
{
tone_t *tp = (tone_t *)cmdarg;
if (tp->frequency == 0)
rest(tp->duration);
else
tone(tp->frequency, tp->duration);
}
else if (cmd == SPKRTUNE)
{
tone_t *tp = (tone_t *)(*(caddr_t *)cmdarg);
tone_t ttp;
int error;
for (; ; tp++) {
error = copyin(tp, &ttp, sizeof(tone_t));
if (error)
return(error);
if (ttp.duration == 0)
break;
if (ttp.frequency == 0)
rest(ttp.duration);
else
tone(ttp.frequency, ttp.duration);
}
}
else
return(EINVAL);
return(0);
}
#endif /* NSPEAKER > 0 */
/* spkr.c ends here */
+24
View File
@@ -0,0 +1,24 @@
# @(#)Makefile 7.3 (Berkeley) 6/9/91
# Makefile for i386 tags file
all:
@echo "make tags or links only"
TI386= ../i386/tags
SI386= ../i386/i386/*.[ch] ../i386/include/*.h ../i386/isa/*.[ch]
AI386= ../i386/i386/*.s
# Directories in which to place i386 tags links
DI386= eisa isa mca include
tags:
-ctags -dtf ${TI386} ${COMM} ${SI386}
egrep "^ENTRY(.*)|^ALTENTRY(.*)" ${AI386} | \
sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$$/;" \
>> ${TI386}
sort -o ${TI386} ${TI386}
links:
-for i in ${DI386}; do \
cd $$i && rm -f tags; ln -s ../tags tags; done

Some files were not shown because too many files have changed in this diff Show More