Initial import, 0.1 + pk 0.2.4-B1
This commit is contained in:
@@ -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
@@ -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);
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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))
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
g/_mcount/s/_mcount/mcount/g
|
||||||
|
w
|
||||||
|
q
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# @(#)Makefile 5.3 (Berkeley) 5/11/90
|
||||||
|
|
||||||
|
PROG= makekey
|
||||||
|
MAN8= makekey.0
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
||||||
@@ -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.
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# @(#)Makefile 5.4 (Berkeley) 6/5/91
|
||||||
|
|
||||||
|
PROG= comcontrol
|
||||||
|
NOMAN= noman
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# @(#)Makefile 1.1 (Julian Elischer) 3/28/93
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
PROG= fdisk
|
||||||
|
SRCS= fdisk.c
|
||||||
|
MAN8= fdisk.0
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
||||||
@@ -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
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# @(#)Makefile 5.4 (Berkeley) 6/5/91
|
||||||
|
|
||||||
|
PROG= comcontrol
|
||||||
|
NOMAN= noman
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# @(#)Makefile 1.1 (Julian Elischer) 3/28/93
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
PROG= fdisk
|
||||||
|
SRCS= fdisk.c
|
||||||
|
MAN8= fdisk.0
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
||||||
@@ -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
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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];
|
||||||
@@ -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
|
||||||
@@ -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
@@ -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)®s->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");
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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
@@ -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
@@ -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
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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_ */
|
||||||
@@ -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
|
||||||
@@ -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___
|
||||||
@@ -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;
|
||||||
|
};
|
||||||
@@ -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___
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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_
|
||||||
@@ -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 */
|
||||||
@@ -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)
|
||||||
@@ -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
|
||||||
@@ -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 */
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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 */
|
||||||
|
};
|
||||||
@@ -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
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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__
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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 */
|
||||||
@@ -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 */
|
||||||
|
|
||||||
@@ -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:
|
||||||
@@ -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:
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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 */);
|
||||||
@@ -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 */
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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_
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
|
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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();
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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 */
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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_ */
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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_
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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 */
|
||||||
|
|
||||||
|
|
||||||
@@ -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 */
|
||||||
|
|
||||||
@@ -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 */
|
||||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||||
@@ -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 */
|
||||||
@@ -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
Reference in New Issue
Block a user