clang-format

This commit is contained in:
Simon Gardling 2024-09-10 13:03:02 -04:00
parent 53c617d779
commit d66450e427
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D
381 changed files with 28864 additions and 34170 deletions

2
.clang-format Normal file
View File

@ -0,0 +1,2 @@
IncludeBlocks: Preserve
SortIncludes: Never

View File

@ -43,14 +43,12 @@
* is less than either x or y (the choice to compare with x or y is
* arbitrary).
*/
long long
__adddi3(long long a, long long b)
{
union uu aa, bb, sum;
long long __adddi3(long long a, long long b) {
union uu aa, bb, sum;
aa.ll = a;
bb.ll = b;
sum.ui[L] = aa.ui[L] + bb.ui[L];
sum.ui[H] = aa.ui[H] + bb.ui[H] + (sum.ui[L] < bb.ui[L]);
return (sum.ll);
aa.ll = a;
bb.ll = b;
sum.ui[L] = aa.ui[L] + bb.ui[L];
sum.ui[H] = aa.ui[H] + bb.ui[H] + (sum.ui[L] < bb.ui[L]);
return (sum.ll);
}

View File

@ -40,14 +40,12 @@
/*
* Return a & b, in long long.
*/
long long
__anddi3(long long a, long long b)
{
union uu aa, bb;
long long __anddi3(long long a, long long b) {
union uu aa, bb;
aa.ll = a;
bb.ll = b;
aa.ui[0] &= bb.ui[0];
aa.ui[1] &= bb.ui[1];
return (aa.ll);
aa.ll = a;
bb.ll = b;
aa.ui[0] &= bb.ui[0];
aa.ui[1] &= bb.ui[1];
return (aa.ll);
}

View File

@ -41,21 +41,18 @@
* Shift a (signed) long long value left (arithmetic shift left).
* This is the same as logical shift left!
*/
long long
__ashldi3(long long a, unsigned int shift)
{
union uu aa;
long long __ashldi3(long long a, unsigned int shift) {
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[H] = aa.ui[L] << (shift - INT_BITS);
aa.ui[L] = 0;
} else {
aa.ui[H] = (aa.ui[H] << shift) |
(aa.ui[L] >> (INT_BITS - shift));
aa.ui[L] <<= shift;
}
return (aa.ll);
if (shift == 0)
return (a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[H] = aa.ui[L] << (shift - INT_BITS);
aa.ui[L] = 0;
} else {
aa.ui[H] = (aa.ui[H] << shift) | (aa.ui[L] >> (INT_BITS - shift));
aa.ui[L] <<= shift;
}
return (aa.ll);
}

View File

@ -40,34 +40,31 @@
/*
* Shift a (signed) long long value right (arithmetic shift right).
*/
long long
__ashrdi3(long long a, unsigned int shift)
{
union uu aa;
long long __ashrdi3(long long a, unsigned int shift) {
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
int s;
if (shift == 0)
return (a);
aa.ll = a;
if (shift >= INT_BITS) {
int s;
/*
* Smear bits rightward using the machine's right-shift
* method, whether that is sign extension or zero fill,
* to get the `sign word' s. Note that shifting by
* INT_BITS is undefined, so we shift (INT_BITS-1),
* then 1 more, to get our answer.
*/
/* LINTED inherits machine dependency */
s = (aa.si[H] >> (INT_BITS - 1)) >> 1;
/* LINTED inherits machine dependency*/
aa.ui[L] = aa.si[H] >> (shift - INT_BITS);
aa.ui[H] = s;
} else {
aa.ui[L] = (aa.ui[L] >> shift) |
(aa.ui[H] << (INT_BITS - shift));
/* LINTED inherits machine dependency */
aa.si[H] >>= shift;
}
return (aa.ll);
/*
* Smear bits rightward using the machine's right-shift
* method, whether that is sign extension or zero fill,
* to get the `sign word' s. Note that shifting by
* INT_BITS is undefined, so we shift (INT_BITS-1),
* then 1 more, to get our answer.
*/
/* LINTED inherits machine dependency */
s = (aa.si[H] >> (INT_BITS - 1)) >> 1;
/* LINTED inherits machine dependency*/
aa.ui[L] = aa.si[H] >> (shift - INT_BITS);
aa.ui[H] = s;
} else {
aa.ui[L] = (aa.ui[L] >> shift) | (aa.ui[H] << (INT_BITS - shift));
/* LINTED inherits machine dependency */
aa.si[H] >>= shift;
}
return (aa.ll);
}

View File

@ -42,13 +42,14 @@
* Both a and b are considered signed---which means only the high word is
* signed.
*/
int
__cmpdi2(long long a, long long b)
{
union uu aa, bb;
int __cmpdi2(long long a, long long b) {
union uu aa, bb;
aa.ll = a;
bb.ll = b;
return (aa.si[H] < bb.si[H] ? 0 : aa.si[H] > bb.si[H] ? 2 :
aa.ui[L] < bb.ui[L] ? 0 : aa.ui[L] > bb.ui[L] ? 2 : 1);
aa.ll = a;
bb.ll = b;
return (aa.si[H] < bb.si[H] ? 0
: aa.si[H] > bb.si[H] ? 2
: aa.ui[L] < bb.ui[L] ? 0
: aa.ui[L] > bb.ui[L] ? 2
: 1);
}

View File

@ -41,22 +41,20 @@
* Divide two signed long longs.
* ??? if -1/2 should produce -1 on this machine, this code is wrong
*/
long long
__divdi3(long long a, long long b)
{
unsigned long long ua, ub, uq;
int neg = 0;
long long __divdi3(long long a, long long b) {
unsigned long long ua, ub, uq;
int neg = 0;
ua = a;
ub = b;
ua = a;
ub = b;
if (a < 0)
ua = -ua, neg ^= 1;
if (b < 0)
ub = -ub, neg ^= 1;
if (a < 0)
ua = -ua, neg ^= 1;
if (b < 0)
ub = -ub, neg ^= 1;
uq = __qdivrem(ua, ub, NULL);
if (neg)
uq = - uq;
return uq;
uq = __qdivrem(ua, ub, NULL);
if (neg)
uq = -uq;
return uq;
}

View File

@ -40,14 +40,12 @@
/*
* Return a | b, in long long.
*/
long long
__iordi3(long long a, long long b)
{
union uu aa, bb;
long long __iordi3(long long a, long long b) {
union uu aa, bb;
aa.ll = a;
bb.ll = b;
aa.ui[0] |= bb.ui[0];
aa.ui[1] |= bb.ui[1];
return (aa.ll);
aa.ll = a;
bb.ll = b;
aa.ui[0] |= bb.ui[0];
aa.ui[1] |= bb.ui[1];
return (aa.ll);
}

View File

@ -68,10 +68,10 @@
* one or more of the following formats.
*/
union uu {
long long ll; /* as a (signed) long long */
unsigned long long ull; /* as an unsigned long long */
int si[2]; /* as two (signed) ints */
unsigned int ui[2]; /* as two unsigned ints */
long long ll; /* as a (signed) long long */
unsigned long long ull; /* as an unsigned long long */
int si[2]; /* as two (signed) ints */
unsigned int ui[2]; /* as two unsigned ints */
};
/*
@ -87,15 +87,14 @@ union uu {
#define L 1
#endif
/*
* Total number of bits in a long long and in the pieces that make it up.
* These are used for shifting, and also below for halfword extraction
* and assembly.
*/
#define LONGLONG_BITS (sizeof(long long) * CHAR_BIT)
#define INT_BITS (sizeof(int) * CHAR_BIT)
#define HALF_BITS (sizeof(int) * CHAR_BIT / 2)
#define LONGLONG_BITS (sizeof(long long) * CHAR_BIT)
#define INT_BITS (sizeof(int) * CHAR_BIT)
#define HALF_BITS (sizeof(int) * CHAR_BIT / 2)
/*
* Extract high and low shortwords from longword, and move low shortword of
@ -107,38 +106,38 @@ union uu {
* and lower halves, and to reassemble a product as a long long, shifted
* left (sizeof(int)*CHAR_BIT/2).
*/
#define HHALF(x) ((unsigned int)(x) >> HALF_BITS)
#define LHALF(x) ((unsigned int)(x) & (((int)1 << HALF_BITS) - 1))
#define LHUP(x) ((unsigned int)(x) << HALF_BITS)
#define HHALF(x) ((unsigned int)(x) >> HALF_BITS)
#define LHALF(x) ((unsigned int)(x) & (((int)1 << HALF_BITS) - 1))
#define LHUP(x) ((unsigned int)(x) << HALF_BITS)
long long __adddi3 ( long long, long long);
long long __anddi3 ( long long, long long);
long long __ashldi3 ( long long, unsigned int);
long long __ashrdi3 ( long long, unsigned int);
int __cmpdi2 ( long long, long long);
long long __divdi3 ( long long, long long);
long long __iordi3 ( long long, long long);
long long __lshldi3 ( long long, unsigned int);
long long __lshrdi3 ( long long, unsigned int);
long long __moddi3 ( long long, long long);
long long __muldi3 ( long long, long long);
long long __negdi2 ( long long);
long long __one_cmpldi2 ( long long);
long long __subdi3 ( long long, long long);
int __ucmpdi2 (unsigned long long, unsigned long long);
unsigned long long __udivdi3 (unsigned long long, unsigned long long);
unsigned long long __umoddi3 (unsigned long long, unsigned long long);
long long __xordi3 ( long long, long long);
long long __adddi3(long long, long long);
long long __anddi3(long long, long long);
long long __ashldi3(long long, unsigned int);
long long __ashrdi3(long long, unsigned int);
int __cmpdi2(long long, long long);
long long __divdi3(long long, long long);
long long __iordi3(long long, long long);
long long __lshldi3(long long, unsigned int);
long long __lshrdi3(long long, unsigned int);
long long __moddi3(long long, long long);
long long __muldi3(long long, long long);
long long __negdi2(long long);
long long __one_cmpldi2(long long);
long long __subdi3(long long, long long);
int __ucmpdi2(unsigned long long, unsigned long long);
unsigned long long __udivdi3(unsigned long long, unsigned long long);
unsigned long long __umoddi3(unsigned long long, unsigned long long);
long long __xordi3(long long, long long);
#ifndef _KERNEL
long long __fixdfdi (double);
long long __fixsfdi (float);
unsigned long long __fixunsdfdi (double);
unsigned long long __fixunssfdi (float);
double __floatdidf (long long);
float __floatdisf (long long);
double __floatunsdidf(unsigned long long);
long long __fixdfdi(double);
long long __fixsfdi(float);
unsigned long long __fixunsdfdi(double);
unsigned long long __fixunssfdi(float);
double __floatdidf(long long);
float __floatdisf(long long);
double __floatunsdidf(unsigned long long);
#endif
unsigned long long __qdivrem (unsigned long long, unsigned long long,
unsigned long long *);
unsigned long long __qdivrem(unsigned long long, unsigned long long,
unsigned long long *);

View File

@ -41,21 +41,18 @@
* Shift an (unsigned) long long value left (logical shift left).
* This is the same as arithmetic shift left!
*/
long long
__lshldi3(long long a, unsigned int shift)
{
union uu aa;
long long __lshldi3(long long a, unsigned int shift) {
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[H] = aa.ui[L] << (shift - INT_BITS);
aa.ui[L] = 0;
} else {
aa.ui[H] = (aa.ui[H] << shift) |
(aa.ui[L] >> (INT_BITS - shift));
aa.ui[L] <<= shift;
}
return (aa.ll);
if (shift == 0)
return (a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[H] = aa.ui[L] << (shift - INT_BITS);
aa.ui[L] = 0;
} else {
aa.ui[H] = (aa.ui[H] << shift) | (aa.ui[L] >> (INT_BITS - shift));
aa.ui[L] <<= shift;
}
return (aa.ll);
}

View File

@ -40,21 +40,18 @@
/*
* Shift an (unsigned) long long value right (logical shift right).
*/
long long
__lshrdi3(long long a, unsigned int shift)
{
union uu aa;
long long __lshrdi3(long long a, unsigned int shift) {
union uu aa;
if (shift == 0)
return(a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[L] = aa.ui[H] >> (shift - INT_BITS);
aa.ui[H] = 0;
} else {
aa.ui[L] = (aa.ui[L] >> shift) |
(aa.ui[H] << (INT_BITS - shift));
aa.ui[H] >>= shift;
}
return (aa.ll);
if (shift == 0)
return (a);
aa.ll = a;
if (shift >= INT_BITS) {
aa.ui[L] = aa.ui[H] >> (shift - INT_BITS);
aa.ui[H] = 0;
} else {
aa.ui[L] = (aa.ui[L] >> shift) | (aa.ui[H] << (INT_BITS - shift));
aa.ui[H] >>= shift;
}
return (aa.ll);
}

View File

@ -42,21 +42,19 @@
*
* XXX we assume a % b < 0 iff a < 0, but this is actually machine-dependent.
*/
long long
__moddi3(long long a, long long b)
{
unsigned long long ua, ub, ur;
int neg = 0;
long long __moddi3(long long a, long long b) {
unsigned long long ua, ub, ur;
int neg = 0;
ua = a;
ub = b;
ua = a;
ub = b;
if (a < 0)
ua = -ua, neg ^= 1;
if (b < 0)
ub = -ub;
(void)__qdivrem(ua, ub, &ur);
if (neg)
ur = -ur;
return (ur);
if (a < 0)
ua = -ua, neg ^= 1;
if (b < 0)
ub = -ub;
(void)__qdivrem(ua, ub, &ur);
if (neg)
ur = -ur;
return (ur);
}

View File

@ -96,67 +96,64 @@
*/
static long long __lmulq(unsigned int, unsigned int);
long long
__muldi3(long long a, long long b)
{
union uu u, v, low, prod;
unsigned int high, mid, udiff, vdiff;
int negall, negmid;
#define u1 u.ui[H]
#define u0 u.ui[L]
#define v1 v.ui[H]
#define v0 v.ui[L]
long long __muldi3(long long a, long long b) {
union uu u, v, low, prod;
unsigned int high, mid, udiff, vdiff;
int negall, negmid;
#define u1 u.ui[H]
#define u0 u.ui[L]
#define v1 v.ui[H]
#define v0 v.ui[L]
/*
* Get u and v such that u, v >= 0. When this is finished,
* u1, u0, v1, and v0 will be directly accessible through the
* int fields.
*/
if (a >= 0)
u.ll = a, negall = 0;
else
u.ll = -a, negall = 1;
if (b >= 0)
v.ll = b;
else
v.ll = -b, negall ^= 1;
/*
* Get u and v such that u, v >= 0. When this is finished,
* u1, u0, v1, and v0 will be directly accessible through the
* int fields.
*/
if (a >= 0)
u.ll = a, negall = 0;
else
u.ll = -a, negall = 1;
if (b >= 0)
v.ll = b;
else
v.ll = -b, negall ^= 1;
if (u1 == 0 && v1 == 0) {
/*
* An (I hope) important optimization occurs when u1 and v1
* are both 0. This should be common since most numbers
* are small. Here the product is just u0*v0.
*/
prod.ll = __lmulq(u0, v0);
} else {
/*
* Compute the three intermediate products, remembering
* whether the middle term is negative. We can discard
* any upper bits in high and mid, so we can use native
* unsigned int * unsigned int => unsigned int arithmetic.
*/
low.ll = __lmulq(u0, v0);
if (u1 == 0 && v1 == 0) {
/*
* An (I hope) important optimization occurs when u1 and v1
* are both 0. This should be common since most numbers
* are small. Here the product is just u0*v0.
*/
prod.ll = __lmulq(u0, v0);
} else {
/*
* Compute the three intermediate products, remembering
* whether the middle term is negative. We can discard
* any upper bits in high and mid, so we can use native
* unsigned int * unsigned int => unsigned int arithmetic.
*/
low.ll = __lmulq(u0, v0);
if (u1 >= u0)
negmid = 0, udiff = u1 - u0;
else
negmid = 1, udiff = u0 - u1;
if (v0 >= v1)
vdiff = v0 - v1;
else
vdiff = v1 - v0, negmid ^= 1;
mid = udiff * vdiff;
if (u1 >= u0)
negmid = 0, udiff = u1 - u0;
else
negmid = 1, udiff = u0 - u1;
if (v0 >= v1)
vdiff = v0 - v1;
else
vdiff = v1 - v0, negmid ^= 1;
mid = udiff * vdiff;
high = u1 * v1;
high = u1 * v1;
/*
* Assemble the final product.
*/
prod.ui[H] = high + (negmid ? -mid : mid) + low.ui[L] +
low.ui[H];
prod.ui[L] = low.ui[L];
}
return (negall ? -prod.ll : prod.ll);
/*
* Assemble the final product.
*/
prod.ui[H] = high + (negmid ? -mid : mid) + low.ui[L] + low.ui[H];
prod.ui[L] = low.ui[L];
}
return (negall ? -prod.ll : prod.ll);
#undef u1
#undef u0
#undef v1
@ -180,62 +177,60 @@ __muldi3(long long a, long long b)
*
* splits into high and low ints as HHALF(l) and LHUP(l) respectively.
*/
static long long
__lmulq(unsigned int u, unsigned int v)
{
unsigned int u1, u0, v1, v0, udiff, vdiff, high, mid, low;
unsigned int prodh, prodl, was;
union uu prod;
int neg;
static long long __lmulq(unsigned int u, unsigned int v) {
unsigned int u1, u0, v1, v0, udiff, vdiff, high, mid, low;
unsigned int prodh, prodl, was;
union uu prod;
int neg;
u1 = HHALF(u);
u0 = LHALF(u);
v1 = HHALF(v);
v0 = LHALF(v);
u1 = HHALF(u);
u0 = LHALF(u);
v1 = HHALF(v);
v0 = LHALF(v);
low = u0 * v0;
low = u0 * v0;
/* This is the same small-number optimization as before. */
if (u1 == 0 && v1 == 0)
return (low);
/* This is the same small-number optimization as before. */
if (u1 == 0 && v1 == 0)
return (low);
if (u1 >= u0)
udiff = u1 - u0, neg = 0;
else
udiff = u0 - u1, neg = 1;
if (v0 >= v1)
vdiff = v0 - v1;
else
vdiff = v1 - v0, neg ^= 1;
mid = udiff * vdiff;
if (u1 >= u0)
udiff = u1 - u0, neg = 0;
else
udiff = u0 - u1, neg = 1;
if (v0 >= v1)
vdiff = v0 - v1;
else
vdiff = v1 - v0, neg ^= 1;
mid = udiff * vdiff;
high = u1 * v1;
high = u1 * v1;
/* prod = (high << 2N) + (high << N); */
prodh = high + HHALF(high);
prodl = LHUP(high);
/* prod = (high << 2N) + (high << N); */
prodh = high + HHALF(high);
prodl = LHUP(high);
/* if (neg) prod -= mid << N; else prod += mid << N; */
if (neg) {
was = prodl;
prodl -= LHUP(mid);
prodh -= HHALF(mid) + (prodl > was);
} else {
was = prodl;
prodl += LHUP(mid);
prodh += HHALF(mid) + (prodl < was);
}
/* if (neg) prod -= mid << N; else prod += mid << N; */
if (neg) {
was = prodl;
prodl -= LHUP(mid);
prodh -= HHALF(mid) + (prodl > was);
} else {
was = prodl;
prodl += LHUP(mid);
prodh += HHALF(mid) + (prodl < was);
}
/* prod += low << N */
was = prodl;
prodl += LHUP(low);
prodh += HHALF(low) + (prodl < was);
/* ... + low; */
if ((prodl += low) < low)
prodh++;
/* prod += low << N */
was = prodl;
prodl += LHUP(low);
prodh += HHALF(low) + (prodl < was);
/* ... + low; */
if ((prodl += low) < low)
prodh++;
/* return 4N-bit product */
prod.ui[H] = prodh;
prod.ui[L] = prodl;
return (prod.ll);
/* return 4N-bit product */
prod.ui[H] = prodh;
prod.ui[L] = prodl;
return (prod.ll);
}

View File

@ -40,13 +40,11 @@
/*
* Return -a (or, equivalently, 0 - a), in long long. See subdi3.c.
*/
long long
__negdi2(long long a)
{
union uu aa, res;
long long __negdi2(long long a) {
union uu aa, res;
aa.ll = a;
res.ui[L] = -aa.ui[L];
res.ui[H] = -aa.ui[H] - (res.ui[L] > 0);
return (res.ll);
aa.ll = a;
res.ui[L] = -aa.ui[L];
res.ui[H] = -aa.ui[H] - (res.ui[L] > 0);
return (res.ll);
}

View File

@ -41,13 +41,11 @@
* Return ~a. For some reason gcc calls this `one's complement' rather
* than `not'.
*/
long long
__one_cmpldi2(long long a)
{
union uu aa;
long long __one_cmpldi2(long long a) {
union uu aa;
aa.ll = a;
aa.ui[0] = ~aa.ui[0];
aa.ui[1] = ~aa.ui[1];
return (aa.ll);
aa.ll = a;
aa.ui[0] = ~aa.ui[0];
aa.ui[1] = ~aa.ui[1];
return (aa.ll);
}

View File

@ -42,10 +42,10 @@
#include "longlong.h"
#define B ((int)1 << HALF_BITS) /* digit base */
#define B ((int)1 << HALF_BITS) /* digit base */
/* Combine two `digits' to make a single two-digit number. */
#define COMBINE(a, b) (((unsigned int)(a) << HALF_BITS) | (b))
#define COMBINE(a, b) (((unsigned int)(a) << HALF_BITS) | (b))
/* select a type for digits in base B: use unsigned short if they fit */
#if UINT_MAX == 0xffffffffU && USHRT_MAX >= 0xffff
@ -64,202 +64,199 @@ static void shl(digit *p, int len, int sh);
* length dividend and divisor are 4 `digits' in this base (they are
* shorter if they have leading zeros).
*/
unsigned long long
__qdivrem(unsigned long long ull, unsigned long long vll,
unsigned long long *arq)
{
union uu tmp;
digit *u, *v, *q;
digit v1, v2;
unsigned int qhat, rhat, t;
int m, n, d, j, i;
digit uspace[5], vspace[5], qspace[5];
unsigned long long __qdivrem(unsigned long long ull, unsigned long long vll,
unsigned long long *arq) {
union uu tmp;
digit *u, *v, *q;
digit v1, v2;
unsigned int qhat, rhat, t;
int m, n, d, j, i;
digit uspace[5], vspace[5], qspace[5];
/*
* Take care of special cases: divide by zero, and u < v.
*/
if (vll == 0) {
/* divide by zero. */
static volatile const unsigned int zero = 0;
/*
* Take care of special cases: divide by zero, and u < v.
*/
if (vll == 0) {
/* divide by zero. */
static volatile const unsigned int zero = 0;
tmp.ui[H] = tmp.ui[L] = 1 / zero;
if (arq)
*arq = ull;
return (tmp.ll);
}
if (ull < vll) {
if (arq)
*arq = ull;
return (0);
}
u = &uspace[0];
v = &vspace[0];
q = &qspace[0];
tmp.ui[H] = tmp.ui[L] = 1 / zero;
if (arq)
*arq = ull;
return (tmp.ll);
}
if (ull < vll) {
if (arq)
*arq = ull;
return (0);
}
u = &uspace[0];
v = &vspace[0];
q = &qspace[0];
/*
* Break dividend and divisor into digits in base B, then
* count leading zeros to determine m and n. When done, we
* will have:
* u = (u[1]u[2]...u[m+n]) sub B
* v = (v[1]v[2]...v[n]) sub B
* v[1] != 0
* 1 < n <= 4 (if n = 1, we use a different division algorithm)
* m >= 0 (otherwise u < v, which we already checked)
* m + n = 4
* and thus
* m = 4 - n <= 2
*/
tmp.ull = ull;
u[0] = 0;
u[1] = (digit)HHALF(tmp.ui[H]);
u[2] = (digit)LHALF(tmp.ui[H]);
u[3] = (digit)HHALF(tmp.ui[L]);
u[4] = (digit)LHALF(tmp.ui[L]);
tmp.ull = vll;
v[1] = (digit)HHALF(tmp.ui[H]);
v[2] = (digit)LHALF(tmp.ui[H]);
v[3] = (digit)HHALF(tmp.ui[L]);
v[4] = (digit)LHALF(tmp.ui[L]);
for (n = 4; v[1] == 0; v++) {
if (--n == 1) {
unsigned int rbj; /* r*B+u[j] (not root boy jim) */
digit q1, q2, q3, q4;
/*
* Break dividend and divisor into digits in base B, then
* count leading zeros to determine m and n. When done, we
* will have:
* u = (u[1]u[2]...u[m+n]) sub B
* v = (v[1]v[2]...v[n]) sub B
* v[1] != 0
* 1 < n <= 4 (if n = 1, we use a different division algorithm)
* m >= 0 (otherwise u < v, which we already checked)
* m + n = 4
* and thus
* m = 4 - n <= 2
*/
tmp.ull = ull;
u[0] = 0;
u[1] = (digit)HHALF(tmp.ui[H]);
u[2] = (digit)LHALF(tmp.ui[H]);
u[3] = (digit)HHALF(tmp.ui[L]);
u[4] = (digit)LHALF(tmp.ui[L]);
tmp.ull = vll;
v[1] = (digit)HHALF(tmp.ui[H]);
v[2] = (digit)LHALF(tmp.ui[H]);
v[3] = (digit)HHALF(tmp.ui[L]);
v[4] = (digit)LHALF(tmp.ui[L]);
for (n = 4; v[1] == 0; v++) {
if (--n == 1) {
unsigned int rbj; /* r*B+u[j] (not root boy jim) */
digit q1, q2, q3, q4;
/*
* Change of plan, per exercise 16.
* r = 0;
* for j = 1..4:
* q[j] = floor((r*B + u[j]) / v),
* r = (r*B + u[j]) % v;
* We unroll this completely here.
*/
t = v[2]; /* nonzero, by definition */
q1 = (digit)(u[1] / t);
rbj = COMBINE(u[1] % t, u[2]);
q2 = (digit)(rbj / t);
rbj = COMBINE(rbj % t, u[3]);
q3 = (digit)(rbj / t);
rbj = COMBINE(rbj % t, u[4]);
q4 = (digit)(rbj / t);
if (arq)
*arq = rbj % t;
tmp.ui[H] = COMBINE(q1, q2);
tmp.ui[L] = COMBINE(q3, q4);
return (tmp.ll);
}
}
/*
* Change of plan, per exercise 16.
* r = 0;
* for j = 1..4:
* q[j] = floor((r*B + u[j]) / v),
* r = (r*B + u[j]) % v;
* We unroll this completely here.
*/
t = v[2]; /* nonzero, by definition */
q1 = (digit)(u[1] / t);
rbj = COMBINE(u[1] % t, u[2]);
q2 = (digit)(rbj / t);
rbj = COMBINE(rbj % t, u[3]);
q3 = (digit)(rbj / t);
rbj = COMBINE(rbj % t, u[4]);
q4 = (digit)(rbj / t);
if (arq)
*arq = rbj % t;
tmp.ui[H] = COMBINE(q1, q2);
tmp.ui[L] = COMBINE(q3, q4);
return (tmp.ll);
}
}
/*
* By adjusting q once we determine m, we can guarantee that
* there is a complete four-digit quotient at &qspace[1] when
* we finally stop.
*/
for (m = 4 - n; u[1] == 0; u++)
m--;
for (i = 4 - m; --i >= 0;)
q[i] = 0;
q += 4 - m;
/*
* By adjusting q once we determine m, we can guarantee that
* there is a complete four-digit quotient at &qspace[1] when
* we finally stop.
*/
for (m = 4 - n; u[1] == 0; u++)
m--;
for (i = 4 - m; --i >= 0;)
q[i] = 0;
q += 4 - m;
/*
* Here we run Program D, translated from MIX to C and acquiring
* a few minor changes.
*
* D1: choose multiplier 1 << d to ensure v[1] >= B/2.
*/
d = 0;
for (t = v[1]; t < B / 2; t <<= 1)
d++;
if (d > 0) {
shl(&u[0], m + n, d); /* u <<= d */
shl(&v[1], n - 1, d); /* v <<= d */
}
/*
* D2: j = 0.
*/
j = 0;
v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
v2 = v[2]; /* for D3 */
do {
digit uj0, uj1, uj2;
/*
* Here we run Program D, translated from MIX to C and acquiring
* a few minor changes.
*
* D1: choose multiplier 1 << d to ensure v[1] >= B/2.
*/
d = 0;
for (t = v[1]; t < B / 2; t <<= 1)
d++;
if (d > 0) {
shl(&u[0], m + n, d); /* u <<= d */
shl(&v[1], n - 1, d); /* v <<= d */
}
/*
* D2: j = 0.
*/
j = 0;
v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
v2 = v[2]; /* for D3 */
do {
digit uj0, uj1, uj2;
/*
* D3: Calculate qhat (\^q, in TeX notation).
* Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
* let rhat = (u[j]*B + u[j+1]) mod v[1].
* While rhat < B and v[2]*qhat > rhat*B+u[j+2],
* decrement qhat and increase rhat correspondingly.
* Note that if rhat >= B, v[2]*qhat < rhat*B.
*/
uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
uj1 = u[j + 1]; /* for D3 only */
uj2 = u[j + 2]; /* for D3 only */
if (uj0 == v1) {
qhat = B;
rhat = uj1;
goto qhat_too_big;
} else {
unsigned int nn = COMBINE(uj0, uj1);
qhat = nn / v1;
rhat = nn % v1;
}
while (v2 * qhat > COMBINE(rhat, uj2)) {
qhat_too_big:
qhat--;
if ((rhat += v1) >= B)
break;
}
/*
* D4: Multiply and subtract.
* The variable `t' holds any borrows across the loop.
* We split this up so that we do not require v[0] = 0,
* and to eliminate a final special case.
*/
for (t = 0, i = n; i > 0; i--) {
t = u[i + j] - v[i] * qhat - t;
u[i + j] = (digit)LHALF(t);
t = (B - HHALF(t)) & (B - 1);
}
t = u[j] - t;
u[j] = (digit)LHALF(t);
/*
* D5: test remainder.
* There is a borrow if and only if HHALF(t) is nonzero;
* in that (rare) case, qhat was too large (by exactly 1).
* Fix it by adding v[1..n] to u[j..j+n].
*/
if (HHALF(t)) {
qhat--;
for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
t += u[i + j] + v[i];
u[i + j] = (digit)LHALF(t);
t = HHALF(t);
}
u[j] = (digit)LHALF(u[j] + t);
}
q[j] = (digit)qhat;
} while (++j <= m); /* D7: loop on j. */
/*
* D3: Calculate qhat (\^q, in TeX notation).
* Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
* let rhat = (u[j]*B + u[j+1]) mod v[1].
* While rhat < B and v[2]*qhat > rhat*B+u[j+2],
* decrement qhat and increase rhat correspondingly.
* Note that if rhat >= B, v[2]*qhat < rhat*B.
*/
uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
uj1 = u[j + 1]; /* for D3 only */
uj2 = u[j + 2]; /* for D3 only */
if (uj0 == v1) {
qhat = B;
rhat = uj1;
goto qhat_too_big;
} else {
unsigned int nn = COMBINE(uj0, uj1);
qhat = nn / v1;
rhat = nn % v1;
}
while (v2 * qhat > COMBINE(rhat, uj2)) {
qhat_too_big:
qhat--;
if ((rhat += v1) >= B)
break;
}
/*
* D4: Multiply and subtract.
* The variable `t' holds any borrows across the loop.
* We split this up so that we do not require v[0] = 0,
* and to eliminate a final special case.
*/
for (t = 0, i = n; i > 0; i--) {
t = u[i + j] - v[i] * qhat - t;
u[i + j] = (digit)LHALF(t);
t = (B - HHALF(t)) & (B - 1);
}
t = u[j] - t;
u[j] = (digit)LHALF(t);
/*
* D5: test remainder.
* There is a borrow if and only if HHALF(t) is nonzero;
* in that (rare) case, qhat was too large (by exactly 1).
* Fix it by adding v[1..n] to u[j..j+n].
*/
if (HHALF(t)) {
qhat--;
for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
t += u[i + j] + v[i];
u[i + j] = (digit)LHALF(t);
t = HHALF(t);
}
u[j] = (digit)LHALF(u[j] + t);
}
q[j] = (digit)qhat;
} while (++j <= m); /* D7: loop on j. */
/*
* If caller wants the remainder, we have to calculate it as
* u[m..m+n] >> d (this is at most n digits and thus fits in
* u[m+1..m+n], but we may need more source digits).
*/
if (arq) {
if (d) {
for (i = m + n; i > m; --i)
u[i] = (digit)(((unsigned int)u[i] >> d) |
LHALF((unsigned int)u[i - 1] <<
(HALF_BITS - d)));
u[i] = 0;
}
tmp.ui[H] = COMBINE(uspace[1], uspace[2]);
tmp.ui[L] = COMBINE(uspace[3], uspace[4]);
*arq = tmp.ll;
}
/*
* If caller wants the remainder, we have to calculate it as
* u[m..m+n] >> d (this is at most n digits and thus fits in
* u[m+1..m+n], but we may need more source digits).
*/
if (arq) {
if (d) {
for (i = m + n; i > m; --i)
u[i] = (digit)(((unsigned int)u[i] >> d) |
LHALF((unsigned int)u[i - 1] << (HALF_BITS - d)));
u[i] = 0;
}
tmp.ui[H] = COMBINE(uspace[1], uspace[2]);
tmp.ui[L] = COMBINE(uspace[3], uspace[4]);
*arq = tmp.ll;
}
tmp.ui[H] = COMBINE(qspace[1], qspace[2]);
tmp.ui[L] = COMBINE(qspace[3], qspace[4]);
return (tmp.ll);
tmp.ui[H] = COMBINE(qspace[1], qspace[2]);
tmp.ui[L] = COMBINE(qspace[3], qspace[4]);
return (tmp.ll);
}
/*
@ -267,13 +264,11 @@ __qdivrem(unsigned long long ull, unsigned long long vll,
* `fall out' the left (there never will be any such anyway).
* We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
*/
static void
shl(digit *p, int len, int sh)
{
int i;
static void shl(digit *p, int len, int sh) {
int i;
for (i = 0; i < len; i++)
p[i] = (digit)(LHALF((unsigned int)p[i] << sh) |
((unsigned int)p[i + 1] >> (HALF_BITS - sh)));
p[i] = (digit)(LHALF((unsigned int)p[i] << sh));
for (i = 0; i < len; i++)
p[i] = (digit)(LHALF((unsigned int)p[i] << sh) |
((unsigned int)p[i + 1] >> (HALF_BITS - sh)));
p[i] = (digit)(LHALF((unsigned int)p[i] << sh));
}

View File

@ -42,14 +42,12 @@
* carry from a single unsigned int difference x-y occurs if and only
* if (x-y) > x.
*/
long long
__subdi3(long long a, long long b)
{
union uu aa, bb, diff;
long long __subdi3(long long a, long long b) {
union uu aa, bb, diff;
aa.ll = a;
bb.ll = b;
diff.ui[L] = aa.ui[L] - bb.ui[L];
diff.ui[H] = aa.ui[H] - bb.ui[H] - (diff.ui[L] > aa.ui[L]);
return (diff.ll);
aa.ll = a;
bb.ll = b;
diff.ui[L] = aa.ui[L] - bb.ui[L];
diff.ui[H] = aa.ui[H] - bb.ui[H] - (diff.ui[L] > aa.ui[L]);
return (diff.ll);
}

View File

@ -41,13 +41,14 @@
* Return 0, 1, or 2 as a <, =, > b respectively.
* Neither a nor b are considered signed.
*/
int
__ucmpdi2(unsigned long long a, unsigned long long b)
{
union uu aa, bb;
int __ucmpdi2(unsigned long long a, unsigned long long b) {
union uu aa, bb;
aa.ull = a;
bb.ull = b;
return (aa.ui[H] < bb.ui[H] ? 0 : aa.ui[H] > bb.ui[H] ? 2 :
aa.ui[L] < bb.ui[L] ? 0 : aa.ui[L] > bb.ui[L] ? 2 : 1);
aa.ull = a;
bb.ull = b;
return (aa.ui[H] < bb.ui[H] ? 0
: aa.ui[H] > bb.ui[H] ? 2
: aa.ui[L] < bb.ui[L] ? 0
: aa.ui[L] > bb.ui[L] ? 2
: 1);
}

View File

@ -40,9 +40,7 @@
/*
* Divide two unsigned long longs.
*/
unsigned long long
__udivdi3(unsigned long long a, unsigned long long b)
{
unsigned long long __udivdi3(unsigned long long a, unsigned long long b) {
return __qdivrem(a, b, NULL);
return __qdivrem(a, b, NULL);
}

View File

@ -40,11 +40,9 @@
/*
* Return remainder after dividing two unsigned long longs.
*/
unsigned long long
__umoddi3(unsigned long long a, unsigned long long b)
{
unsigned long long r;
unsigned long long __umoddi3(unsigned long long a, unsigned long long b) {
unsigned long long r;
(void)__qdivrem(a, b, &r);
return (r);
(void)__qdivrem(a, b, &r);
return (r);
}

View File

@ -40,14 +40,12 @@
/*
* Return a ^ b, in long long.
*/
long long
__xordi3(long long a, long long b)
{
union uu aa, bb;
long long __xordi3(long long a, long long b) {
union uu aa, bb;
aa.ll = a;
bb.ll = b;
aa.ui[0] ^= bb.ui[0];
aa.ui[1] ^= bb.ui[1];
return (aa.ll);
aa.ll = a;
bb.ll = b;
aa.ui[0] ^= bb.ui[0];
aa.ui[1] ^= bb.ui[1];
return (aa.ll);
}

View File

@ -52,7 +52,6 @@
#include <stdarg.h>
/*
* Do we want to support "long long" types with %lld?
*
@ -67,12 +66,11 @@
* Define a type that holds the longest signed integer we intend to support.
*/
#ifdef USE_LONGLONG
#define INTTYPE long long
#define INTTYPE long long
#else
#define INTTYPE long
#define INTTYPE long
#endif
/*
* Space for a long long in base 8, plus a NUL, plus one
* character extra for slop.
@ -87,52 +85,52 @@
* Structure holding the state for printf.
*/
typedef struct {
/* Callback for sending printed string data */
void (*sendfunc)(void *clientdata, const char *str, size_t len);
void *clientdata;
/* Callback for sending printed string data */
void (*sendfunc)(void *clientdata, const char *str, size_t len);
void *clientdata;
/* The varargs argument pointer */
va_list ap;
/* The varargs argument pointer */
va_list ap;
/* Total count of characters printed */
int charcount;
/* Total count of characters printed */
int charcount;
/* Flag that's true if we are currently looking in a %-format */
int in_pct;
/* Flag that's true if we are currently looking in a %-format */
int in_pct;
/* Size of the integer argument to retrieve */
enum {
INTSZ,
LONGSZ,
/* Size of the integer argument to retrieve */
enum {
INTSZ,
LONGSZ,
#ifdef USE_LONGLONG
LLONGSZ,
LLONGSZ,
#endif
SIZETSZ,
} size;
SIZETSZ,
} size;
/* The value of the integer argument retrieved */
unsigned INTTYPE num;
/* The value of the integer argument retrieved */
unsigned INTTYPE num;
/* Sign of the integer argument (0 = positive; -1 = negative) */
int sign;
/* Sign of the integer argument (0 = positive; -1 = negative) */
int sign;
/* Field width (number of spaces) */
int spacing;
/* Field width (number of spaces) */
int spacing;
/* Flag: align to left in field instead of right */
int rightspc;
/* Flag: align to left in field instead of right */
int rightspc;
/* Character to pad to field size with (space or 0) */
int fillchar;
/* Character to pad to field size with (space or 0) */
int fillchar;
/* Number base to print the integer argument in (8, 10, 16) */
int base;
/* Number base to print the integer argument in (8, 10, 16) */
int base;
/* Flag: if set, print 0x before hex and 0 before octal numbers */
int baseprefix;
/* Flag: if set, print 0x before hex and 0 before octal numbers */
int baseprefix;
/* Flag: alternative output format selected with %#... */
int altformat;
/* Flag: alternative output format selected with %#... */
int altformat;
} PF;
/*
@ -141,31 +139,25 @@ typedef struct {
* We count the total length we send out so we can return it from __vprintf,
* since that's what most printf-like functions want to return.
*/
static
void
__pf_print(PF *pf, const char *txt, size_t len)
{
pf->sendfunc(pf->clientdata, txt, len);
pf->charcount += len;
static void __pf_print(PF *pf, const char *txt, size_t len) {
pf->sendfunc(pf->clientdata, txt, len);
pf->charcount += len;
}
/*
* Reset the state for the next %-field.
*/
static
void
__pf_endfield(PF *pf)
{
pf->in_pct = 0;
pf->size = INTSZ;
pf->num = 0;
pf->sign = 0;
pf->spacing = 0;
pf->rightspc = 0;
pf->fillchar = ' ';
pf->base = 0;
pf->baseprefix = 0;
pf->altformat = 0;
static void __pf_endfield(PF *pf) {
pf->in_pct = 0;
pf->size = INTSZ;
pf->num = 0;
pf->sign = 0;
pf->spacing = 0;
pf->rightspc = 0;
pf->fillchar = ' ';
pf->base = 0;
pf->baseprefix = 0;
pf->altformat = 0;
}
/*
@ -177,59 +169,54 @@ __pf_endfield(PF *pf)
* 0-9 field width
* leading 0 pad with zeros instead of spaces
*/
static
void
__pf_modifier(PF *pf, int ch)
{
switch (ch) {
case '#':
pf->altformat = 1;
break;
case '-':
pf->rightspc = 1;
break;
case 'l':
if (pf->size==LONGSZ) {
static void __pf_modifier(PF *pf, int ch) {
switch (ch) {
case '#':
pf->altformat = 1;
break;
case '-':
pf->rightspc = 1;
break;
case 'l':
if (pf->size == LONGSZ) {
#ifdef USE_LONGLONG
pf->size = LLONGSZ;
pf->size = LLONGSZ;
#endif
}
else {
pf->size = LONGSZ;
}
break;
case 'z':
pf->size = SIZETSZ;
break;
case '0':
if (pf->spacing>0) {
/*
* Already seen some digits; this is part of the
* field size.
*/
pf->spacing = pf->spacing*10;
}
else {
/*
* Leading zero; set the padding character to 0.
*/
pf->fillchar = '0';
}
break;
default:
/*
* Invalid characters should be filtered out by a
* higher-level function, so if this assert goes off
* it's our fault.
*/
assert(ch>'0' && ch<='9');
} else {
pf->size = LONGSZ;
}
break;
case 'z':
pf->size = SIZETSZ;
break;
case '0':
if (pf->spacing > 0) {
/*
* Already seen some digits; this is part of the
* field size.
*/
pf->spacing = pf->spacing * 10;
} else {
/*
* Leading zero; set the padding character to 0.
*/
pf->fillchar = '0';
}
break;
default:
/*
* Invalid characters should be filtered out by a
* higher-level function, so if this assert goes off
* it's our fault.
*/
assert(ch > '0' && ch <= '9');
/*
* Got a digit; accumulate the field size.
*/
pf->spacing = pf->spacing*10 + (ch-'0');
break;
}
/*
* Got a digit; accumulate the field size.
*/
pf->spacing = pf->spacing * 10 + (ch - '0');
break;
}
}
/*
@ -237,77 +224,71 @@ __pf_modifier(PF *pf, int ch)
* in pf->num, according to the size recorded in pf->size and using
* the numeric type specified by ch.
*/
static
void
__pf_getnum(PF *pf, int ch)
{
if (ch=='p') {
/*
* Pointer.
*
* uintptr_t is a C99 standard type that's an unsigned
* integer the same size as a pointer.
*/
pf->num = (uintptr_t) va_arg(pf->ap, void *);
}
else if (ch=='d') {
/* signed integer */
INTTYPE signednum=0;
switch (pf->size) {
case INTSZ:
/* %d */
signednum = va_arg(pf->ap, int);
break;
case LONGSZ:
/* %ld */
signednum = va_arg(pf->ap, long);
break;
static void __pf_getnum(PF *pf, int ch) {
if (ch == 'p') {
/*
* Pointer.
*
* uintptr_t is a C99 standard type that's an unsigned
* integer the same size as a pointer.
*/
pf->num = (uintptr_t)va_arg(pf->ap, void *);
} else if (ch == 'd') {
/* signed integer */
INTTYPE signednum = 0;
switch (pf->size) {
case INTSZ:
/* %d */
signednum = va_arg(pf->ap, int);
break;
case LONGSZ:
/* %ld */
signednum = va_arg(pf->ap, long);
break;
#ifdef USE_LONGLONG
case LLONGSZ:
/* %lld */
signednum = va_arg(pf->ap, long long);
break;
case LLONGSZ:
/* %lld */
signednum = va_arg(pf->ap, long long);
break;
#endif
case SIZETSZ:
/* %zd */
signednum = va_arg(pf->ap, ssize_t);
break;
}
case SIZETSZ:
/* %zd */
signednum = va_arg(pf->ap, ssize_t);
break;
}
/*
* Check for negative numbers.
*/
if (signednum < 0) {
pf->sign = -1;
pf->num = -signednum;
}
else {
pf->num = signednum;
}
}
else {
/* unsigned integer */
switch (pf->size) {
case INTSZ:
/* %u (or %o, %x) */
pf->num = va_arg(pf->ap, unsigned int);
break;
case LONGSZ:
/* %lu (or %lo, %lx) */
pf->num = va_arg(pf->ap, unsigned long);
break;
/*
* Check for negative numbers.
*/
if (signednum < 0) {
pf->sign = -1;
pf->num = -signednum;
} else {
pf->num = signednum;
}
} else {
/* unsigned integer */
switch (pf->size) {
case INTSZ:
/* %u (or %o, %x) */
pf->num = va_arg(pf->ap, unsigned int);
break;
case LONGSZ:
/* %lu (or %lo, %lx) */
pf->num = va_arg(pf->ap, unsigned long);
break;
#ifdef USE_LONGLONG
case LLONGSZ:
/* %llu, %llo, %llx */
pf->num = va_arg(pf->ap, unsigned long long);
break;
case LLONGSZ:
/* %llu, %llo, %llx */
pf->num = va_arg(pf->ap, unsigned long long);
break;
#endif
case SIZETSZ:
/* %zu, %zo, %zx */
pf->num = va_arg(pf->ap, size_t);
break;
}
}
case SIZETSZ:
/* %zu, %zo, %zx */
pf->num = va_arg(pf->ap, size_t);
break;
}
}
}
/*
@ -320,40 +301,34 @@ __pf_getnum(PF *pf, int ch)
* If the "alternate format" was requested, or always for pointers,
* note to print the C prefix for the type.
*/
static
void
__pf_setbase(PF *pf, int ch)
{
switch (ch) {
case 'd':
case 'u':
pf->base = 10;
break;
case 'x':
case 'p':
pf->base = 16;
break;
case 'o':
pf->base = 8;
break;
}
if (pf->altformat || ch=='p') {
pf->baseprefix = 1;
}
static void __pf_setbase(PF *pf, int ch) {
switch (ch) {
case 'd':
case 'u':
pf->base = 10;
break;
case 'x':
case 'p':
pf->base = 16;
break;
case 'o':
pf->base = 8;
break;
}
if (pf->altformat || ch == 'p') {
pf->baseprefix = 1;
}
}
/*
* Function to print "spc" instances of the fill character.
*/
static
void
__pf_fill(PF *pf, int spc)
{
char f = pf->fillchar;
int i;
for (i=0; i<spc; i++) {
__pf_print(pf, &f, 1);
}
static void __pf_fill(PF *pf, int spc) {
char f = pf->fillchar;
int i;
for (i = 0; i < spc; i++) {
__pf_print(pf, &f, 1);
}
}
/*
@ -362,45 +337,40 @@ __pf_fill(PF *pf, int spc)
* and the other is the sign) get printed *after* space padding but
* *before* zero padding, if padding is on the left.
*/
static
void
__pf_printstuff(PF *pf,
const char *prefix, const char *prefix2,
const char *stuff)
{
/* Total length to print. */
int len = strlen(prefix)+strlen(prefix2)+strlen(stuff);
static void __pf_printstuff(PF *pf, const char *prefix, const char *prefix2,
const char *stuff) {
/* Total length to print. */
int len = strlen(prefix) + strlen(prefix2) + strlen(stuff);
/* Get field width and compute amount of padding in "spc". */
int spc = pf->spacing;
if (spc > len) {
spc -= len;
}
else {
spc = 0;
}
/* Get field width and compute amount of padding in "spc". */
int spc = pf->spacing;
if (spc > len) {
spc -= len;
} else {
spc = 0;
}
/* If padding on left and the fill char is not 0, pad first. */
if (spc > 0 && pf->rightspc==0 && pf->fillchar!='0') {
__pf_fill(pf, spc);
}
/* If padding on left and the fill char is not 0, pad first. */
if (spc > 0 && pf->rightspc == 0 && pf->fillchar != '0') {
__pf_fill(pf, spc);
}
/* Print the prefixes. */
__pf_print(pf, prefix, strlen(prefix));
__pf_print(pf, prefix2, strlen(prefix2));
/* Print the prefixes. */
__pf_print(pf, prefix, strlen(prefix));
__pf_print(pf, prefix2, strlen(prefix2));
/* If padding on left and the fill char *is* 0, pad here. */
if (spc > 0 && pf->rightspc==0 && pf->fillchar=='0') {
__pf_fill(pf, spc);
}
/* If padding on left and the fill char *is* 0, pad here. */
if (spc > 0 && pf->rightspc == 0 && pf->fillchar == '0') {
__pf_fill(pf, spc);
}
/* Print the actual string. */
__pf_print(pf, stuff, strlen(stuff));
/* Print the actual string. */
__pf_print(pf, stuff, strlen(stuff));
/* If padding on the right, pad afterwards. */
if (spc > 0 && pf->rightspc!=0) {
__pf_fill(pf, spc);
}
/* If padding on the right, pad afterwards. */
if (spc > 0 && pf->rightspc != 0) {
__pf_fill(pf, spc);
}
}
/*
@ -410,156 +380,142 @@ __pf_printstuff(PF *pf,
* NUMBER_BUF_SIZE is set so that the longest number string we can
* generate (a long long printed in octal) will fit. See above.
*/
static
void
__pf_printnum(PF *pf)
{
/* Digits to print with. */
const char *const digits = "0123456789abcdef";
static void __pf_printnum(PF *pf) {
/* Digits to print with. */
const char *const digits = "0123456789abcdef";
char buf[NUMBER_BUF_SIZE]; /* Accumulation buffer for string. */
char *x; /* Current pointer into buf. */
unsigned INTTYPE xnum; /* Current value to print. */
const char *bprefix; /* Base prefix (0, 0x, or nothing) */
const char *sprefix; /* Sign prefix (- or nothing) */
char buf[NUMBER_BUF_SIZE]; /* Accumulation buffer for string. */
char *x; /* Current pointer into buf. */
unsigned INTTYPE xnum; /* Current value to print. */
const char *bprefix; /* Base prefix (0, 0x, or nothing) */
const char *sprefix; /* Sign prefix (- or nothing) */
/* Start in the last slot of the buffer. */
x = buf+sizeof(buf)-1;
/* Start in the last slot of the buffer. */
x = buf + sizeof(buf) - 1;
/* Insert null terminator. */
*x-- = 0;
/* Insert null terminator. */
*x-- = 0;
/* Initialize value. */
xnum = pf->num;
/* Initialize value. */
xnum = pf->num;
/*
* Convert a single digit.
* Do this loop at least once - that way 0 prints as 0 and not "".
*/
do {
/*
* Get the digit character for the least significant
* part of xnum.
*/
*x = digits[xnum % pf->base];
/*
* Convert a single digit.
* Do this loop at least once - that way 0 prints as 0 and not "".
*/
do {
/*
* Get the digit character for the least significant
* part of xnum.
*/
*x = digits[xnum % pf->base];
/*
* Back up the pointer to point to the next space to the left.
*/
x--;
/*
* Back up the pointer to point to the next space to the left.
*/
x--;
/*
* Drop the value of the digit we just printed from xnum.
*/
xnum = xnum / pf->base;
/*
* Drop the value of the digit we just printed from xnum.
*/
xnum = xnum / pf->base;
/*
* If xnum hits 0 there's no more number left.
*/
} while (xnum > 0);
/*
* If xnum hits 0 there's no more number left.
*/
} while (xnum > 0);
/*
* x points to the *next* slot in the buffer to use.
* However, we're done printing the number. So it's pointing
* one slot *before* the start of the actual number text.
* So advance it by one so it actually points at the number.
*/
x++;
/*
* x points to the *next* slot in the buffer to use.
* However, we're done printing the number. So it's pointing
* one slot *before* the start of the actual number text.
* So advance it by one so it actually points at the number.
*/
x++;
/*
* If a base prefix was requested, select it.
*/
if (pf->baseprefix && pf->base==16) {
bprefix = "0x";
}
else if (pf->baseprefix && pf->base==8) {
bprefix = "0";
}
else {
bprefix = "";
}
/*
* If a base prefix was requested, select it.
*/
if (pf->baseprefix && pf->base == 16) {
bprefix = "0x";
} else if (pf->baseprefix && pf->base == 8) {
bprefix = "0";
} else {
bprefix = "";
}
/*
* Choose the sign prefix.
*/
sprefix = pf->sign ? "-" : "";
/*
* Choose the sign prefix.
*/
sprefix = pf->sign ? "-" : "";
/*
* Now actually print the string we just generated.
*/
__pf_printstuff(pf, sprefix, bprefix, x);
/*
* Now actually print the string we just generated.
*/
__pf_printstuff(pf, sprefix, bprefix, x);
}
/*
* Process a single character out of the format string.
*/
static
void
__pf_send(PF *pf, int ch)
{
/* Cannot get NULs here. */
assert(ch!=0);
static void __pf_send(PF *pf, int ch) {
/* Cannot get NULs here. */
assert(ch != 0);
if (pf->in_pct==0 && ch!='%') {
/*
* Not currently in a format, and not a %. Just send
* the character on through.
*/
char c = ch;
__pf_print(pf, &c, 1);
}
else if (pf->in_pct==0) {
/*
* Not in a format, but got a %. Start a format.
*/
pf->in_pct = 1;
}
else if (strchr("#-lz0123456789", ch)) {
/*
* These are the modifier characters we recognize.
* (These are the characters between the % and the type.)
*/
__pf_modifier(pf, ch);
}
else if (strchr("doupx", ch)) {
/*
* Integer types.
* Fetch the number, set the base, print it, then
* reset for the next format.
*/
__pf_getnum(pf, ch);
__pf_setbase(pf, ch);
__pf_printnum(pf);
__pf_endfield(pf);
}
else if (ch=='s') {
/*
* Print a string.
*/
const char *str = va_arg(pf->ap, const char *);
if (str==NULL) {
str = "(null)";
}
__pf_printstuff(pf, "", "", str);
__pf_endfield(pf);
}
else {
/*
* %%, %c, or illegal character.
* Illegal characters are printed like %%.
* for example, %5k prints " k".
*/
char x[2];
if (ch=='c') {
x[0] = va_arg(pf->ap, int);
}
else {
x[0] = ch;
}
x[1] = 0;
__pf_printstuff(pf, "", "", x);
__pf_endfield(pf);
}
if (pf->in_pct == 0 && ch != '%') {
/*
* Not currently in a format, and not a %. Just send
* the character on through.
*/
char c = ch;
__pf_print(pf, &c, 1);
} else if (pf->in_pct == 0) {
/*
* Not in a format, but got a %. Start a format.
*/
pf->in_pct = 1;
} else if (strchr("#-lz0123456789", ch)) {
/*
* These are the modifier characters we recognize.
* (These are the characters between the % and the type.)
*/
__pf_modifier(pf, ch);
} else if (strchr("doupx", ch)) {
/*
* Integer types.
* Fetch the number, set the base, print it, then
* reset for the next format.
*/
__pf_getnum(pf, ch);
__pf_setbase(pf, ch);
__pf_printnum(pf);
__pf_endfield(pf);
} else if (ch == 's') {
/*
* Print a string.
*/
const char *str = va_arg(pf->ap, const char *);
if (str == NULL) {
str = "(null)";
}
__pf_printstuff(pf, "", "", str);
__pf_endfield(pf);
} else {
/*
* %%, %c, or illegal character.
* Illegal characters are printed like %%.
* for example, %5k prints " k".
*/
char x[2];
if (ch == 'c') {
x[0] = va_arg(pf->ap, int);
} else {
x[0] = ch;
}
x[1] = 0;
__pf_printstuff(pf, "", "", x);
__pf_endfield(pf);
}
}
/*
@ -567,26 +523,24 @@ __pf_send(PF *pf, int ch)
* Create and initialize a printf state object,
* then send it each character from the format string.
*/
int
__vprintf(void (*func)(void *clientdata, const char *str, size_t len),
void *clientdata, const char *format, va_list ap)
{
PF pf;
int i;
int __vprintf(void (*func)(void *clientdata, const char *str, size_t len),
void *clientdata, const char *format, va_list ap) {
PF pf;
int i;
pf.sendfunc = func;
pf.clientdata = clientdata;
pf.sendfunc = func;
pf.clientdata = clientdata;
#ifdef va_copy
va_copy(pf.ap, ap);
va_copy(pf.ap, ap);
#else
pf.ap = ap;
pf.ap = ap;
#endif
pf.charcount = 0;
__pf_endfield(&pf);
pf.charcount = 0;
__pf_endfield(&pf);
for (i=0; format[i]; i++) {
__pf_send(&pf, format[i]);
}
for (i = 0; format[i]; i++) {
__pf_send(&pf, format[i]);
}
return pf.charcount;
return pf.charcount;
}

View File

@ -47,7 +47,6 @@
* Standard C string/IO function: printf into a character buffer.
*/
/*
* Context structure for snprintf: buffer to print into, maximum
* length, and index of the next character to write.
@ -58,9 +57,9 @@
*/
typedef struct {
char *buf;
size_t buflen;
size_t bufpos;
char *buf;
size_t buflen;
size_t bufpos;
} SNP;
/*
@ -70,88 +69,79 @@ typedef struct {
* null-terminated.
*/
static
void
__snprintf_send(void *mydata, const char *data, size_t len)
{
SNP *snp = mydata;
unsigned i;
static void __snprintf_send(void *mydata, const char *data, size_t len) {
SNP *snp = mydata;
unsigned i;
/* For each character we're sent... */
for (i=0; i<len; i++) {
/* For each character we're sent... */
for (i = 0; i < len; i++) {
/* If we aren't past the length, */
if (snp->bufpos < snp->buflen) {
/* If we aren't past the length, */
if (snp->bufpos < snp->buflen) {
/* store the character */
snp->buf[snp->bufpos] = data[i];
/* store the character */
snp->buf[snp->bufpos] = data[i];
/* and increment the position. */
snp->bufpos++;
}
}
/* and increment the position. */
snp->bufpos++;
}
}
}
/*
* The va_list version of snprintf.
*/
int
vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
{
int chars;
SNP snp;
int vsnprintf(char *buf, size_t len, const char *fmt, va_list ap) {
int chars;
SNP snp;
/*
* Fill in the context structure.
* We set snp.buflen to the number of characters that can be
* written (excluding the null terminator) so as not to have
* to special-case the possibility that we got passed a length
* of zero elsewhere.
*/
snp.buf = buf;
if (len==0) {
snp.buflen = 0;
}
else {
snp.buflen = len-1;
}
snp.bufpos = 0;
/*
* Fill in the context structure.
* We set snp.buflen to the number of characters that can be
* written (excluding the null terminator) so as not to have
* to special-case the possibility that we got passed a length
* of zero elsewhere.
*/
snp.buf = buf;
if (len == 0) {
snp.buflen = 0;
} else {
snp.buflen = len - 1;
}
snp.bufpos = 0;
/* Call __vprintf to do the actual work. */
chars = __vprintf(__snprintf_send, &snp, fmt, ap);
/* Call __vprintf to do the actual work. */
chars = __vprintf(__snprintf_send, &snp, fmt, ap);
/*
* Add a null terminator. If the length *we were passed* is greater
* than zero, we reserved a space in the buffer for the terminator,
* so this won't overflow. If the length we were passed is zero,
* nothing will have been or should be written anyway, and buf
* might even be NULL. (C99 explicitly endorses this possibility.)
*/
if (len > 0) {
buf[snp.bufpos] = 0;
}
/*
* Add a null terminator. If the length *we were passed* is greater
* than zero, we reserved a space in the buffer for the terminator,
* so this won't overflow. If the length we were passed is zero,
* nothing will have been or should be written anyway, and buf
* might even be NULL. (C99 explicitly endorses this possibility.)
*/
if (len > 0) {
buf[snp.bufpos] = 0;
}
/*
* Return the number of characters __vprintf processed.
* According to C99, snprintf should return this number, not
* the number of characters actually stored, and should not
* return -1 on overflow but only on other errors. (All none
* of them since we don't do multibyte characters...)
*/
return chars;
/*
* Return the number of characters __vprintf processed.
* According to C99, snprintf should return this number, not
* the number of characters actually stored, and should not
* return -1 on overflow but only on other errors. (All none
* of them since we don't do multibyte characters...)
*/
return chars;
}
/*
* snprintf - hand off to vsnprintf.
*/
int
snprintf(char *buf, size_t len, const char *fmt, ...)
{
int chars;
va_list ap;
va_start(ap, fmt);
chars = vsnprintf(buf, len, fmt, ap);
va_end(ap);
return chars;
int snprintf(char *buf, size_t len, const char *fmt, ...) {
int chars;
va_list ap;
va_start(ap, fmt);
chars = vsnprintf(buf, len, fmt, ap);
va_end(ap);
return chars;
}

View File

@ -46,56 +46,53 @@
* really report syntax errors or overflow in any useful way.
*/
int
atoi(const char *s)
{
static const char digits[] = "0123456789"; /* legal digits in order */
unsigned val=0; /* value we're accumulating */
int neg=0; /* set to true if we see a minus sign */
int atoi(const char *s) {
static const char digits[] = "0123456789"; /* legal digits in order */
unsigned val = 0; /* value we're accumulating */
int neg = 0; /* set to true if we see a minus sign */
/* skip whitespace */
while (*s==' ' || *s=='\t') {
s++;
}
/* skip whitespace */
while (*s == ' ' || *s == '\t') {
s++;
}
/* check for sign */
if (*s=='-') {
neg=1;
s++;
}
else if (*s=='+') {
s++;
}
/* check for sign */
if (*s == '-') {
neg = 1;
s++;
} else if (*s == '+') {
s++;
}
/* process each digit */
while (*s) {
const char *where;
unsigned digit;
/* process each digit */
while (*s) {
const char *where;
unsigned digit;
/* look for the digit in the list of digits */
where = strchr(digits, *s);
if (where==NULL) {
/* not found; not a digit, so stop */
break;
}
/* look for the digit in the list of digits */
where = strchr(digits, *s);
if (where == NULL) {
/* not found; not a digit, so stop */
break;
}
/* get the index into the digit list, which is the value */
digit = (where - digits);
/* get the index into the digit list, which is the value */
digit = (where - digits);
/* could (should?) check for overflow here */
/* could (should?) check for overflow here */
/* shift the number over and add in the new digit */
val = val*10 + digit;
/* shift the number over and add in the new digit */
val = val * 10 + digit;
/* look at the next character */
s++;
}
/* look at the next character */
s++;
}
/* handle negative numbers */
if (neg) {
return -val;
}
/* handle negative numbers */
if (neg) {
return -val;
}
/* done */
return val;
/* done */
return val;
}

View File

@ -45,32 +45,28 @@
* memory.
*/
void
bzero(void *vblock, size_t len)
{
char *block = vblock;
size_t i;
void bzero(void *vblock, size_t len) {
char *block = vblock;
size_t i;
/*
* For performance, optimize the common case where the pointer
* and the length are word-aligned, and write word-at-a-time
* instead of byte-at-a-time. Otherwise, write bytes.
*
* The alignment logic here should be portable. We rely on the
* compiler to be reasonably intelligent about optimizing the
* divides and moduli out. Fortunately, it is.
*/
/*
* For performance, optimize the common case where the pointer
* and the length are word-aligned, and write word-at-a-time
* instead of byte-at-a-time. Otherwise, write bytes.
*
* The alignment logic here should be portable. We rely on the
* compiler to be reasonably intelligent about optimizing the
* divides and moduli out. Fortunately, it is.
*/
if ((uintptr_t)block % sizeof(long) == 0 &&
len % sizeof(long) == 0) {
long *lb = (long *)block;
for (i=0; i<len/sizeof(long); i++) {
lb[i] = 0;
}
}
else {
for (i=0; i<len; i++) {
block[i] = 0;
}
}
if ((uintptr_t)block % sizeof(long) == 0 && len % sizeof(long) == 0) {
long *lb = (long *)block;
for (i = 0; i < len / sizeof(long); i++) {
lb[i] = 0;
}
} else {
for (i = 0; i < len; i++) {
block[i] = 0;
}
}
}

View File

@ -44,43 +44,39 @@
* C standard function - copy a block of memory.
*/
void *
memcpy(void *dst, const void *src, size_t len)
{
size_t i;
void *memcpy(void *dst, const void *src, size_t len) {
size_t i;
/*
* memcpy does not support overlapping buffers, so always do it
* forwards. (Don't change this without adjusting memmove.)
*
* For speedy copying, optimize the common case where both pointers
* and the length are word-aligned, and copy word-at-a-time instead
* of byte-at-a-time. Otherwise, copy by bytes.
*
* The alignment logic below should be portable. We rely on
* the compiler to be reasonably intelligent about optimizing
* the divides and modulos out. Fortunately, it is.
*/
/*
* memcpy does not support overlapping buffers, so always do it
* forwards. (Don't change this without adjusting memmove.)
*
* For speedy copying, optimize the common case where both pointers
* and the length are word-aligned, and copy word-at-a-time instead
* of byte-at-a-time. Otherwise, copy by bytes.
*
* The alignment logic below should be portable. We rely on
* the compiler to be reasonably intelligent about optimizing
* the divides and modulos out. Fortunately, it is.
*/
if ((uintptr_t)dst % sizeof(long) == 0 &&
(uintptr_t)src % sizeof(long) == 0 &&
len % sizeof(long) == 0) {
if ((uintptr_t)dst % sizeof(long) == 0 &&
(uintptr_t)src % sizeof(long) == 0 && len % sizeof(long) == 0) {
long *d = dst;
const long *s = src;
long *d = dst;
const long *s = src;
for (i=0; i<len/sizeof(long); i++) {
d[i] = s[i];
}
}
else {
char *d = dst;
const char *s = src;
for (i = 0; i < len / sizeof(long); i++) {
d[i] = s[i];
}
} else {
char *d = dst;
const char *s = src;
for (i=0; i<len; i++) {
d[i] = s[i];
}
}
for (i = 0; i < len; i++) {
d[i] = s[i];
}
}
return dst;
return dst;
}

View File

@ -45,73 +45,69 @@
* regions correctly.
*/
void *
memmove(void *dst, const void *src, size_t len)
{
size_t i;
void *memmove(void *dst, const void *src, size_t len) {
size_t i;
/*
* If the buffers don't overlap, it doesn't matter what direction
* we copy in. If they do, it does, so just assume they always do.
* We don't concern ourselves with the possibility that the region
* to copy might roll over across the top of memory, because it's
* not going to happen.
*
* If the destination is above the source, we have to copy
* back to front to avoid overwriting the data we want to
* copy.
*
* dest: dddddddd
* src: ssssssss ^
* | ^ |___|
* |___|
*
* If the destination is below the source, we have to copy
* front to back.
*
* dest: dddddddd
* src: ^ ssssssss
* |___| ^ |
* |___|
*/
/*
* If the buffers don't overlap, it doesn't matter what direction
* we copy in. If they do, it does, so just assume they always do.
* We don't concern ourselves with the possibility that the region
* to copy might roll over across the top of memory, because it's
* not going to happen.
*
* If the destination is above the source, we have to copy
* back to front to avoid overwriting the data we want to
* copy.
*
* dest: dddddddd
* src: ssssssss ^
* | ^ |___|
* |___|
*
* If the destination is below the source, we have to copy
* front to back.
*
* dest: dddddddd
* src: ^ ssssssss
* |___| ^ |
* |___|
*/
if ((uintptr_t)dst < (uintptr_t)src) {
/*
* As author/maintainer of libc, take advantage of the
* fact that we know memcpy copies forwards.
*/
return memcpy(dst, src, len);
}
if ((uintptr_t)dst < (uintptr_t)src) {
/*
* As author/maintainer of libc, take advantage of the
* fact that we know memcpy copies forwards.
*/
return memcpy(dst, src, len);
}
/*
* Copy by words in the common case. Look in memcpy.c for more
* information.
*/
/*
* Copy by words in the common case. Look in memcpy.c for more
* information.
*/
if ((uintptr_t)dst % sizeof(long) == 0 &&
(uintptr_t)src % sizeof(long) == 0 &&
len % sizeof(long) == 0) {
if ((uintptr_t)dst % sizeof(long) == 0 &&
(uintptr_t)src % sizeof(long) == 0 && len % sizeof(long) == 0) {
long *d = dst;
const long *s = src;
long *d = dst;
const long *s = src;
/*
* The reason we copy index i-1 and test i>0 is that
* i is unsigned -- so testing i>=0 doesn't work.
*/
/*
* The reason we copy index i-1 and test i>0 is that
* i is unsigned -- so testing i>=0 doesn't work.
*/
for (i=len/sizeof(long); i>0; i--) {
d[i-1] = s[i-1];
}
}
else {
char *d = dst;
const char *s = src;
for (i = len / sizeof(long); i > 0; i--) {
d[i - 1] = s[i - 1];
}
} else {
char *d = dst;
const char *s = src;
for (i=len; i>0; i--) {
d[i-1] = s[i-1];
}
}
for (i = len; i > 0; i--) {
d[i - 1] = s[i - 1];
}
}
return dst;
return dst;
}

View File

@ -38,15 +38,13 @@
* C standard function - initialize a block of memory
*/
void *
memset(void *ptr, int ch, size_t len)
{
char *p = ptr;
size_t i;
void *memset(void *ptr, int ch, size_t len) {
char *p = ptr;
size_t i;
for (i=0; i<len; i++) {
p[i] = ch;
}
for (i = 0; i < len; i++) {
p[i] = ch;
}
return ptr;
return ptr;
}

View File

@ -43,12 +43,10 @@
* Standard C string function: append one string to another.
*/
char *
strcat(char *dest, const char *src)
{
size_t offset;
char *strcat(char *dest, const char *src) {
size_t offset;
offset = strlen(dest);
strcpy(dest+offset, src);
return dest;
offset = strlen(dest);
strcpy(dest + offset, src);
return dest;
}

View File

@ -43,26 +43,24 @@
* C standard string function: find leftmost instance of a character
* in a string.
*/
char *
strchr(const char *s, int ch_arg)
{
/* avoid sign-extension problems */
const char ch = ch_arg;
char *strchr(const char *s, int ch_arg) {
/* avoid sign-extension problems */
const char ch = ch_arg;
/* scan from left to right */
while (*s) {
/* if we hit it, return it */
if (*s == ch) {
return (char *)s;
}
s++;
}
/* scan from left to right */
while (*s) {
/* if we hit it, return it */
if (*s == ch) {
return (char *)s;
}
s++;
}
/* if we were looking for the 0, return that */
if (*s == ch) {
return (char *)s;
}
/* if we were looking for the 0, return that */
if (*s == ch) {
return (char *)s;
}
/* didn't find it */
return NULL;
/* didn't find it */
return NULL;
}

View File

@ -44,47 +44,44 @@
* sort order.
*/
int
strcmp(const char *a, const char *b)
{
size_t i;
int strcmp(const char *a, const char *b) {
size_t i;
/*
* Walk down both strings until either they're different
* or we hit the end of A.
*
* If A and B strings are not the same length, when the
* shorter one ends, the two will be different, and we'll
* stop before running off the end of either.
*
* If they *are* the same length, it's sufficient to check
* that we haven't run off the end of A, because that's the
* same as checking to make sure we haven't run off the end of
* B.
*/
/*
* Walk down both strings until either they're different
* or we hit the end of A.
*
* If A and B strings are not the same length, when the
* shorter one ends, the two will be different, and we'll
* stop before running off the end of either.
*
* If they *are* the same length, it's sufficient to check
* that we haven't run off the end of A, because that's the
* same as checking to make sure we haven't run off the end of
* B.
*/
for (i=0; a[i]!=0 && a[i]==b[i]; i++) {
/* nothing */
}
for (i = 0; a[i] != 0 && a[i] == b[i]; i++) {
/* nothing */
}
/*
* If A is greater than B, return 1. If A is less than B,
* return -1. If they're the same, return 0. Since we have
* stopped at the first character of difference (or the end of
* both strings) checking the character under I accomplishes
* this.
*
* Note that strcmp does not handle accented characters,
* internationalization, or locale sort order; strcoll() does
* that.
*
* The rules say we compare order in terms of *unsigned* char.
*/
if ((unsigned char)a[i] > (unsigned char)b[i]) {
return 1;
}
else if (a[i] == b[i]) {
return 0;
}
return -1;
/*
* If A is greater than B, return 1. If A is less than B,
* return -1. If they're the same, return 0. Since we have
* stopped at the first character of difference (or the end of
* both strings) checking the character under I accomplishes
* this.
*
* Note that strcmp does not handle accented characters,
* internationalization, or locale sort order; strcoll() does
* that.
*
* The rules say we compare order in terms of *unsigned* char.
*/
if ((unsigned char)a[i] > (unsigned char)b[i]) {
return 1;
} else if (a[i] == b[i]) {
return 0;
}
return -1;
}

View File

@ -42,22 +42,20 @@
/*
* Standard C string function: copy one string to another.
*/
char *
strcpy(char *dest, const char *src)
{
size_t i;
char *strcpy(char *dest, const char *src) {
size_t i;
/*
* Copy characters until we hit the null terminator.
*/
for (i=0; src[i]; i++) {
dest[i] = src[i];
}
/*
* Copy characters until we hit the null terminator.
*/
for (i = 0; src[i]; i++) {
dest[i] = src[i];
}
/*
* Add null terminator to result.
*/
dest[i] = 0;
/*
* Add null terminator to result.
*/
dest[i] = 0;
return dest;
return dest;
}

View File

@ -43,13 +43,11 @@
* C standard string function: get length of a string
*/
size_t
strlen(const char *str)
{
size_t ret = 0;
size_t strlen(const char *str) {
size_t ret = 0;
while (str[ret]) {
ret++;
}
return ret;
while (str[ret]) {
ret++;
}
return ret;
}

View File

@ -43,27 +43,25 @@
* C standard string function: find rightmost instance of a character
* in a string.
*/
char *
strrchr(const char *s, int ch_arg)
{
/* avoid sign-extension problems */
const char ch = ch_arg;
char *strrchr(const char *s, int ch_arg) {
/* avoid sign-extension problems */
const char ch = ch_arg;
/* start one past the last character INCLUDING NULL TERMINATOR */
size_t i = strlen(s)+1;
/* start one past the last character INCLUDING NULL TERMINATOR */
size_t i = strlen(s) + 1;
/* go from right to left; stop at 0 */
while (i > 0) {
/* go from right to left; stop at 0 */
while (i > 0) {
/* decrement first */
i--;
/* decrement first */
i--;
/* now check the character we're over */
if (s[i] == ch) {
return (char *)(s+i);
}
}
/* now check the character we're over */
if (s[i] == ch) {
return (char *)(s + i);
}
}
/* didn't find it */
return NULL;
/* didn't find it */
return NULL;
}

View File

@ -46,51 +46,48 @@
* The "context" argument should point to a "char *" that is preserved
* between calls to strtok_r that wish to operate on same string.
*/
char *
strtok_r(char *string, const char *seps, char **context)
{
char *head; /* start of word */
char *tail; /* end of word */
char *strtok_r(char *string, const char *seps, char **context) {
char *head; /* start of word */
char *tail; /* end of word */
/* If we're starting up, initialize context */
if (string) {
*context = string;
}
/* If we're starting up, initialize context */
if (string) {
*context = string;
}
/* Get potential start of this next word */
head = *context;
if (head == NULL) {
return NULL;
}
/* Get potential start of this next word */
head = *context;
if (head == NULL) {
return NULL;
}
/* Skip any leading separators */
while (*head && strchr(seps, *head)) {
head++;
}
/* Skip any leading separators */
while (*head && strchr(seps, *head)) {
head++;
}
/* Did we hit the end? */
if (*head == 0) {
/* Nothing left */
*context = NULL;
return NULL;
}
/* Did we hit the end? */
if (*head == 0) {
/* Nothing left */
*context = NULL;
return NULL;
}
/* skip over word */
tail = head;
while (*tail && !strchr(seps, *tail)) {
tail++;
}
/* skip over word */
tail = head;
while (*tail && !strchr(seps, *tail)) {
tail++;
}
/* Save head for next time in context */
if (*tail == 0) {
*context = NULL;
}
else {
*tail = 0;
tail++;
*context = tail;
}
/* Save head for next time in context */
if (*tail == 0) {
*context = NULL;
} else {
*tail = 0;
tail++;
*context = tail;
}
/* Return current word */
return head;
/* Return current word */
return head;
}

View File

@ -30,7 +30,6 @@
#ifndef _MIPS_CURRENT_H_
#define _MIPS_CURRENT_H_
/*
* Macro for current thread, or current cpu.
*
@ -60,7 +59,7 @@
*/
#ifdef __GNUC__
register struct thread *curthread __asm("$23"); /* s7 register */
register struct thread *curthread __asm("$23"); /* s7 register */
#else
#error "Don't know how to declare curthread in this compiler"
#endif

View File

@ -34,25 +34,23 @@
* MIPS machine-dependent definitions for the ELF binary format.
*/
/* The ELF executable type. */
#define EM_MACHINE EM_MIPS
#define EM_MACHINE EM_MIPS
/* Linker relocation codes. SIZE DESCRIPTION */
#define R_MIPS_NONE 0 /* --- nop */
#define R_MIPS_16 1 /* u16 value */
#define R_MIPS_32 2 /* u32 value */
#define R_MIPS_REL32 3 /* u32 value relative to patched address */
#define R_MIPS_26 4 /* u26 j/jal instruction address field */
#define R_MIPS_HI16 5 /* u16 %hi(sym) as below */
#define R_MIPS_LO16 6 /* s16 %lo(sym) as below */
#define R_MIPS_GPREL16 7 /* s16 offset from GP register */
#define R_MIPS_LITERAL 8 /* s16 GPREL16 for file-local symbols (?) */
#define R_MIPS_GOT16 9 /* u16 offset into global offset table */
#define R_MIPS_PC16 10 /* s16 PC-relative reference */
#define R_MIPS_CALL16 11 /* u16 call through global offset table */
#define R_MIPS_GPREL32 12 /* s32 offset from GP register */
#define R_MIPS_NONE 0 /* --- nop */
#define R_MIPS_16 1 /* u16 value */
#define R_MIPS_32 2 /* u32 value */
#define R_MIPS_REL32 3 /* u32 value relative to patched address */
#define R_MIPS_26 4 /* u26 j/jal instruction address field */
#define R_MIPS_HI16 5 /* u16 %hi(sym) as below */
#define R_MIPS_LO16 6 /* s16 %lo(sym) as below */
#define R_MIPS_GPREL16 7 /* s16 offset from GP register */
#define R_MIPS_LITERAL 8 /* s16 GPREL16 for file-local symbols (?) */
#define R_MIPS_GOT16 9 /* u16 offset into global offset table */
#define R_MIPS_PC16 10 /* s16 PC-relative reference */
#define R_MIPS_CALL16 11 /* u16 call through global offset table */
#define R_MIPS_GPREL32 12 /* s32 offset from GP register */
/* %hi/%lo are defined so %hi(sym) << 16 + %lo(sym) = sym */
#endif /* _MIPS_ELF_H_ */

View File

@ -36,39 +36,37 @@
#ifndef _KERN_MIPS_REGDEFS_H_
#define _KERN_MIPS_REGDEFS_H_
#define z0 $0 /* always zero register */
#define AT $1 /* assembler temp register */
#define v0 $2 /* value 0 */
#define v1 $3 /* value 1 */
#define a0 $4 /* argument 0 */
#define a1 $5 /* argument 1 */
#define a2 $6 /* argument 2 */
#define a3 $7 /* argument 3 */
#define t0 $8 /* temporary (caller-save) 0 */
#define t1 $9 /* temporary (caller-save) 1 */
#define t2 $10 /* temporary (caller-save) 2 */
#define t3 $11 /* temporary (caller-save) 3 */
#define t4 $12 /* temporary (caller-save) 4 */
#define t5 $13 /* temporary (caller-save) 5 */
#define t6 $14 /* temporary (caller-save) 6 */
#define t7 $15 /* temporary (caller-save) 7 */
#define s0 $16 /* saved (callee-save) 0 */
#define s1 $17 /* saved (callee-save) 1 */
#define s2 $18 /* saved (callee-save) 2 */
#define s3 $19 /* saved (callee-save) 3 */
#define s4 $20 /* saved (callee-save) 4 */
#define s5 $21 /* saved (callee-save) 5 */
#define s6 $22 /* saved (callee-save) 6 */
#define s7 $23 /* saved (callee-save) 7 */
#define t8 $24 /* temporary (caller-save) 8 */
#define t9 $25 /* temporary (caller-save) 9 */
#define k0 $26 /* kernel temporary 0 */
#define k1 $27 /* kernel temporary 1 */
#define gp $28 /* global pointer */
#define sp $29 /* stack pointer */
#define s8 $30 /* saved (callee-save) 8 = frame pointer */
#define ra $31 /* return address */
#define z0 $0 /* always zero register */
#define AT $1 /* assembler temp register */
#define v0 $2 /* value 0 */
#define v1 $3 /* value 1 */
#define a0 $4 /* argument 0 */
#define a1 $5 /* argument 1 */
#define a2 $6 /* argument 2 */
#define a3 $7 /* argument 3 */
#define t0 $8 /* temporary (caller-save) 0 */
#define t1 $9 /* temporary (caller-save) 1 */
#define t2 $10 /* temporary (caller-save) 2 */
#define t3 $11 /* temporary (caller-save) 3 */
#define t4 $12 /* temporary (caller-save) 4 */
#define t5 $13 /* temporary (caller-save) 5 */
#define t6 $14 /* temporary (caller-save) 6 */
#define t7 $15 /* temporary (caller-save) 7 */
#define s0 $16 /* saved (callee-save) 0 */
#define s1 $17 /* saved (callee-save) 1 */
#define s2 $18 /* saved (callee-save) 2 */
#define s3 $19 /* saved (callee-save) 3 */
#define s4 $20 /* saved (callee-save) 4 */
#define s5 $21 /* saved (callee-save) 5 */
#define s6 $22 /* saved (callee-save) 6 */
#define s7 $23 /* saved (callee-save) 7 */
#define t8 $24 /* temporary (caller-save) 8 */
#define t9 $25 /* temporary (caller-save) 9 */
#define k0 $26 /* kernel temporary 0 */
#define k1 $27 /* kernel temporary 1 */
#define gp $28 /* global pointer */
#define sp $29 /* stack pointer */
#define s8 $30 /* saved (callee-save) 8 = frame pointer */
#define ra $31 /* return address */
#endif /* _KERN_MIPS_REGDEFS_H_ */

View File

@ -38,10 +38,9 @@
* Must save: s0-s8, sp, ra (11 registers)
* Don't change __JB_REGS without adjusting mips_setjmp.S accordingly.
*/
#define __JB_REGS 11
#define __JB_REGS 11
/* A jmp_buf is an array of __JB_REGS registers */
typedef uint32_t jmp_buf[__JB_REGS];
#endif /* _MIPS_SETJMP_H_ */

View File

@ -27,7 +27,6 @@
* SUCH DAMAGE.
*/
#ifndef _KERN_MIPS_SIGNAL_H_
#define _KERN_MIPS_SIGNAL_H_
@ -39,7 +38,7 @@
* probably won't.)
*/
struct sigcontext {
/* Dummy. */
/* Dummy. */
};
#endif /* _KERN_MIPS_SIGNAL_H_ */

View File

@ -38,21 +38,20 @@
* See kern/types.h for an explanation of the underscores.
*/
/* Sized integer types, with convenient short names */
typedef char __i8; /* 8-bit signed integer */
typedef short __i16; /* 16-bit signed integer */
typedef int __i32; /* 32-bit signed integer */
typedef long long __i64; /* 64-bit signed integer */
typedef char __i8; /* 8-bit signed integer */
typedef short __i16; /* 16-bit signed integer */
typedef int __i32; /* 32-bit signed integer */
typedef long long __i64; /* 64-bit signed integer */
typedef unsigned char __u8; /* 8-bit unsigned integer */
typedef unsigned short __u16; /* 16-bit unsigned integer */
typedef unsigned int __u32; /* 32-bit unsigned integer */
typedef unsigned long long __u64; /* 64-bit unsigned integer */
typedef unsigned char __u8; /* 8-bit unsigned integer */
typedef unsigned short __u16; /* 16-bit unsigned integer */
typedef unsigned int __u32; /* 32-bit unsigned integer */
typedef unsigned long long __u64; /* 64-bit unsigned integer */
/* Further standard C types */
typedef long __intptr_t; /* Signed pointer-sized integer */
typedef unsigned long __uintptr_t; /* Unsigned pointer-sized integer */
typedef long __intptr_t; /* Signed pointer-sized integer */
typedef unsigned long __uintptr_t; /* Unsigned pointer-sized integer */
/*
* Since we're a 32-bit platform, size_t, ssize_t, and ptrdiff_t can
@ -62,17 +61,16 @@ typedef unsigned long __uintptr_t; /* Unsigned pointer-sized integer */
* errors involving size_t, try changing this.
*/
#if 1
typedef unsigned __size_t; /* Size of a memory region */
typedef int __ssize_t; /* Signed type of same size */
typedef int __ptrdiff_t; /* Difference of two pointers */
typedef unsigned __size_t; /* Size of a memory region */
typedef int __ssize_t; /* Signed type of same size */
typedef int __ptrdiff_t; /* Difference of two pointers */
#else
typedef unsigned long __size_t; /* Size of a memory region */
typedef long __ssize_t; /* Signed type of same size */
typedef long __ptrdiff_t; /* Difference of two pointers */
typedef unsigned long __size_t; /* Size of a memory region */
typedef long __ssize_t; /* Signed type of same size */
typedef long __ptrdiff_t; /* Difference of two pointers */
#endif
/* Number of bits per byte. */
#define __CHAR_BIT 8
#define __CHAR_BIT 8
#endif /* _KERN_MIPS_TYPES_H_ */

View File

@ -41,17 +41,14 @@
*/
MEMBAR_INLINE
void
membar_any_any(void)
{
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
"sync;" /* do it */
".set pop" /* restore assembler mode */
: /* no outputs */
: /* no inputs */
: "memory"); /* "changes" memory */
void membar_any_any(void) {
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
"sync;" /* do it */
".set pop" /* restore assembler mode */
: /* no outputs */
: /* no inputs */
: "memory"); /* "changes" memory */
}
MEMBAR_INLINE void membar_load_load(void) { membar_any_any(); }
@ -59,5 +56,4 @@ MEMBAR_INLINE void membar_store_store(void) { membar_any_any(); }
MEMBAR_INLINE void membar_store_any(void) { membar_any_any(); }
MEMBAR_INLINE void membar_any_store(void) { membar_any_any(); }
#endif /* _MIPS_MEMBAR_H_ */

View File

@ -30,62 +30,61 @@
#ifndef _MIPS_SPECIALREG_H_
#define _MIPS_SPECIALREG_H_
/*
* Coprocessor 0 (system processor) register numbers
*/
#define c0_index $0 /* TLB entry index register */
#define c0_random $1 /* TLB random slot register */
#define c0_entrylo $2 /* TLB entry contents (low-order half) */
/* c0_entrylo0 $2 */ /* MIPS-II and up only */
/* c0_entrylo1 $3 */ /* MIPS-II and up only */
#define c0_context $4 /* some precomputed pagetable stuff */
/* c0_pagemask $5 */ /* MIPS-II and up only */
/* c0_wired $6 */ /* MIPS-II and up only */
#define c0_vaddr $8 /* virtual addr of failing memory access */
#define c0_count $9 /* cycle counter (MIPS-II and up) */
#define c0_entryhi $10 /* TLB entry contents (high-order half) */
#define c0_compare $11 /* on-chip timer control (MIPS-II and up) */
#define c0_status $12 /* processor status register */
#define c0_cause $13 /* exception cause register */
#define c0_epc $14 /* exception PC register */
#define c0_prid $15 /* processor ID register */
/* c0_config $16 */ /* MIPS-II and up only */
/* c0_lladdr $17 */ /* MIPS-II and up only */
/* c0_watchlo $18 */ /* MIPS-II and up only */
/* c0_watchhi $19 */ /* MIPS-II and up only */
#define c0_index $0 /* TLB entry index register */
#define c0_random $1 /* TLB random slot register */
#define c0_entrylo $2 /* TLB entry contents (low-order half) */
/* c0_entrylo0 $2 */ /* MIPS-II and up only */
/* c0_entrylo1 $3 */ /* MIPS-II and up only */
#define c0_context $4 /* some precomputed pagetable stuff */
/* c0_pagemask $5 */ /* MIPS-II and up only */
/* c0_wired $6 */ /* MIPS-II and up only */
#define c0_vaddr $8 /* virtual addr of failing memory access */
#define c0_count $9 /* cycle counter (MIPS-II and up) */
#define c0_entryhi $10 /* TLB entry contents (high-order half) */
#define c0_compare $11 /* on-chip timer control (MIPS-II and up) */
#define c0_status $12 /* processor status register */
#define c0_cause $13 /* exception cause register */
#define c0_epc $14 /* exception PC register */
#define c0_prid $15 /* processor ID register */
/* c0_config $16 */ /* MIPS-II and up only */
/* c0_lladdr $17 */ /* MIPS-II and up only */
/* c0_watchlo $18 */ /* MIPS-II and up only */
/* c0_watchhi $19 */ /* MIPS-II and up only */
/*
* Mode bits in c0_status
*/
#define CST_IEc 0x00000001 /* current: interrupt enable */
#define CST_KUc 0x00000002 /* current: user mode */
#define CST_IEp 0x00000004 /* previous: interrupt enable */
#define CST_KUp 0x00000008 /* previous: user mode */
#define CST_IEo 0x00000010 /* old: interrupt enable */
#define CST_KUo 0x00000020 /* old: user mode */
#define CST_IEc 0x00000001 /* current: interrupt enable */
#define CST_KUc 0x00000002 /* current: user mode */
#define CST_IEp 0x00000004 /* previous: interrupt enable */
#define CST_KUp 0x00000008 /* previous: user mode */
#define CST_IEo 0x00000010 /* old: interrupt enable */
#define CST_KUo 0x00000020 /* old: user mode */
#define CST_MODEMASK 0x0000003f /* mask for the above */
#define CST_IRQMASK 0x0000ff00 /* mask for the individual irq enable bits */
#define CST_BEV 0x00400000 /* bootstrap exception vectors flag */
#define CST_IRQMASK 0x0000ff00 /* mask for the individual irq enable bits */
#define CST_BEV 0x00400000 /* bootstrap exception vectors flag */
/*
* Fields of the c0_cause register
*/
#define CCA_UTLB 0x00000001 /* true if UTLB exception (set by our asm) */
#define CCA_CODE 0x0000003c /* EX_foo in trapframe.h */
#define CCA_IRQS 0x0000ff00 /* Currently pending interrupts */
#define CCA_COPN 0x30000000 /* Coprocessor number for EX_CPU */
#define CCA_JD 0x80000000 /* True if exception happened in jump delay */
#define CCA_UTLB 0x00000001 /* true if UTLB exception (set by our asm) */
#define CCA_CODE 0x0000003c /* EX_foo in trapframe.h */
#define CCA_IRQS 0x0000ff00 /* Currently pending interrupts */
#define CCA_COPN 0x30000000 /* Coprocessor number for EX_CPU */
#define CCA_JD 0x80000000 /* True if exception happened in jump delay */
#define CCA_CODESHIFT 2 /* shift for CCA_CODE field */
#define CCA_CODESHIFT 2 /* shift for CCA_CODE field */
/*
* Fields of the c0_index register
*/
#define CIN_P 0x80000000 /* nonzero -> TLB probe found nothing */
#define CIN_INDEX 0x00003f00 /* 6-bit index into TLB */
#define CIN_P 0x80000000 /* nonzero -> TLB probe found nothing */
#define CIN_INDEX 0x00003f00 /* 6-bit index into TLB */
#define CIN_INDEXSHIFT 8 /* shift for CIN_INDEX field */
#define CIN_INDEXSHIFT 8 /* shift for CIN_INDEX field */
/*
* Fields of the c0_context register
@ -102,16 +101,15 @@
* there's no other good place in the chip to put it. See discussions
* elsewhere.
*/
#define CTX_VSHIFT 0x001ffffc /* shifted/masked copy of c0_vaddr */
#define CTX_PTBASE 0xffe00000 /* page table base address */
#define CTX_VSHIFT 0x001ffffc /* shifted/masked copy of c0_vaddr */
#define CTX_PTBASE 0xffe00000 /* page table base address */
#define CTX_PTBASESHIFT 21 /* shift for CTX_PBASE field */
#define CTX_PTBASESHIFT 21 /* shift for CTX_PBASE field */
/*
* Hardwired exception handler addresses.
*/
#define EXADDR_UTLB 0x80000000
#define EXADDR_GENERAL 0x80000080
#define EXADDR_UTLB 0x80000000
#define EXADDR_GENERAL 0x80000080
#endif /* _MIPS_SPECIALREG_H_ */

View File

@ -32,12 +32,11 @@
#include <cdefs.h>
/* Type of value needed to actually spin on */
typedef unsigned spinlock_data_t;
/* Initializer for use by SPINLOCK_INITIALIZER */
#define SPINLOCK_DATA_INITIALIZER 0
#define SPINLOCK_DATA_INITIALIZER 0
/* Atomic operations on spinlock_data_t */
SPINLOCK_INLINE
@ -55,10 +54,8 @@ spinlock_data_t spinlock_data_testandset(volatile spinlock_data_t *sd);
* memory.
*/
SPINLOCK_INLINE
void
spinlock_data_set(volatile spinlock_data_t *sd, unsigned val)
{
*sd = val;
void spinlock_data_set(volatile spinlock_data_t *sd, unsigned val) {
*sd = val;
}
/*
@ -66,11 +63,7 @@ spinlock_data_set(volatile spinlock_data_t *sd, unsigned val)
* instruction, and instructions are atomic with respect to memory.
*/
SPINLOCK_INLINE
spinlock_data_t
spinlock_data_get(volatile spinlock_data_t *sd)
{
return *sd;
}
spinlock_data_t spinlock_data_get(volatile spinlock_data_t *sd) { return *sd; }
/*
* Test-and-set a spinlock_data_t. Use the LL/SC instructions to
@ -86,37 +79,34 @@ spinlock_data_get(volatile spinlock_data_t *sd)
* to atomically update one machine word.
*/
SPINLOCK_INLINE
spinlock_data_t
spinlock_data_testandset(volatile spinlock_data_t *sd)
{
spinlock_data_t x;
spinlock_data_t y;
spinlock_data_t spinlock_data_testandset(volatile spinlock_data_t *sd) {
spinlock_data_t x;
spinlock_data_t y;
/*
* Test-and-set using LL/SC.
*
* Load the existing value into X, and use Y to store 1.
* After the SC, Y contains 1 if the store succeeded,
* 0 if it failed.
*
* On failure, return 1 to pretend that the spinlock
* was already held.
*/
/*
* Test-and-set using LL/SC.
*
* Load the existing value into X, and use Y to store 1.
* After the SC, Y contains 1 if the store succeeded,
* 0 if it failed.
*
* On failure, return 1 to pretend that the spinlock
* was already held.
*/
y = 1;
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"ll %0, 0(%2);" /* x = *sd */
"sc %1, 0(%2);" /* *sd = y; y = success? */
".set pop" /* restore assembler mode */
: "=&r" (x), "+r" (y) : "r" (sd));
if (y == 0) {
return 1;
}
return x;
y = 1;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"ll %0, 0(%2);" /* x = *sd */
"sc %1, 0(%2);" /* *sd = y; y = success? */
".set pop" /* restore assembler mode */
: "=&r"(x), "+r"(y)
: "r"(sd));
if (y == 0) {
return 1;
}
return x;
}
#endif /* _MIPS_SPINLOCK_H_ */

View File

@ -30,7 +30,6 @@
#ifndef _MIPS_THREAD_H_
#define _MIPS_THREAD_H_
/*
* Machine-dependent thread bits.
*/
@ -40,9 +39,8 @@
typedef void (*badfaultfunc_t)(void);
struct thread_machdep {
badfaultfunc_t tm_badfaultfunc; /* fault hook used by copyin/out */
jmp_buf tm_copyjmp; /* longjmp area used by copyin/out */
badfaultfunc_t tm_badfaultfunc; /* fault hook used by copyin/out */
jmp_buf tm_copyjmp; /* longjmp area used by copyin/out */
};
#endif /* _MIPS_THREAD_H_ */

View File

@ -77,14 +77,14 @@ int tlb_probe(uint32_t entryhi, uint32_t entrylo);
*/
/* Fields in the high-order word */
#define TLBHI_VPAGE 0xfffff000
#define TLBHI_VPAGE 0xfffff000
/* TLBHI_PID 0x00000fc0 */
/* Fields in the low-order word */
#define TLBLO_PPAGE 0xfffff000
#define TLBLO_PPAGE 0xfffff000
#define TLBLO_NOCACHE 0x00000800
#define TLBLO_DIRTY 0x00000400
#define TLBLO_VALID 0x00000200
#define TLBLO_DIRTY 0x00000400
#define TLBLO_VALID 0x00000200
/* TLBLO_GLOBAL 0x00000100 */
/*
@ -92,14 +92,13 @@ int tlb_probe(uint32_t entryhi, uint32_t entrylo);
* be passed to TLBHI_INVALID; this prevents loading the same invalid
* entry into multiple TLB slots.
*/
#define TLBHI_INVALID(entryno) ((0x80000+(entryno))<<12)
#define TLBLO_INVALID() (0)
#define TLBHI_INVALID(entryno) ((0x80000 + (entryno)) << 12)
#define TLBLO_INVALID() (0)
/*
* Number of TLB entries in the processor.
*/
#define NUM_TLB 64
#define NUM_TLB 64
#endif /* _MIPS_TLB_H_ */

View File

@ -38,59 +38,59 @@
*/
struct trapframe {
uint32_t tf_vaddr; /* coprocessor 0 vaddr register */
uint32_t tf_status; /* coprocessor 0 status register */
uint32_t tf_cause; /* coprocessor 0 cause register */
uint32_t tf_lo;
uint32_t tf_hi;
uint32_t tf_ra; /* Saved register 31 */
uint32_t tf_at; /* Saved register 1 (AT) */
uint32_t tf_v0; /* Saved register 2 (v0) */
uint32_t tf_v1; /* etc. */
uint32_t tf_a0;
uint32_t tf_a1;
uint32_t tf_a2;
uint32_t tf_a3;
uint32_t tf_t0;
uint32_t tf_t1;
uint32_t tf_t2;
uint32_t tf_t3;
uint32_t tf_t4;
uint32_t tf_t5;
uint32_t tf_t6;
uint32_t tf_t7;
uint32_t tf_s0;
uint32_t tf_s1;
uint32_t tf_s2;
uint32_t tf_s3;
uint32_t tf_s4;
uint32_t tf_s5;
uint32_t tf_s6;
uint32_t tf_s7;
uint32_t tf_t8;
uint32_t tf_t9;
uint32_t tf_gp;
uint32_t tf_sp;
uint32_t tf_s8;
uint32_t tf_epc; /* coprocessor 0 epc register */
uint32_t tf_vaddr; /* coprocessor 0 vaddr register */
uint32_t tf_status; /* coprocessor 0 status register */
uint32_t tf_cause; /* coprocessor 0 cause register */
uint32_t tf_lo;
uint32_t tf_hi;
uint32_t tf_ra; /* Saved register 31 */
uint32_t tf_at; /* Saved register 1 (AT) */
uint32_t tf_v0; /* Saved register 2 (v0) */
uint32_t tf_v1; /* etc. */
uint32_t tf_a0;
uint32_t tf_a1;
uint32_t tf_a2;
uint32_t tf_a3;
uint32_t tf_t0;
uint32_t tf_t1;
uint32_t tf_t2;
uint32_t tf_t3;
uint32_t tf_t4;
uint32_t tf_t5;
uint32_t tf_t6;
uint32_t tf_t7;
uint32_t tf_s0;
uint32_t tf_s1;
uint32_t tf_s2;
uint32_t tf_s3;
uint32_t tf_s4;
uint32_t tf_s5;
uint32_t tf_s6;
uint32_t tf_s7;
uint32_t tf_t8;
uint32_t tf_t9;
uint32_t tf_gp;
uint32_t tf_sp;
uint32_t tf_s8;
uint32_t tf_epc; /* coprocessor 0 epc register */
};
/*
* MIPS exception codes.
*/
#define EX_IRQ 0 /* Interrupt */
#define EX_MOD 1 /* TLB Modify (write to read-only page) */
#define EX_TLBL 2 /* TLB miss on load */
#define EX_TLBS 3 /* TLB miss on store */
#define EX_ADEL 4 /* Address error on load */
#define EX_ADES 5 /* Address error on store */
#define EX_IBE 6 /* Bus error on instruction fetch */
#define EX_DBE 7 /* Bus error on data load *or* store */
#define EX_SYS 8 /* Syscall */
#define EX_BP 9 /* Breakpoint */
#define EX_RI 10 /* Reserved (illegal) instruction */
#define EX_CPU 11 /* Coprocessor unusable */
#define EX_OVF 12 /* Arithmetic overflow */
#define EX_IRQ 0 /* Interrupt */
#define EX_MOD 1 /* TLB Modify (write to read-only page) */
#define EX_TLBL 2 /* TLB miss on load */
#define EX_TLBS 3 /* TLB miss on store */
#define EX_ADEL 4 /* Address error on load */
#define EX_ADES 5 /* Address error on store */
#define EX_IBE 6 /* Bus error on instruction fetch */
#define EX_DBE 7 /* Bus error on data load *or* store */
#define EX_SYS 8 /* Syscall */
#define EX_BP 9 /* Breakpoint */
#define EX_RI 10 /* Reserved (illegal) instruction */
#define EX_CPU 11 /* Coprocessor unusable */
#define EX_OVF 12 /* Arithmetic overflow */
/*
* Function to enter user mode. Does not return. The trapframe must
@ -104,5 +104,4 @@ __DEAD void mips_usermode(struct trapframe *tf);
extern vaddr_t cpustacks[];
extern vaddr_t cputhreads[];
#endif /* _MIPS_TRAPFRAME_H_ */

View File

@ -30,13 +30,12 @@
#ifndef _MIPS_VM_H_
#define _MIPS_VM_H_
/*
* Machine-dependent VM system definitions.
*/
#define PAGE_SIZE 4096 /* size of VM page */
#define PAGE_FRAME 0xfffff000 /* mask for getting page number from addr */
#define PAGE_SIZE 4096 /* size of VM page */
#define PAGE_FRAME 0xfffff000 /* mask for getting page number from addr */
/*
* MIPS-I hardwired memory layout:
@ -48,10 +47,10 @@
* (mips32 is a little different)
*/
#define MIPS_KUSEG 0x00000000
#define MIPS_KSEG0 0x80000000
#define MIPS_KSEG1 0xa0000000
#define MIPS_KSEG2 0xc0000000
#define MIPS_KUSEG 0x00000000
#define MIPS_KSEG0 0x80000000
#define MIPS_KSEG1 0xa0000000
#define MIPS_KSEG2 0xc0000000
/*
* The first 512 megs of physical space can be addressed in both kseg0 and
@ -65,13 +64,13 @@
* exception handler code) when converted to a vaddr it's *not* NULL, *is*
* a valid address, and will make a *huge* mess if you scribble on it.
*/
#define PADDR_TO_KVADDR(paddr) ((paddr)+MIPS_KSEG0)
#define PADDR_TO_KVADDR(paddr) ((paddr) + MIPS_KSEG0)
/*
* The top of user space. (Actually, the address immediately above the
* last valid user address.)
*/
#define USERSPACETOP MIPS_KSEG0
#define USERSPACETOP MIPS_KSEG0
/*
* The starting value for the stack pointer at user level. Because
@ -81,7 +80,7 @@
* We put the stack at the very top of user virtual memory because it
* grows downwards.
*/
#define USERSTACK USERSPACETOP
#define USERSTACK USERSPACETOP
/*
* Interface to the low-level module that looks after the amount of
@ -117,13 +116,12 @@ paddr_t ram_getfirstfree(void);
*/
struct tlbshootdown {
/*
* Change this to what you need for your VM design.
*/
int ts_placeholder;
/*
* Change this to what you need for your VM design.
*/
int ts_placeholder;
};
#define TLBSHOOTDOWN_MAX 16
#endif /* _MIPS_VM_H_ */

View File

@ -40,81 +40,68 @@
#include <mainbus.h>
#include <syscall.h>
/* in exception-*.S */
extern __DEAD void asm_usermode(struct trapframe *tf);
/* called only from assembler, so not declared in a header */
void mips_trap(struct trapframe *tf);
/* Names for trap codes */
#define NTRAPCODES 13
static const char *const trapcodenames[NTRAPCODES] = {
"Interrupt",
"TLB modify trap",
"TLB miss on load",
"TLB miss on store",
"Address error on load",
"Address error on store",
"Bus error on code",
"Bus error on data",
"System call",
"Break instruction",
"Illegal instruction",
"Coprocessor unusable",
"Arithmetic overflow",
"Interrupt", "TLB modify trap", "TLB miss on load",
"TLB miss on store", "Address error on load", "Address error on store",
"Bus error on code", "Bus error on data", "System call",
"Break instruction", "Illegal instruction", "Coprocessor unusable",
"Arithmetic overflow",
};
/*
* Function called when user-level code hits a fatal fault.
*/
static
void
kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
{
int sig = 0;
static void kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr) {
int sig = 0;
KASSERT(code < NTRAPCODES);
switch (code) {
case EX_IRQ:
case EX_IBE:
case EX_DBE:
case EX_SYS:
/* should not be seen */
KASSERT(0);
sig = SIGABRT;
break;
case EX_MOD:
case EX_TLBL:
case EX_TLBS:
sig = SIGSEGV;
break;
case EX_ADEL:
case EX_ADES:
sig = SIGBUS;
break;
case EX_BP:
sig = SIGTRAP;
break;
case EX_RI:
sig = SIGILL;
break;
case EX_CPU:
sig = SIGSEGV;
break;
case EX_OVF:
sig = SIGFPE;
break;
}
KASSERT(code < NTRAPCODES);
switch (code) {
case EX_IRQ:
case EX_IBE:
case EX_DBE:
case EX_SYS:
/* should not be seen */
KASSERT(0);
sig = SIGABRT;
break;
case EX_MOD:
case EX_TLBL:
case EX_TLBS:
sig = SIGSEGV;
break;
case EX_ADEL:
case EX_ADES:
sig = SIGBUS;
break;
case EX_BP:
sig = SIGTRAP;
break;
case EX_RI:
sig = SIGILL;
break;
case EX_CPU:
sig = SIGSEGV;
break;
case EX_OVF:
sig = SIGFPE;
break;
}
/*
* You will probably want to change this.
*/
/*
* You will probably want to change this.
*/
kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n",
code, sig, trapcodenames[code], epc, vaddr);
panic("I don't know how to handle this\n");
kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n", code,
sig, trapcodenames[code], epc, vaddr);
panic("I don't know how to handle this\n");
}
/*
@ -122,229 +109,223 @@ kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
* This is called by the assembly-language exception handler once
* the trapframe has been set up.
*/
void
mips_trap(struct trapframe *tf)
{
uint32_t code;
/*bool isutlb; -- not used */
bool iskern;
int spl;
void mips_trap(struct trapframe *tf) {
uint32_t code;
/*bool isutlb; -- not used */
bool iskern;
int spl;
/* The trap frame is supposed to be 35 registers long. */
KASSERT(sizeof(struct trapframe)==(35*4));
/* The trap frame is supposed to be 35 registers long. */
KASSERT(sizeof(struct trapframe) == (35 * 4));
/*
* Extract the exception code info from the register fields.
*/
code = (tf->tf_cause & CCA_CODE) >> CCA_CODESHIFT;
/*isutlb = (tf->tf_cause & CCA_UTLB) != 0;*/
iskern = (tf->tf_status & CST_KUp) == 0;
/*
* Extract the exception code info from the register fields.
*/
code = (tf->tf_cause & CCA_CODE) >> CCA_CODESHIFT;
/*isutlb = (tf->tf_cause & CCA_UTLB) != 0;*/
iskern = (tf->tf_status & CST_KUp) == 0;
KASSERT(code < NTRAPCODES);
KASSERT(code < NTRAPCODES);
/* Make sure we haven't run off our stack */
if (curthread != NULL && curthread->t_stack != NULL) {
KASSERT((vaddr_t)tf > (vaddr_t)curthread->t_stack);
KASSERT((vaddr_t)tf < (vaddr_t)(curthread->t_stack
+ STACK_SIZE));
}
/* Make sure we haven't run off our stack */
if (curthread != NULL && curthread->t_stack != NULL) {
KASSERT((vaddr_t)tf > (vaddr_t)curthread->t_stack);
KASSERT((vaddr_t)tf < (vaddr_t)(curthread->t_stack + STACK_SIZE));
}
/* Interrupt? Call the interrupt handler and return. */
if (code == EX_IRQ) {
int old_in;
bool doadjust;
/* Interrupt? Call the interrupt handler and return. */
if (code == EX_IRQ) {
int old_in;
bool doadjust;
old_in = curthread->t_in_interrupt;
curthread->t_in_interrupt = 1;
old_in = curthread->t_in_interrupt;
curthread->t_in_interrupt = 1;
/*
* The processor has turned interrupts off; if the
* currently recorded interrupt state is interrupts on
* (spl of 0), adjust the recorded state to match, and
* restore after processing the interrupt.
*
* How can we get an interrupt if the recorded state
* is interrupts off? Well, as things currently stand
* when the CPU finishes idling it flips interrupts on
* and off to allow things to happen, but leaves
* curspl high while doing so.
*
* While we're here, assert that the interrupt
* handling code hasn't leaked a spinlock or an
* splhigh().
*/
/*
* The processor has turned interrupts off; if the
* currently recorded interrupt state is interrupts on
* (spl of 0), adjust the recorded state to match, and
* restore after processing the interrupt.
*
* How can we get an interrupt if the recorded state
* is interrupts off? Well, as things currently stand
* when the CPU finishes idling it flips interrupts on
* and off to allow things to happen, but leaves
* curspl high while doing so.
*
* While we're here, assert that the interrupt
* handling code hasn't leaked a spinlock or an
* splhigh().
*/
if (curthread->t_curspl == 0) {
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
curthread->t_curspl = IPL_HIGH;
curthread->t_iplhigh_count++;
doadjust = true;
}
else {
doadjust = false;
}
if (curthread->t_curspl == 0) {
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
curthread->t_curspl = IPL_HIGH;
curthread->t_iplhigh_count++;
doadjust = true;
} else {
doadjust = false;
}
mainbus_interrupt(tf);
mainbus_interrupt(tf);
if (doadjust) {
KASSERT(curthread->t_curspl == IPL_HIGH);
KASSERT(curthread->t_iplhigh_count == 1);
curthread->t_iplhigh_count--;
curthread->t_curspl = 0;
}
if (doadjust) {
KASSERT(curthread->t_curspl == IPL_HIGH);
KASSERT(curthread->t_iplhigh_count == 1);
curthread->t_iplhigh_count--;
curthread->t_curspl = 0;
}
curthread->t_in_interrupt = old_in;
goto done2;
}
curthread->t_in_interrupt = old_in;
goto done2;
}
/*
* The processor turned interrupts off when it took the trap.
*
* While we're in the kernel, and not actually handling an
* interrupt, restore the interrupt state to where it was in
* the previous context, which may be low (interrupts on).
*
* Do this by forcing splhigh(), which may do a redundant
* cpu_irqoff() but forces the stored MI interrupt state into
* sync, then restoring the previous state.
*/
spl = splhigh();
splx(spl);
/*
* The processor turned interrupts off when it took the trap.
*
* While we're in the kernel, and not actually handling an
* interrupt, restore the interrupt state to where it was in
* the previous context, which may be low (interrupts on).
*
* Do this by forcing splhigh(), which may do a redundant
* cpu_irqoff() but forces the stored MI interrupt state into
* sync, then restoring the previous state.
*/
spl = splhigh();
splx(spl);
/* Syscall? Call the syscall handler and return. */
if (code == EX_SYS) {
/* Interrupts should have been on while in user mode. */
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
/* Syscall? Call the syscall handler and return. */
if (code == EX_SYS) {
/* Interrupts should have been on while in user mode. */
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
DEBUG(DB_SYSCALL, "syscall: #%d, args %x %x %x %x\n",
tf->tf_v0, tf->tf_a0, tf->tf_a1, tf->tf_a2, tf->tf_a3);
DEBUG(DB_SYSCALL, "syscall: #%d, args %x %x %x %x\n", tf->tf_v0, tf->tf_a0,
tf->tf_a1, tf->tf_a2, tf->tf_a3);
syscall(tf);
goto done;
}
syscall(tf);
goto done;
}
/*
* Ok, it wasn't any of the really easy cases.
* Call vm_fault on the TLB exceptions.
* Panic on the bus error exceptions.
*/
switch (code) {
case EX_MOD:
if (vm_fault(VM_FAULT_READONLY, tf->tf_vaddr)==0) {
goto done;
}
break;
case EX_TLBL:
if (vm_fault(VM_FAULT_READ, tf->tf_vaddr)==0) {
goto done;
}
break;
case EX_TLBS:
if (vm_fault(VM_FAULT_WRITE, tf->tf_vaddr)==0) {
goto done;
}
break;
case EX_IBE:
case EX_DBE:
/*
* This means you loaded invalid TLB entries, or
* touched invalid parts of the direct-mapped
* segments. These are serious kernel errors, so
* panic.
*
* The MIPS won't even tell you what invalid address
* caused the bus error.
*/
panic("Bus error exception, PC=0x%x\n", tf->tf_epc);
break;
}
/*
* Ok, it wasn't any of the really easy cases.
* Call vm_fault on the TLB exceptions.
* Panic on the bus error exceptions.
*/
switch (code) {
case EX_MOD:
if (vm_fault(VM_FAULT_READONLY, tf->tf_vaddr) == 0) {
goto done;
}
break;
case EX_TLBL:
if (vm_fault(VM_FAULT_READ, tf->tf_vaddr) == 0) {
goto done;
}
break;
case EX_TLBS:
if (vm_fault(VM_FAULT_WRITE, tf->tf_vaddr) == 0) {
goto done;
}
break;
case EX_IBE:
case EX_DBE:
/*
* This means you loaded invalid TLB entries, or
* touched invalid parts of the direct-mapped
* segments. These are serious kernel errors, so
* panic.
*
* The MIPS won't even tell you what invalid address
* caused the bus error.
*/
panic("Bus error exception, PC=0x%x\n", tf->tf_epc);
break;
}
/*
* If we get to this point, it's a fatal fault - either it's
* one of the other exceptions, like illegal instruction, or
* it was a page fault we couldn't handle.
*/
/*
* If we get to this point, it's a fatal fault - either it's
* one of the other exceptions, like illegal instruction, or
* it was a page fault we couldn't handle.
*/
if (!iskern) {
/*
* Fatal fault in user mode.
* Kill the current user process.
*/
kill_curthread(tf->tf_epc, code, tf->tf_vaddr);
goto done;
}
if (!iskern) {
/*
* Fatal fault in user mode.
* Kill the current user process.
*/
kill_curthread(tf->tf_epc, code, tf->tf_vaddr);
goto done;
}
/*
* Fatal fault in kernel mode.
*
* If pcb_badfaultfunc is set, we do not panic; badfaultfunc is
* set by copyin/copyout and related functions to signify that
* the addresses they're accessing are userlevel-supplied and
* not trustable. What we actually want to do is resume
* execution at the function pointed to by badfaultfunc. That's
* going to be "copyfail" (see copyinout.c), which longjmps
* back to copyin/copyout or wherever and returns EFAULT.
*
* Note that we do not just *call* this function, because that
* won't necessarily do anything. We want the control flow
* that is currently executing in copyin (or whichever), and
* is stopped while we process the exception, to *teleport* to
* copyfail.
*
* This is accomplished by changing tf->tf_epc and returning
* from the exception handler.
*/
/*
* Fatal fault in kernel mode.
*
* If pcb_badfaultfunc is set, we do not panic; badfaultfunc is
* set by copyin/copyout and related functions to signify that
* the addresses they're accessing are userlevel-supplied and
* not trustable. What we actually want to do is resume
* execution at the function pointed to by badfaultfunc. That's
* going to be "copyfail" (see copyinout.c), which longjmps
* back to copyin/copyout or wherever and returns EFAULT.
*
* Note that we do not just *call* this function, because that
* won't necessarily do anything. We want the control flow
* that is currently executing in copyin (or whichever), and
* is stopped while we process the exception, to *teleport* to
* copyfail.
*
* This is accomplished by changing tf->tf_epc and returning
* from the exception handler.
*/
if (curthread != NULL &&
curthread->t_machdep.tm_badfaultfunc != NULL) {
tf->tf_epc = (vaddr_t) curthread->t_machdep.tm_badfaultfunc;
goto done;
}
if (curthread != NULL && curthread->t_machdep.tm_badfaultfunc != NULL) {
tf->tf_epc = (vaddr_t)curthread->t_machdep.tm_badfaultfunc;
goto done;
}
/*
* Really fatal kernel-mode fault.
*/
/*
* Really fatal kernel-mode fault.
*/
kprintf("panic: Fatal exception %u (%s) in kernel mode\n", code,
trapcodenames[code]);
kprintf("panic: EPC 0x%x, exception vaddr 0x%x\n",
tf->tf_epc, tf->tf_vaddr);
kprintf("panic: Fatal exception %u (%s) in kernel mode\n", code,
trapcodenames[code]);
kprintf("panic: EPC 0x%x, exception vaddr 0x%x\n", tf->tf_epc, tf->tf_vaddr);
panic("I can't handle this... I think I'll just die now...\n");
panic("I can't handle this... I think I'll just die now...\n");
done:
/*
* Turn interrupts off on the processor, without affecting the
* stored interrupt state.
*/
cpu_irqoff();
done2:
done:
/*
* Turn interrupts off on the processor, without affecting the
* stored interrupt state.
*/
cpu_irqoff();
done2:
/*
* The boot thread can get here (e.g. on interrupt return) but
* since it doesn't go to userlevel, it can't be returning to
* userlevel, so there's no need to set cputhreads[] and
* cpustacks[]. Just return.
*/
if (curthread->t_stack == NULL) {
return;
}
/*
* The boot thread can get here (e.g. on interrupt return) but
* since it doesn't go to userlevel, it can't be returning to
* userlevel, so there's no need to set cputhreads[] and
* cpustacks[]. Just return.
*/
if (curthread->t_stack == NULL) {
return;
}
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
/*
* This assertion will fail if either
* (1) curthread->t_stack is corrupted, or
* (2) the trap frame is somehow on the wrong kernel stack.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
/*
* This assertion will fail if either
* (1) curthread->t_stack is corrupted, or
* (2) the trap frame is somehow on the wrong kernel stack.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number] - 1, (vaddr_t)tf));
}
/*
@ -364,43 +345,41 @@ mips_trap(struct trapframe *tf)
* - enter_new_process, for use by exec and equivalent.
* - enter_forked_process, in syscall.c, for use by fork.
*/
void
mips_usermode(struct trapframe *tf)
{
void mips_usermode(struct trapframe *tf) {
/*
* Interrupts should be off within the kernel while entering
* user mode. However, while in user mode, interrupts should
* be on. To interact properly with the spl-handling logic
* above, we explicitly call spl0() and then call cpu_irqoff().
*/
spl0();
cpu_irqoff();
/*
* Interrupts should be off within the kernel while entering
* user mode. However, while in user mode, interrupts should
* be on. To interact properly with the spl-handling logic
* above, we explicitly call spl0() and then call cpu_irqoff().
*/
spl0();
cpu_irqoff();
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
/*
* This assertion will fail if either
* (1) cpustacks[] is corrupted, or
* (2) the trap frame is not on our own kernel stack, or
* (3) the boot thread tries to enter user mode.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*
* It's necessary for the trap frame used here to be on the
* current thread's own stack. It cannot correctly be on
* either another thread's stack or in the kernel heap.
* (Exercise: why?)
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
/*
* This assertion will fail if either
* (1) cpustacks[] is corrupted, or
* (2) the trap frame is not on our own kernel stack, or
* (3) the boot thread tries to enter user mode.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*
* It's necessary for the trap frame used here to be on the
* current thread's own stack. It cannot correctly be on
* either another thread's stack or in the kernel heap.
* (Exercise: why?)
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number] - 1, (vaddr_t)tf));
/*
* This actually does it. See exception-*.S.
*/
asm_usermode(tf);
/*
* This actually does it. See exception-*.S.
*/
asm_usermode(tf);
}
/*
@ -419,20 +398,18 @@ mips_usermode(struct trapframe *tf)
*
* Works by creating an ersatz trapframe.
*/
void
enter_new_process(int argc, userptr_t argv, userptr_t env,
vaddr_t stack, vaddr_t entry)
{
struct trapframe tf;
void enter_new_process(int argc, userptr_t argv, userptr_t env, vaddr_t stack,
vaddr_t entry) {
struct trapframe tf;
bzero(&tf, sizeof(tf));
bzero(&tf, sizeof(tf));
tf.tf_status = CST_IRQMASK | CST_IEp | CST_KUp;
tf.tf_epc = entry;
tf.tf_a0 = argc;
tf.tf_a1 = (vaddr_t)argv;
tf.tf_a2 = (vaddr_t)env;
tf.tf_sp = stack;
tf.tf_status = CST_IRQMASK | CST_IEp | CST_KUp;
tf.tf_epc = entry;
tf.tf_a0 = argc;
tf.tf_a1 = (vaddr_t)argv;
tf.tf_a2 = (vaddr_t)env;
tf.tf_sp = stack;
mips_usermode(&tf);
mips_usermode(&tf);
}

View File

@ -36,7 +36,6 @@
#include <current.h>
#include <syscall.h>
/*
* System call dispatcher.
*
@ -75,75 +74,70 @@
* stack, starting at sp+16 to skip over the slots for the
* registerized values, with copyin().
*/
void
syscall(struct trapframe *tf)
{
int callno;
int32_t retval;
int err;
void syscall(struct trapframe *tf) {
int callno;
int32_t retval;
int err;
KASSERT(curthread != NULL);
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
KASSERT(curthread != NULL);
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
callno = tf->tf_v0;
callno = tf->tf_v0;
/*
* Initialize retval to 0. Many of the system calls don't
* really return a value, just 0 for success and -1 on
* error. Since retval is the value returned on success,
* initialize it to 0 by default; thus it's not necessary to
* deal with it except for calls that return other values,
* like write.
*/
/*
* Initialize retval to 0. Many of the system calls don't
* really return a value, just 0 for success and -1 on
* error. Since retval is the value returned on success,
* initialize it to 0 by default; thus it's not necessary to
* deal with it except for calls that return other values,
* like write.
*/
retval = 0;
retval = 0;
switch (callno) {
case SYS_reboot:
err = sys_reboot(tf->tf_a0);
break;
switch (callno) {
case SYS_reboot:
err = sys_reboot(tf->tf_a0);
break;
case SYS___time:
err = sys___time((userptr_t)tf->tf_a0,
(userptr_t)tf->tf_a1);
break;
case SYS___time:
err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1);
break;
/* Add stuff here */
/* Add stuff here */
default:
kprintf("Unknown syscall %d\n", callno);
err = ENOSYS;
break;
}
default:
kprintf("Unknown syscall %d\n", callno);
err = ENOSYS;
break;
}
if (err) {
/*
* Return the error code. This gets converted at
* userlevel to a return value of -1 and the error
* code in errno.
*/
tf->tf_v0 = err;
tf->tf_a3 = 1; /* signal an error */
} else {
/* Success. */
tf->tf_v0 = retval;
tf->tf_a3 = 0; /* signal no error */
}
if (err) {
/*
* Return the error code. This gets converted at
* userlevel to a return value of -1 and the error
* code in errno.
*/
tf->tf_v0 = err;
tf->tf_a3 = 1; /* signal an error */
}
else {
/* Success. */
tf->tf_v0 = retval;
tf->tf_a3 = 0; /* signal no error */
}
/*
* Now, advance the program counter, to avoid restarting
* the syscall over and over again.
*/
/*
* Now, advance the program counter, to avoid restarting
* the syscall over and over again.
*/
tf->tf_epc += 4;
tf->tf_epc += 4;
/* Make sure the syscall code didn't forget to lower spl */
KASSERT(curthread->t_curspl == 0);
/* ...or leak any spinlocks */
KASSERT(curthread->t_iplhigh_count == 0);
/* Make sure the syscall code didn't forget to lower spl */
KASSERT(curthread->t_curspl == 0);
/* ...or leak any spinlocks */
KASSERT(curthread->t_iplhigh_count == 0);
}
/*
@ -154,8 +148,4 @@ syscall(struct trapframe *tf)
*
* Thus, you can trash it and do things another way if you prefer.
*/
void
enter_forked_process(struct trapframe *tf)
{
(void)tf;
}
void enter_forked_process(struct trapframe *tf) { (void)tf; }

View File

@ -72,30 +72,27 @@ vaddr_t cputhreads[MAXCPUS];
* associated with a new cpu. Note that we're not running on the new
* cpu when this is called.
*/
void
cpu_machdep_init(struct cpu *c)
{
vaddr_t stackpointer;
void cpu_machdep_init(struct cpu *c) {
vaddr_t stackpointer;
KASSERT(c->c_number < MAXCPUS);
KASSERT(c->c_number < MAXCPUS);
if (c->c_curthread->t_stack == NULL) {
/* boot cpu; don't need to do anything here */
}
else {
/*
* Stick the stack in cpustacks[], and thread pointer
* in cputhreads[].
*/
if (c->c_curthread->t_stack == NULL) {
/* boot cpu; don't need to do anything here */
} else {
/*
* Stick the stack in cpustacks[], and thread pointer
* in cputhreads[].
*/
/* stack base address */
stackpointer = (vaddr_t) c->c_curthread->t_stack;
/* since stacks grow down, get the top */
stackpointer += STACK_SIZE;
/* stack base address */
stackpointer = (vaddr_t)c->c_curthread->t_stack;
/* since stacks grow down, get the top */
stackpointer += STACK_SIZE;
cpustacks[c->c_number] = stackpointer;
cputhreads[c->c_number] = (vaddr_t)c->c_curthread;
}
cpustacks[c->c_number] = stackpointer;
cputhreads[c->c_number] = (vaddr_t)c->c_curthread;
}
}
////////////////////////////////////////////////////////////
@ -107,73 +104,61 @@ cpu_machdep_init(struct cpu *c)
* System/161 processor-ID values.
*/
#define SYS161_PRID_ORIG 0x000003ff
#define SYS161_PRID_2X 0x000000a1
#define SYS161_PRID_ORIG 0x000003ff
#define SYS161_PRID_2X 0x000000a1
static inline
uint32_t
cpu_getprid(void)
{
uint32_t prid;
static inline uint32_t cpu_getprid(void) {
uint32_t prid;
__asm volatile("mfc0 %0,$15" : "=r" (prid));
return prid;
__asm volatile("mfc0 %0,$15" : "=r"(prid));
return prid;
}
static inline
uint32_t
cpu_getfeatures(void)
{
uint32_t features;
static inline uint32_t cpu_getfeatures(void) {
uint32_t features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,1;" /* get cop0 reg 15 sel 1 */
".set pop" /* restore assembler mode */
: "=r" (features));
return features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,1;" /* get cop0 reg 15 sel 1 */
".set pop" /* restore assembler mode */
: "=r"(features));
return features;
}
static inline
uint32_t
cpu_getifeatures(void)
{
uint32_t features;
static inline uint32_t cpu_getifeatures(void) {
uint32_t features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,2;" /* get cop0 reg 15 sel 2 */
".set pop" /* restore assembler mode */
: "=r" (features));
return features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,2;" /* get cop0 reg 15 sel 2 */
".set pop" /* restore assembler mode */
: "=r"(features));
return features;
}
void
cpu_identify(char *buf, size_t max)
{
uint32_t prid;
uint32_t features;
void cpu_identify(char *buf, size_t max) {
uint32_t prid;
uint32_t features;
prid = cpu_getprid();
switch (prid) {
case SYS161_PRID_ORIG:
snprintf(buf, max, "MIPS/161 (System/161 1.x and pre-2.x)");
break;
case SYS161_PRID_2X:
features = cpu_getfeatures();
snprintf(buf, max, "MIPS/161 (System/161 2.x) features 0x%x",
features);
features = cpu_getifeatures();
if (features != 0) {
kprintf("WARNING: unknown CPU incompatible features "
"0x%x\n", features);
}
break;
default:
snprintf(buf, max, "32-bit MIPS (unknown type, CPU ID 0x%x)",
prid);
break;
}
prid = cpu_getprid();
switch (prid) {
case SYS161_PRID_ORIG:
snprintf(buf, max, "MIPS/161 (System/161 1.x and pre-2.x)");
break;
case SYS161_PRID_2X:
features = cpu_getfeatures();
snprintf(buf, max, "MIPS/161 (System/161 2.x) features 0x%x", features);
features = cpu_getifeatures();
if (features != 0) {
kprintf("WARNING: unknown CPU incompatible features "
"0x%x\n",
features);
}
break;
default:
snprintf(buf, max, "32-bit MIPS (unknown type, CPU ID 0x%x)", prid);
break;
}
}
////////////////////////////////////////////////////////////
@ -200,50 +185,43 @@ cpu_identify(char *buf, size_t max)
* These considerations do not (currently) apply to System/161,
* however.
*/
#define GET_STATUS(x) __asm volatile("mfc0 %0,$12" : "=r" (x))
#define SET_STATUS(x) __asm volatile("mtc0 %0,$12" :: "r" (x))
#define GET_STATUS(x) __asm volatile("mfc0 %0,$12" : "=r"(x))
#define SET_STATUS(x) __asm volatile("mtc0 %0,$12" ::"r"(x))
/*
* Interrupts on.
*/
void
cpu_irqon(void)
{
uint32_t x;
void cpu_irqon(void) {
uint32_t x;
GET_STATUS(x);
x |= CST_IEc;
SET_STATUS(x);
GET_STATUS(x);
x |= CST_IEc;
SET_STATUS(x);
}
/*
* Interrupts off.
*/
void
cpu_irqoff(void)
{
uint32_t x;
void cpu_irqoff(void) {
uint32_t x;
GET_STATUS(x);
x &= ~(uint32_t)CST_IEc;
SET_STATUS(x);
GET_STATUS(x);
x &= ~(uint32_t)CST_IEc;
SET_STATUS(x);
}
/*
* Used below.
*/
static
void
cpu_irqonoff(void)
{
uint32_t x, xon, xoff;
static void cpu_irqonoff(void) {
uint32_t x, xon, xoff;
GET_STATUS(x);
xon = x | CST_IEc;
xoff = x & ~(uint32_t)CST_IEc;
SET_STATUS(xon);
__asm volatile("nop; nop; nop; nop");
SET_STATUS(xoff);
GET_STATUS(x);
xon = x | CST_IEc;
xoff = x & ~(uint32_t)CST_IEc;
SET_STATUS(xon);
__asm volatile("nop; nop; nop; nop");
SET_STATUS(xoff);
}
////////////////////////////////////////////////////////////
@ -261,49 +239,40 @@ cpu_irqonoff(void)
* appropriate the mips32 WAIT instruction.
*/
static
inline
void
wait(void)
{
/*
* The WAIT instruction goes into powersave mode until an
* interrupt is trying to occur.
*
* Then switch interrupts on and off again, so we actually
* take the interrupt.
*
* Note that the precise behavior of this instruction in the
* System/161 simulator is partly guesswork. This code may not
* work on a real mips.
*/
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"wait;" /* suspend until interrupted */
".set pop" /* restore assembler mode */
);
static inline void wait(void) {
/*
* The WAIT instruction goes into powersave mode until an
* interrupt is trying to occur.
*
* Then switch interrupts on and off again, so we actually
* take the interrupt.
*
* Note that the precise behavior of this instruction in the
* System/161 simulator is partly guesswork. This code may not
* work on a real mips.
*/
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"wait;" /* suspend until interrupted */
".set pop" /* restore assembler mode */
);
}
/*
* Idle the processor until something happens.
*/
void
cpu_idle(void)
{
wait();
cpu_irqonoff();
void cpu_idle(void) {
wait();
cpu_irqonoff();
}
/*
* Halt the CPU permanently.
*/
void
cpu_halt(void)
{
cpu_irqoff();
while (1) {
wait();
}
void cpu_halt(void) {
cpu_irqoff();
while (1) {
wait();
}
}

View File

@ -37,7 +37,6 @@
/* in threadstart.S */
extern void mips_threadstart(/* arguments are in unusual registers */);
/*
* Function to initialize the switchframe of a new thread, which is
* *not* the one that is currently running.
@ -51,48 +50,46 @@ extern void mips_threadstart(/* arguments are in unusual registers */);
* store the arguments in the s* registers, and use a bit of asm
* (mips_threadstart) to move them and then jump to thread_startup.
*/
void
switchframe_init(struct thread *thread,
void (*entrypoint)(void *data1, unsigned long data2),
void *data1, unsigned long data2)
{
vaddr_t stacktop;
struct switchframe *sf;
void switchframe_init(struct thread *thread,
void (*entrypoint)(void *data1, unsigned long data2),
void *data1, unsigned long data2) {
vaddr_t stacktop;
struct switchframe *sf;
/*
* MIPS stacks grow down. t_stack is just a hunk of memory, so
* get the other end of it. Then set up a switchframe on the
* top of the stack.
*/
stacktop = ((vaddr_t)thread->t_stack) + STACK_SIZE;
sf = ((struct switchframe *) stacktop) - 1;
/*
* MIPS stacks grow down. t_stack is just a hunk of memory, so
* get the other end of it. Then set up a switchframe on the
* top of the stack.
*/
stacktop = ((vaddr_t)thread->t_stack) + STACK_SIZE;
sf = ((struct switchframe *)stacktop) - 1;
/* Zero out the switchframe. */
bzero(sf, sizeof(*sf));
/* Zero out the switchframe. */
bzero(sf, sizeof(*sf));
/*
* Now set the important parts: pass through the three arguments,
* and set the return address register to the place we want
* execution to begin.
*
* Thus, when switchframe_switch does its "j ra", it will
* actually jump to mips_threadstart, which will move the
* arguments into the right register and jump to
* thread_startup().
*
* Note that this means that when we call switchframe_switch()
* in thread_switch(), we may not come back out the same way
* in the next thread. (Though we will come back out the same
* way when we later come back to the same thread again.)
*
* This has implications for code at the bottom of
* thread_switch, described in thread.c.
*/
sf->sf_s0 = (uint32_t)entrypoint;
sf->sf_s1 = (uint32_t)data1;
sf->sf_s2 = (uint32_t)data2;
sf->sf_ra = (uint32_t)mips_threadstart;
/*
* Now set the important parts: pass through the three arguments,
* and set the return address register to the place we want
* execution to begin.
*
* Thus, when switchframe_switch does its "j ra", it will
* actually jump to mips_threadstart, which will move the
* arguments into the right register and jump to
* thread_startup().
*
* Note that this means that when we call switchframe_switch()
* in thread_switch(), we may not come back out the same way
* in the next thread. (Though we will come back out the same
* way when we later come back to the same thread again.)
*
* This has implications for code at the bottom of
* thread_switch, described in thread.c.
*/
sf->sf_s0 = (uint32_t)entrypoint;
sf->sf_s1 = (uint32_t)data1;
sf->sf_s2 = (uint32_t)data2;
sf->sf_ra = (uint32_t)mips_threadstart;
/* Set ->t_context, and we're done. */
thread->t_context = sf;
/* Set ->t_context, and we're done. */
thread->t_context = sf;
}

View File

@ -37,16 +37,16 @@
*/
struct switchframe {
uint32_t sf_s0;
uint32_t sf_s1;
uint32_t sf_s2;
uint32_t sf_s3;
uint32_t sf_s4;
uint32_t sf_s5;
uint32_t sf_s6;
uint32_t sf_s8;
uint32_t sf_gp;
uint32_t sf_ra;
uint32_t sf_s0;
uint32_t sf_s1;
uint32_t sf_s2;
uint32_t sf_s3;
uint32_t sf_s4;
uint32_t sf_s5;
uint32_t sf_s6;
uint32_t sf_s8;
uint32_t sf_gp;
uint32_t sf_ra;
};
#endif /* _MIPS_SWITCHFRAME_H_ */

View File

@ -36,14 +36,10 @@
#include <thread.h>
#include <threadprivate.h>
void
thread_machdep_init(struct thread_machdep *tm)
{
tm->tm_badfaultfunc = NULL;
void thread_machdep_init(struct thread_machdep *tm) {
tm->tm_badfaultfunc = NULL;
}
void
thread_machdep_cleanup(struct thread_machdep *tm)
{
KASSERT(tm->tm_badfaultfunc == NULL);
void thread_machdep_cleanup(struct thread_machdep *tm) {
KASSERT(tm->tm_badfaultfunc == NULL);
}

View File

@ -57,18 +57,14 @@
/* under dumbvm, always have 72k of user stack */
/* (this must be > 64K so argument blocks of size ARG_MAX will fit) */
#define DUMBVM_STACKPAGES 18
#define DUMBVM_STACKPAGES 18
/*
* Wrap ram_stealmem in a spinlock.
*/
static struct spinlock stealmem_lock = SPINLOCK_INITIALIZER;
void
vm_bootstrap(void)
{
/* Do nothing. */
}
void vm_bootstrap(void) { /* Do nothing. */ }
/*
* Check if we're in a context that can sleep. While most of the
@ -77,351 +73,311 @@ vm_bootstrap(void)
* avoid the situation where syscall-layer code that works ok with
* dumbvm starts blowing up during the VM assignment.
*/
static
void
dumbvm_can_sleep(void)
{
if (CURCPU_EXISTS()) {
/* must not hold spinlocks */
KASSERT(curcpu->c_spinlocks == 0);
static void dumbvm_can_sleep(void) {
if (CURCPU_EXISTS()) {
/* must not hold spinlocks */
KASSERT(curcpu->c_spinlocks == 0);
/* must not be in an interrupt handler */
KASSERT(curthread->t_in_interrupt == 0);
}
/* must not be in an interrupt handler */
KASSERT(curthread->t_in_interrupt == 0);
}
}
static
paddr_t
getppages(unsigned long npages)
{
paddr_t addr;
static paddr_t getppages(unsigned long npages) {
paddr_t addr;
spinlock_acquire(&stealmem_lock);
spinlock_acquire(&stealmem_lock);
addr = ram_stealmem(npages);
addr = ram_stealmem(npages);
spinlock_release(&stealmem_lock);
return addr;
spinlock_release(&stealmem_lock);
return addr;
}
/* Allocate/free some kernel-space virtual pages */
vaddr_t
alloc_kpages(unsigned npages)
{
paddr_t pa;
vaddr_t alloc_kpages(unsigned npages) {
paddr_t pa;
dumbvm_can_sleep();
pa = getppages(npages);
if (pa==0) {
return 0;
}
return PADDR_TO_KVADDR(pa);
dumbvm_can_sleep();
pa = getppages(npages);
if (pa == 0) {
return 0;
}
return PADDR_TO_KVADDR(pa);
}
void
free_kpages(vaddr_t addr)
{
/* nothing - leak the memory. */
void free_kpages(vaddr_t addr) {
/* nothing - leak the memory. */
(void)addr;
(void)addr;
}
void
vm_tlbshootdown(const struct tlbshootdown *ts)
{
(void)ts;
panic("dumbvm tried to do tlb shootdown?!\n");
void vm_tlbshootdown(const struct tlbshootdown *ts) {
(void)ts;
panic("dumbvm tried to do tlb shootdown?!\n");
}
int
vm_fault(int faulttype, vaddr_t faultaddress)
{
vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
paddr_t paddr;
int i;
uint32_t ehi, elo;
struct addrspace *as;
int spl;
int vm_fault(int faulttype, vaddr_t faultaddress) {
vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
paddr_t paddr;
int i;
uint32_t ehi, elo;
struct addrspace *as;
int spl;
faultaddress &= PAGE_FRAME;
faultaddress &= PAGE_FRAME;
DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
switch (faulttype) {
case VM_FAULT_READONLY:
/* We always create pages read-write, so we can't get this */
panic("dumbvm: got VM_FAULT_READONLY\n");
case VM_FAULT_READ:
case VM_FAULT_WRITE:
break;
default:
return EINVAL;
}
switch (faulttype) {
case VM_FAULT_READONLY:
/* We always create pages read-write, so we can't get this */
panic("dumbvm: got VM_FAULT_READONLY\n");
case VM_FAULT_READ:
case VM_FAULT_WRITE:
break;
default:
return EINVAL;
}
if (curproc == NULL) {
/*
* No process. This is probably a kernel fault early
* in boot. Return EFAULT so as to panic instead of
* getting into an infinite faulting loop.
*/
return EFAULT;
}
if (curproc == NULL) {
/*
* No process. This is probably a kernel fault early
* in boot. Return EFAULT so as to panic instead of
* getting into an infinite faulting loop.
*/
return EFAULT;
}
as = proc_getas();
if (as == NULL) {
/*
* No address space set up. This is probably also a
* kernel fault early in boot.
*/
return EFAULT;
}
as = proc_getas();
if (as == NULL) {
/*
* No address space set up. This is probably also a
* kernel fault early in boot.
*/
return EFAULT;
}
/* Assert that the address space has been set up properly. */
KASSERT(as->as_vbase1 != 0);
KASSERT(as->as_pbase1 != 0);
KASSERT(as->as_npages1 != 0);
KASSERT(as->as_vbase2 != 0);
KASSERT(as->as_pbase2 != 0);
KASSERT(as->as_npages2 != 0);
KASSERT(as->as_stackpbase != 0);
KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
/* Assert that the address space has been set up properly. */
KASSERT(as->as_vbase1 != 0);
KASSERT(as->as_pbase1 != 0);
KASSERT(as->as_npages1 != 0);
KASSERT(as->as_vbase2 != 0);
KASSERT(as->as_pbase2 != 0);
KASSERT(as->as_npages2 != 0);
KASSERT(as->as_stackpbase != 0);
KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
vbase1 = as->as_vbase1;
vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
vbase2 = as->as_vbase2;
vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
stacktop = USERSTACK;
vbase1 = as->as_vbase1;
vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
vbase2 = as->as_vbase2;
vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
stacktop = USERSTACK;
if (faultaddress >= vbase1 && faultaddress < vtop1) {
paddr = (faultaddress - vbase1) + as->as_pbase1;
}
else if (faultaddress >= vbase2 && faultaddress < vtop2) {
paddr = (faultaddress - vbase2) + as->as_pbase2;
}
else if (faultaddress >= stackbase && faultaddress < stacktop) {
paddr = (faultaddress - stackbase) + as->as_stackpbase;
}
else {
return EFAULT;
}
if (faultaddress >= vbase1 && faultaddress < vtop1) {
paddr = (faultaddress - vbase1) + as->as_pbase1;
} else if (faultaddress >= vbase2 && faultaddress < vtop2) {
paddr = (faultaddress - vbase2) + as->as_pbase2;
} else if (faultaddress >= stackbase && faultaddress < stacktop) {
paddr = (faultaddress - stackbase) + as->as_stackpbase;
} else {
return EFAULT;
}
/* make sure it's page-aligned */
KASSERT((paddr & PAGE_FRAME) == paddr);
/* make sure it's page-aligned */
KASSERT((paddr & PAGE_FRAME) == paddr);
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
for (i=0; i<NUM_TLB; i++) {
tlb_read(&ehi, &elo, i);
if (elo & TLBLO_VALID) {
continue;
}
ehi = faultaddress;
elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
tlb_write(ehi, elo, i);
splx(spl);
return 0;
}
for (i = 0; i < NUM_TLB; i++) {
tlb_read(&ehi, &elo, i);
if (elo & TLBLO_VALID) {
continue;
}
ehi = faultaddress;
elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
tlb_write(ehi, elo, i);
splx(spl);
return 0;
}
kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
splx(spl);
return EFAULT;
kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
splx(spl);
return EFAULT;
}
struct addrspace *
as_create(void)
{
struct addrspace *as = kmalloc(sizeof(struct addrspace));
if (as==NULL) {
return NULL;
}
struct addrspace *as_create(void) {
struct addrspace *as = kmalloc(sizeof(struct addrspace));
if (as == NULL) {
return NULL;
}
as->as_vbase1 = 0;
as->as_pbase1 = 0;
as->as_npages1 = 0;
as->as_vbase2 = 0;
as->as_pbase2 = 0;
as->as_npages2 = 0;
as->as_stackpbase = 0;
as->as_vbase1 = 0;
as->as_pbase1 = 0;
as->as_npages1 = 0;
as->as_vbase2 = 0;
as->as_pbase2 = 0;
as->as_npages2 = 0;
as->as_stackpbase = 0;
return as;
return as;
}
void
as_destroy(struct addrspace *as)
{
dumbvm_can_sleep();
kfree(as);
void as_destroy(struct addrspace *as) {
dumbvm_can_sleep();
kfree(as);
}
void
as_activate(void)
{
int i, spl;
struct addrspace *as;
void as_activate(void) {
int i, spl;
struct addrspace *as;
as = proc_getas();
if (as == NULL) {
return;
}
as = proc_getas();
if (as == NULL) {
return;
}
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
for (i=0; i<NUM_TLB; i++) {
tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
}
for (i = 0; i < NUM_TLB; i++) {
tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
}
splx(spl);
splx(spl);
}
void
as_deactivate(void)
{
/* nothing */
void as_deactivate(void) { /* nothing */ }
int as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
int readable, int writeable, int executable) {
size_t npages;
dumbvm_can_sleep();
/* Align the region. First, the base... */
sz += vaddr & ~(vaddr_t)PAGE_FRAME;
vaddr &= PAGE_FRAME;
/* ...and now the length. */
sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
npages = sz / PAGE_SIZE;
/* We don't use these - all pages are read-write */
(void)readable;
(void)writeable;
(void)executable;
if (as->as_vbase1 == 0) {
as->as_vbase1 = vaddr;
as->as_npages1 = npages;
return 0;
}
if (as->as_vbase2 == 0) {
as->as_vbase2 = vaddr;
as->as_npages2 = npages;
return 0;
}
/*
* Support for more than two regions is not available.
*/
kprintf("dumbvm: Warning: too many regions\n");
return ENOSYS;
}
int
as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
int readable, int writeable, int executable)
{
size_t npages;
dumbvm_can_sleep();
/* Align the region. First, the base... */
sz += vaddr & ~(vaddr_t)PAGE_FRAME;
vaddr &= PAGE_FRAME;
/* ...and now the length. */
sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
npages = sz / PAGE_SIZE;
/* We don't use these - all pages are read-write */
(void)readable;
(void)writeable;
(void)executable;
if (as->as_vbase1 == 0) {
as->as_vbase1 = vaddr;
as->as_npages1 = npages;
return 0;
}
if (as->as_vbase2 == 0) {
as->as_vbase2 = vaddr;
as->as_npages2 = npages;
return 0;
}
/*
* Support for more than two regions is not available.
*/
kprintf("dumbvm: Warning: too many regions\n");
return ENOSYS;
static void as_zero_region(paddr_t paddr, unsigned npages) {
bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
}
static
void
as_zero_region(paddr_t paddr, unsigned npages)
{
bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
int as_prepare_load(struct addrspace *as) {
KASSERT(as->as_pbase1 == 0);
KASSERT(as->as_pbase2 == 0);
KASSERT(as->as_stackpbase == 0);
dumbvm_can_sleep();
as->as_pbase1 = getppages(as->as_npages1);
if (as->as_pbase1 == 0) {
return ENOMEM;
}
as->as_pbase2 = getppages(as->as_npages2);
if (as->as_pbase2 == 0) {
return ENOMEM;
}
as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
if (as->as_stackpbase == 0) {
return ENOMEM;
}
as_zero_region(as->as_pbase1, as->as_npages1);
as_zero_region(as->as_pbase2, as->as_npages2);
as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
return 0;
}
int
as_prepare_load(struct addrspace *as)
{
KASSERT(as->as_pbase1 == 0);
KASSERT(as->as_pbase2 == 0);
KASSERT(as->as_stackpbase == 0);
dumbvm_can_sleep();
as->as_pbase1 = getppages(as->as_npages1);
if (as->as_pbase1 == 0) {
return ENOMEM;
}
as->as_pbase2 = getppages(as->as_npages2);
if (as->as_pbase2 == 0) {
return ENOMEM;
}
as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
if (as->as_stackpbase == 0) {
return ENOMEM;
}
as_zero_region(as->as_pbase1, as->as_npages1);
as_zero_region(as->as_pbase2, as->as_npages2);
as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
return 0;
int as_complete_load(struct addrspace *as) {
dumbvm_can_sleep();
(void)as;
return 0;
}
int
as_complete_load(struct addrspace *as)
{
dumbvm_can_sleep();
(void)as;
return 0;
int as_define_stack(struct addrspace *as, vaddr_t *stackptr) {
KASSERT(as->as_stackpbase != 0);
*stackptr = USERSTACK;
return 0;
}
int
as_define_stack(struct addrspace *as, vaddr_t *stackptr)
{
KASSERT(as->as_stackpbase != 0);
int as_copy(struct addrspace *old, struct addrspace **ret) {
struct addrspace *new;
*stackptr = USERSTACK;
return 0;
}
int
as_copy(struct addrspace *old, struct addrspace **ret)
{
struct addrspace *new;
dumbvm_can_sleep();
new = as_create();
if (new==NULL) {
return ENOMEM;
}
new->as_vbase1 = old->as_vbase1;
new->as_npages1 = old->as_npages1;
new->as_vbase2 = old->as_vbase2;
new->as_npages2 = old->as_npages2;
/* (Mis)use as_prepare_load to allocate some physical memory. */
if (as_prepare_load(new)) {
as_destroy(new);
return ENOMEM;
}
KASSERT(new->as_pbase1 != 0);
KASSERT(new->as_pbase2 != 0);
KASSERT(new->as_stackpbase != 0);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
(const void *)PADDR_TO_KVADDR(old->as_pbase1),
old->as_npages1*PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
(const void *)PADDR_TO_KVADDR(old->as_pbase2),
old->as_npages2*PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
(const void *)PADDR_TO_KVADDR(old->as_stackpbase),
DUMBVM_STACKPAGES*PAGE_SIZE);
*ret = new;
return 0;
dumbvm_can_sleep();
new = as_create();
if (new == NULL) {
return ENOMEM;
}
new->as_vbase1 = old->as_vbase1;
new->as_npages1 = old->as_npages1;
new->as_vbase2 = old->as_vbase2;
new->as_npages2 = old->as_npages2;
/* (Mis)use as_prepare_load to allocate some physical memory. */
if (as_prepare_load(new)) {
as_destroy(new);
return ENOMEM;
}
KASSERT(new->as_pbase1 != 0);
KASSERT(new->as_pbase2 != 0);
KASSERT(new->as_stackpbase != 0);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
(const void *)PADDR_TO_KVADDR(old->as_pbase1),
old->as_npages1 * PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
(const void *)PADDR_TO_KVADDR(old->as_pbase2),
old->as_npages2 * PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
(const void *)PADDR_TO_KVADDR(old->as_stackpbase),
DUMBVM_STACKPAGES * PAGE_SIZE);
*ret = new;
return 0;
}

View File

@ -32,45 +32,41 @@
#include <vm.h>
#include <mainbus.h>
vaddr_t firstfree; /* first free virtual address; set by start.S */
vaddr_t firstfree; /* first free virtual address; set by start.S */
static paddr_t firstpaddr; /* address of first free physical page */
static paddr_t lastpaddr; /* one past end of last free physical page */
static paddr_t firstpaddr; /* address of first free physical page */
static paddr_t lastpaddr; /* one past end of last free physical page */
/*
* Called very early in system boot to figure out how much physical
* RAM is available.
*/
void
ram_bootstrap(void)
{
size_t ramsize;
void ram_bootstrap(void) {
size_t ramsize;
/* Get size of RAM. */
ramsize = mainbus_ramsize();
/* Get size of RAM. */
ramsize = mainbus_ramsize();
/*
* This is the same as the last physical address, as long as
* we have less than 512 megabytes of memory. If we had more,
* we wouldn't be able to access it all through kseg0 and
* everything would get a lot more complicated. This is not a
* case we are going to worry about.
*/
if (ramsize > 512*1024*1024) {
ramsize = 512*1024*1024;
}
/*
* This is the same as the last physical address, as long as
* we have less than 512 megabytes of memory. If we had more,
* we wouldn't be able to access it all through kseg0 and
* everything would get a lot more complicated. This is not a
* case we are going to worry about.
*/
if (ramsize > 512 * 1024 * 1024) {
ramsize = 512 * 1024 * 1024;
}
lastpaddr = ramsize;
lastpaddr = ramsize;
/*
* Get first free virtual address from where start.S saved it.
* Convert to physical address.
*/
firstpaddr = firstfree - MIPS_KSEG0;
/*
* Get first free virtual address from where start.S saved it.
* Convert to physical address.
*/
firstpaddr = firstfree - MIPS_KSEG0;
kprintf("%uk physical memory available\n",
(lastpaddr-firstpaddr)/1024);
kprintf("%uk physical memory available\n", (lastpaddr - firstpaddr) / 1024);
}
/*
@ -91,22 +87,20 @@ ram_bootstrap(void)
* This function should not be called once the VM system is initialized,
* so it is not synchronized.
*/
paddr_t
ram_stealmem(unsigned long npages)
{
size_t size;
paddr_t paddr;
paddr_t ram_stealmem(unsigned long npages) {
size_t size;
paddr_t paddr;
size = npages * PAGE_SIZE;
size = npages * PAGE_SIZE;
if (firstpaddr + size > lastpaddr) {
return 0;
}
if (firstpaddr + size > lastpaddr) {
return 0;
}
paddr = firstpaddr;
firstpaddr += size;
paddr = firstpaddr;
firstpaddr += size;
return paddr;
return paddr;
}
/*
@ -124,11 +118,7 @@ ram_stealmem(unsigned long npages)
* initialize the VM system, after which the VM system should take
* charge of knowing what memory exists.
*/
paddr_t
ram_getsize(void)
{
return lastpaddr;
}
paddr_t ram_getsize(void) { return lastpaddr; }
/*
* This function is intended to be called by the VM system when it
@ -142,12 +132,10 @@ ram_getsize(void)
* This function should not be called once the VM system is initialized,
* so it is not synchronized.
*/
paddr_t
ram_getfirstfree(void)
{
paddr_t ret;
paddr_t ram_getfirstfree(void) {
paddr_t ret;
ret = firstpaddr;
firstpaddr = lastpaddr = 0;
return ret;
ret = firstpaddr;
firstpaddr = lastpaddr = 0;
return ret;
}

View File

@ -60,20 +60,16 @@
* matches the c0_compare register, the timer interrupt line is
* asserted. Writing to c0_compare again clears the interrupt.
*/
static
void
mips_timer_set(uint32_t count)
{
/*
* $11 == c0_compare; we can't use the symbolic name inside
* the asm string.
*/
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 registers */
"mtc0 %0, $11;" /* do it */
".set pop" /* restore assembler mode */
:: "r" (count));
static void mips_timer_set(uint32_t count) {
/*
* $11 == c0_compare; we can't use the symbolic name inside
* the asm string.
*/
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 registers */
"mtc0 %0, $11;" /* do it */
".set pop" /* restore assembler mode */
::"r"(count));
}
/*
@ -83,138 +79,122 @@ mips_timer_set(uint32_t count)
*/
static struct lamebus_softc *lamebus;
void
mainbus_bootstrap(void)
{
/* Interrupts should be off (and have been off since startup) */
KASSERT(curthread->t_curspl > 0);
void mainbus_bootstrap(void) {
/* Interrupts should be off (and have been off since startup) */
KASSERT(curthread->t_curspl > 0);
/* Initialize the system LAMEbus data */
lamebus = lamebus_init();
/* Initialize the system LAMEbus data */
lamebus = lamebus_init();
/* Probe CPUs (should these be done as device attachments instead?) */
lamebus_find_cpus(lamebus);
/* Probe CPUs (should these be done as device attachments instead?) */
lamebus_find_cpus(lamebus);
/*
* Print the device name for the main bus.
*/
kprintf("lamebus0 (system main bus)\n");
/*
* Print the device name for the main bus.
*/
kprintf("lamebus0 (system main bus)\n");
/*
* Now we can take interrupts without croaking, so turn them on.
* Some device probes might require being able to get interrupts.
*/
/*
* Now we can take interrupts without croaking, so turn them on.
* Some device probes might require being able to get interrupts.
*/
spl0();
spl0();
/*
* Now probe all the devices attached to the bus.
* (This amounts to all devices.)
*/
autoconf_lamebus(lamebus, 0);
/*
* Now probe all the devices attached to the bus.
* (This amounts to all devices.)
*/
autoconf_lamebus(lamebus, 0);
/*
* Configure the MIPS on-chip timer to interrupt HZ times a second.
*/
mips_timer_set(CPU_FREQUENCY / HZ);
/*
* Configure the MIPS on-chip timer to interrupt HZ times a second.
*/
mips_timer_set(CPU_FREQUENCY / HZ);
}
/*
* Start all secondary CPUs.
*/
void
mainbus_start_cpus(void)
{
lamebus_start_cpus(lamebus);
}
void mainbus_start_cpus(void) { lamebus_start_cpus(lamebus); }
/*
* Function to generate the memory address (in the uncached segment)
* for the specified offset into the specified slot's region of the
* LAMEbus.
*/
void *
lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset)
{
uint32_t address;
void *lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset) {
uint32_t address;
(void)bus; // not needed
(void)bus; // not needed
KASSERT(slot >= 0 && slot < LB_NSLOTS);
KASSERT(slot >= 0 && slot < LB_NSLOTS);
address = LB_BASEADDR + slot*LB_SLOT_SIZE + offset;
return (void *)address;
address = LB_BASEADDR + slot * LB_SLOT_SIZE + offset;
return (void *)address;
}
/*
* Read a 32-bit register from a LAMEbus device.
*/
uint32_t
lamebus_read_register(struct lamebus_softc *bus, int slot, uint32_t offset)
{
uint32_t *ptr;
uint32_t lamebus_read_register(struct lamebus_softc *bus, int slot,
uint32_t offset) {
uint32_t *ptr;
ptr = lamebus_map_area(bus, slot, offset);
ptr = lamebus_map_area(bus, slot, offset);
/*
* Make sure the load happens after anything the device has
* been doing.
*/
membar_load_load();
/*
* Make sure the load happens after anything the device has
* been doing.
*/
membar_load_load();
return *ptr;
return *ptr;
}
/*
* Write a 32-bit register of a LAMEbus device.
*/
void
lamebus_write_register(struct lamebus_softc *bus, int slot,
uint32_t offset, uint32_t val)
{
uint32_t *ptr;
void lamebus_write_register(struct lamebus_softc *bus, int slot,
uint32_t offset, uint32_t val) {
uint32_t *ptr;
ptr = lamebus_map_area(bus, slot, offset);
*ptr = val;
ptr = lamebus_map_area(bus, slot, offset);
*ptr = val;
/*
* Make sure the store happens before we do anything else to
* the device.
*/
membar_store_store();
/*
* Make sure the store happens before we do anything else to
* the device.
*/
membar_store_store();
}
/*
* Power off the system.
*/
void
mainbus_poweroff(void)
{
/*
*
* Note that lamebus_write_register() doesn't actually access
* the bus argument, so this will still work if we get here
* before the bus is initialized.
*/
lamebus_poweroff(lamebus);
void mainbus_poweroff(void) {
/*
*
* Note that lamebus_write_register() doesn't actually access
* the bus argument, so this will still work if we get here
* before the bus is initialized.
*/
lamebus_poweroff(lamebus);
}
/*
* Reboot the system.
*/
void
mainbus_reboot(void)
{
/*
* The MIPS doesn't appear to have any on-chip reset.
* LAMEbus doesn't have a reset control, so we just
* power off instead of rebooting. This would not be
* so great in a real system, but it's fine for what
* we're doing.
*/
kprintf("Cannot reboot - powering off instead, sorry.\n");
mainbus_poweroff();
void mainbus_reboot(void) {
/*
* The MIPS doesn't appear to have any on-chip reset.
* LAMEbus doesn't have a reset control, so we just
* power off instead of rebooting. This would not be
* so great in a real system, but it's fine for what
* we're doing.
*/
kprintf("Cannot reboot - powering off instead, sorry.\n");
mainbus_poweroff();
}
/*
@ -222,11 +202,7 @@ mainbus_reboot(void)
* On some systems, this would return to the boot monitor. But we don't
* have one.
*/
void
mainbus_halt(void)
{
cpu_halt();
}
void mainbus_halt(void) { cpu_halt(); }
/*
* Called to reset the system from panic().
@ -235,110 +211,94 @@ mainbus_halt(void)
* as to panic recursively if we do much of anything. So just power off.
* (We'd reboot, but System/161 doesn't do that.)
*/
void
mainbus_panic(void)
{
mainbus_poweroff();
}
void mainbus_panic(void) { mainbus_poweroff(); }
/*
* Function to get the size of installed physical RAM from the LAMEbus
* controller.
*/
uint32_t
mainbus_ramsize(void)
{
uint32_t ramsize;
uint32_t mainbus_ramsize(void) {
uint32_t ramsize;
ramsize = lamebus_ramsize();
ramsize = lamebus_ramsize();
/*
* This is the same as the last physical address, as long as
* we have less than 508 megabytes of memory. The LAMEbus I/O
* area occupies the space between 508 megabytes and 512
* megabytes, so if we had more RAM than this it would have to
* be discontiguous. This is not a case we are going to worry
* about.
*/
if (ramsize > 508*1024*1024) {
ramsize = 508*1024*1024;
}
/*
* This is the same as the last physical address, as long as
* we have less than 508 megabytes of memory. The LAMEbus I/O
* area occupies the space between 508 megabytes and 512
* megabytes, so if we had more RAM than this it would have to
* be discontiguous. This is not a case we are going to worry
* about.
*/
if (ramsize > 508 * 1024 * 1024) {
ramsize = 508 * 1024 * 1024;
}
return ramsize;
return ramsize;
}
/*
* Send IPI.
*/
void
mainbus_send_ipi(struct cpu *target)
{
lamebus_assert_ipi(lamebus, target);
void mainbus_send_ipi(struct cpu *target) {
lamebus_assert_ipi(lamebus, target);
}
/*
* Trigger the debugger.
*/
void
mainbus_debugger(void)
{
ltrace_stop(0);
}
void mainbus_debugger(void) { ltrace_stop(0); }
/*
* Interrupt dispatcher.
*/
/* Wiring of LAMEbus interrupts to bits in the cause register */
#define LAMEBUS_IRQ_BIT 0x00000400 /* all system bus slots */
#define LAMEBUS_IPI_BIT 0x00000800 /* inter-processor interrupt */
#define MIPS_TIMER_BIT 0x00008000 /* on-chip timer */
#define LAMEBUS_IRQ_BIT 0x00000400 /* all system bus slots */
#define LAMEBUS_IPI_BIT 0x00000800 /* inter-processor interrupt */
#define MIPS_TIMER_BIT 0x00008000 /* on-chip timer */
void
mainbus_interrupt(struct trapframe *tf)
{
uint32_t cause;
bool seen = false;
void mainbus_interrupt(struct trapframe *tf) {
uint32_t cause;
bool seen = false;
/* interrupts should be off */
KASSERT(curthread->t_curspl > 0);
/* interrupts should be off */
KASSERT(curthread->t_curspl > 0);
cause = tf->tf_cause;
if (cause & LAMEBUS_IRQ_BIT) {
lamebus_interrupt(lamebus);
seen = true;
}
if (cause & LAMEBUS_IPI_BIT) {
interprocessor_interrupt();
lamebus_clear_ipi(lamebus, curcpu);
seen = true;
}
if (cause & MIPS_TIMER_BIT) {
/* Reset the timer (this clears the interrupt) */
mips_timer_set(CPU_FREQUENCY / HZ);
/* and call hardclock */
hardclock();
seen = true;
}
cause = tf->tf_cause;
if (cause & LAMEBUS_IRQ_BIT) {
lamebus_interrupt(lamebus);
seen = true;
}
if (cause & LAMEBUS_IPI_BIT) {
interprocessor_interrupt();
lamebus_clear_ipi(lamebus, curcpu);
seen = true;
}
if (cause & MIPS_TIMER_BIT) {
/* Reset the timer (this clears the interrupt) */
mips_timer_set(CPU_FREQUENCY / HZ);
/* and call hardclock */
hardclock();
seen = true;
}
if (!seen) {
if ((cause & CCA_IRQS) == 0) {
/*
* Don't panic here; this can happen if an
* interrupt line asserts (very) briefly and
* turns off again before we get as far as
* reading the cause register. This was
* actually seen... once.
*/
}
else {
/*
* But if we get an interrupt on an interrupt
* line that's not supposed to be wired up,
* complain.
*/
panic("Unknown interrupt; cause register is %08x\n",
cause);
}
}
if (!seen) {
if ((cause & CCA_IRQS) == 0) {
/*
* Don't panic here; this can happen if an
* interrupt line asserts (very) briefly and
* turns off again before we get as far as
* reading the cause register. This was
* actually seen... once.
*/
} else {
/*
* But if we get an interrupt on an interrupt
* line that's not supposed to be wired up,
* complain.
*/
panic("Unknown interrupt; cause register is %08x\n", cause);
}
}
}

View File

@ -37,24 +37,22 @@
* This would need to be a bit more complicated if that weren't the case.
*/
#include <machine/vm.h> /* for MIPS_KSEG1 */
#include <lamebus/lamebus.h> /* for LAMEbus definitions */
#include <machine/vm.h> /* for MIPS_KSEG1 */
#include <lamebus/lamebus.h> /* for LAMEbus definitions */
#define bus_write_register(bus, slot, offset, val) \
lamebus_write_register(bus, slot, offset, val)
#define bus_write_register(bus, slot, offset, val) \
lamebus_write_register(bus, slot, offset, val)
#define bus_read_register(bus, slot, offset) \
lamebus_read_register(bus, slot, offset)
#define bus_read_register(bus, slot, offset) \
lamebus_read_register(bus, slot, offset)
#define bus_map_area(bus, slot, offset) \
lamebus_map_area(bus, slot, offset)
#define bus_map_area(bus, slot, offset) lamebus_map_area(bus, slot, offset)
/*
* Machine-dependent LAMEbus definitions
*/
/* Base address of the LAMEbus mapping area */
#define LB_BASEADDR (MIPS_KSEG1 + 0x1fe00000)
#define LB_BASEADDR (MIPS_KSEG1 + 0x1fe00000)
#endif /* _SYS161_BUS_H_ */

View File

@ -46,26 +46,21 @@
static struct beep_softc *the_beep = NULL;
int
config_beep(struct beep_softc *bs, int unit)
{
/* We use only the first beep device. */
if (unit!=0) {
return ENODEV;
}
int config_beep(struct beep_softc *bs, int unit) {
/* We use only the first beep device. */
if (unit != 0) {
return ENODEV;
}
KASSERT(the_beep==NULL);
the_beep = bs;
return 0;
KASSERT(the_beep == NULL);
the_beep = bs;
return 0;
}
void
beep(void)
{
if (the_beep!=NULL) {
the_beep->bs_beep(the_beep->bs_devdata);
}
else {
kprintf("beep: Warning: no beep device\n");
}
void beep(void) {
if (the_beep != NULL) {
the_beep->bs_beep(the_beep->bs_devdata);
} else {
kprintf("beep: Warning: no beep device\n");
}
}

View File

@ -36,8 +36,8 @@
*/
struct beep_softc {
void *bs_devdata;
void (*bs_beep)(void *devdata);
void *bs_devdata;
void (*bs_beep)(void *devdata);
};
#endif /* _GENERIC_BEEP_H_ */

View File

@ -79,32 +79,26 @@ static struct lock *con_userlock_write = NULL;
* console is set up. Upon console setup they are dumped
* to the actual console; thenceforth this space is unused.
*/
#define DELAYBUFSIZE 1024
#define DELAYBUFSIZE 1024
static char delayed_outbuf[DELAYBUFSIZE];
static size_t delayed_outbuf_pos=0;
static size_t delayed_outbuf_pos = 0;
static
void
putch_delayed(int ch)
{
/*
* No synchronization needed: called only during system startup
* by main thread.
*/
static void putch_delayed(int ch) {
/*
* No synchronization needed: called only during system startup
* by main thread.
*/
KASSERT(delayed_outbuf_pos < sizeof(delayed_outbuf));
delayed_outbuf[delayed_outbuf_pos++] = ch;
KASSERT(delayed_outbuf_pos < sizeof(delayed_outbuf));
delayed_outbuf[delayed_outbuf_pos++] = ch;
}
static
void
flush_delay_buf(void)
{
size_t i;
for (i=0; i<delayed_outbuf_pos; i++) {
putch(delayed_outbuf[i]);
}
delayed_outbuf_pos = 0;
static void flush_delay_buf(void) {
size_t i;
for (i = 0; i < delayed_outbuf_pos; i++) {
putch(delayed_outbuf[i]);
}
delayed_outbuf_pos = 0;
}
//////////////////////////////////////////////////
@ -113,11 +107,8 @@ flush_delay_buf(void)
* Print a character, using polling instead of interrupts to wait for
* I/O completion.
*/
static
void
putch_polled(struct con_softc *cs, int ch)
{
cs->cs_sendpolled(cs->cs_devdata, ch);
static void putch_polled(struct con_softc *cs, int ch) {
cs->cs_sendpolled(cs->cs_devdata, ch);
}
//////////////////////////////////////////////////
@ -125,28 +116,21 @@ putch_polled(struct con_softc *cs, int ch)
/*
* Print a character, using interrupts to wait for I/O completion.
*/
static
void
putch_intr(struct con_softc *cs, int ch)
{
P(cs->cs_wsem);
cs->cs_send(cs->cs_devdata, ch);
static void putch_intr(struct con_softc *cs, int ch) {
P(cs->cs_wsem);
cs->cs_send(cs->cs_devdata, ch);
}
/*
* Read a character, using interrupts to wait for I/O completion.
*/
static
int
getch_intr(struct con_softc *cs)
{
unsigned char ret;
static int getch_intr(struct con_softc *cs) {
unsigned char ret;
P(cs->cs_rsem);
ret = cs->cs_gotchars[cs->cs_gotchars_tail];
cs->cs_gotchars_tail =
(cs->cs_gotchars_tail + 1) % CONSOLE_INPUT_BUFFER_SIZE;
return ret;
P(cs->cs_rsem);
ret = cs->cs_gotchars[cs->cs_gotchars_tail];
cs->cs_gotchars_tail = (cs->cs_gotchars_tail + 1) % CONSOLE_INPUT_BUFFER_SIZE;
return ret;
}
/*
@ -158,33 +142,29 @@ getch_intr(struct con_softc *cs)
* too) would be with a second semaphore used with a nonblocking P,
* but we don't have that in OS/161.
*/
void
con_input(void *vcs, int ch)
{
struct con_softc *cs = vcs;
unsigned nexthead;
void con_input(void *vcs, int ch) {
struct con_softc *cs = vcs;
unsigned nexthead;
nexthead = (cs->cs_gotchars_head + 1) % CONSOLE_INPUT_BUFFER_SIZE;
if (nexthead == cs->cs_gotchars_tail) {
/* overflow; drop character */
return;
}
nexthead = (cs->cs_gotchars_head + 1) % CONSOLE_INPUT_BUFFER_SIZE;
if (nexthead == cs->cs_gotchars_tail) {
/* overflow; drop character */
return;
}
cs->cs_gotchars[cs->cs_gotchars_head] = ch;
cs->cs_gotchars_head = nexthead;
cs->cs_gotchars[cs->cs_gotchars_head] = ch;
cs->cs_gotchars_head = nexthead;
V(cs->cs_rsem);
V(cs->cs_rsem);
}
/*
* Called from underlying device when a write-done interrupt occurs.
*/
void
con_start(void *vcs)
{
struct con_softc *cs = vcs;
void con_start(void *vcs) {
struct con_softc *cs = vcs;
V(cs->cs_wsem);
V(cs->cs_wsem);
}
//////////////////////////////////////////////////
@ -197,32 +177,25 @@ con_start(void *vcs)
* not, and does not.
*/
void
putch(int ch)
{
struct con_softc *cs = the_console;
void putch(int ch) {
struct con_softc *cs = the_console;
if (cs==NULL) {
putch_delayed(ch);
}
else if (curthread->t_in_interrupt ||
curthread->t_curspl > 0 ||
curcpu->c_spinlocks > 0) {
putch_polled(cs, ch);
}
else {
putch_intr(cs, ch);
}
if (cs == NULL) {
putch_delayed(ch);
} else if (curthread->t_in_interrupt || curthread->t_curspl > 0 ||
curcpu->c_spinlocks > 0) {
putch_polled(cs, ch);
} else {
putch_intr(cs, ch);
}
}
int
getch(void)
{
struct con_softc *cs = the_console;
KASSERT(cs != NULL);
KASSERT(!curthread->t_in_interrupt && curthread->t_iplhigh_count == 0);
int getch(void) {
struct con_softc *cs = the_console;
KASSERT(cs != NULL);
KASSERT(!curthread->t_in_interrupt && curthread->t_iplhigh_count == 0);
return getch_intr(cs);
return getch_intr(cs);
}
////////////////////////////////////////////////////////////
@ -231,107 +204,93 @@ getch(void)
* VFS interface functions
*/
static
int
con_eachopen(struct device *dev, int openflags)
{
(void)dev;
(void)openflags;
return 0;
static int con_eachopen(struct device *dev, int openflags) {
(void)dev;
(void)openflags;
return 0;
}
static
int
con_io(struct device *dev, struct uio *uio)
{
int result;
char ch;
struct lock *lk;
static int con_io(struct device *dev, struct uio *uio) {
int result;
char ch;
struct lock *lk;
(void)dev; // unused
(void)dev; // unused
if (uio->uio_rw==UIO_READ) {
lk = con_userlock_read;
}
else {
lk = con_userlock_write;
}
if (uio->uio_rw == UIO_READ) {
lk = con_userlock_read;
} else {
lk = con_userlock_write;
}
KASSERT(lk != NULL);
lock_acquire(lk);
KASSERT(lk != NULL);
lock_acquire(lk);
while (uio->uio_resid > 0) {
if (uio->uio_rw==UIO_READ) {
ch = getch();
if (ch=='\r') {
ch = '\n';
}
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch=='\n') {
break;
}
}
else {
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch=='\n') {
putch('\r');
}
putch(ch);
}
}
lock_release(lk);
return 0;
while (uio->uio_resid > 0) {
if (uio->uio_rw == UIO_READ) {
ch = getch();
if (ch == '\r') {
ch = '\n';
}
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch == '\n') {
break;
}
} else {
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch == '\n') {
putch('\r');
}
putch(ch);
}
}
lock_release(lk);
return 0;
}
static
int
con_ioctl(struct device *dev, int op, userptr_t data)
{
/* No ioctls. */
(void)dev;
(void)op;
(void)data;
return EINVAL;
static int con_ioctl(struct device *dev, int op, userptr_t data) {
/* No ioctls. */
(void)dev;
(void)op;
(void)data;
return EINVAL;
}
static const struct device_ops console_devops = {
.devop_eachopen = con_eachopen,
.devop_io = con_io,
.devop_ioctl = con_ioctl,
.devop_eachopen = con_eachopen,
.devop_io = con_io,
.devop_ioctl = con_ioctl,
};
static
int
attach_console_to_vfs(struct con_softc *cs)
{
struct device *dev;
int result;
static int attach_console_to_vfs(struct con_softc *cs) {
struct device *dev;
int result;
dev = kmalloc(sizeof(*dev));
if (dev==NULL) {
return ENOMEM;
}
dev = kmalloc(sizeof(*dev));
if (dev == NULL) {
return ENOMEM;
}
dev->d_ops = &console_devops;
dev->d_blocks = 0;
dev->d_blocksize = 1;
dev->d_data = cs;
dev->d_ops = &console_devops;
dev->d_blocks = 0;
dev->d_blocksize = 1;
dev->d_data = cs;
result = vfs_adddev("con", dev, 0);
if (result) {
kfree(dev);
return result;
}
result = vfs_adddev("con", dev, 0);
if (result) {
kfree(dev);
return result;
}
return 0;
return 0;
}
////////////////////////////////////////////////////////////
@ -340,58 +299,56 @@ attach_console_to_vfs(struct con_softc *cs)
* Config routine called by autoconf.c after we are attached to something.
*/
int
config_con(struct con_softc *cs, int unit)
{
struct semaphore *rsem, *wsem;
struct lock *rlk, *wlk;
int config_con(struct con_softc *cs, int unit) {
struct semaphore *rsem, *wsem;
struct lock *rlk, *wlk;
/*
* Only allow one system console.
* Further devices that could be the system console are ignored.
*
* Do not hardwire the console to be "con1" instead of "con0",
* or these asserts will go off.
*/
if (unit>0) {
KASSERT(the_console!=NULL);
return ENODEV;
}
KASSERT(the_console==NULL);
/*
* Only allow one system console.
* Further devices that could be the system console are ignored.
*
* Do not hardwire the console to be "con1" instead of "con0",
* or these asserts will go off.
*/
if (unit > 0) {
KASSERT(the_console != NULL);
return ENODEV;
}
KASSERT(the_console == NULL);
rsem = sem_create("console read", 0);
if (rsem == NULL) {
return ENOMEM;
}
wsem = sem_create("console write", 1);
if (wsem == NULL) {
sem_destroy(rsem);
return ENOMEM;
}
rlk = lock_create("console-lock-read");
if (rlk == NULL) {
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
wlk = lock_create("console-lock-write");
if (wlk == NULL) {
lock_destroy(rlk);
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
rsem = sem_create("console read", 0);
if (rsem == NULL) {
return ENOMEM;
}
wsem = sem_create("console write", 1);
if (wsem == NULL) {
sem_destroy(rsem);
return ENOMEM;
}
rlk = lock_create("console-lock-read");
if (rlk == NULL) {
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
wlk = lock_create("console-lock-write");
if (wlk == NULL) {
lock_destroy(rlk);
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
cs->cs_rsem = rsem;
cs->cs_wsem = wsem;
cs->cs_gotchars_head = 0;
cs->cs_gotchars_tail = 0;
cs->cs_rsem = rsem;
cs->cs_wsem = wsem;
cs->cs_gotchars_head = 0;
cs->cs_gotchars_tail = 0;
the_console = cs;
con_userlock_read = rlk;
con_userlock_write = wlk;
the_console = cs;
con_userlock_read = rlk;
con_userlock_write = wlk;
flush_delay_buf();
flush_delay_buf();
return attach_console_to_vfs(cs);
return attach_console_to_vfs(cs);
}

View File

@ -40,17 +40,17 @@
#define CONSOLE_INPUT_BUFFER_SIZE 32
struct con_softc {
/* initialized by attach routine */
void *cs_devdata;
void (*cs_send)(void *devdata, int ch);
void (*cs_sendpolled)(void *devdata, int ch);
/* initialized by attach routine */
void *cs_devdata;
void (*cs_send)(void *devdata, int ch);
void (*cs_sendpolled)(void *devdata, int ch);
/* initialized by config routine */
struct semaphore *cs_rsem;
struct semaphore *cs_wsem;
unsigned char cs_gotchars[CONSOLE_INPUT_BUFFER_SIZE];
unsigned cs_gotchars_head; /* next slot to put a char in */
unsigned cs_gotchars_tail; /* next slot to take a char out */
/* initialized by config routine */
struct semaphore *cs_rsem;
struct semaphore *cs_wsem;
unsigned char cs_gotchars[CONSOLE_INPUT_BUFFER_SIZE];
unsigned cs_gotchars_head; /* next slot to put a char in */
unsigned cs_gotchars_tail; /* next slot to take a char out */
};
/*

View File

@ -53,106 +53,90 @@ static struct random_softc *the_random = NULL;
* VFS device functions.
* open: allow reading only.
*/
static
int
randeachopen(struct device *dev, int openflags)
{
(void)dev;
static int randeachopen(struct device *dev, int openflags) {
(void)dev;
if (openflags != O_RDONLY) {
return EIO;
}
if (openflags != O_RDONLY) {
return EIO;
}
return 0;
return 0;
}
/*
* VFS I/O function. Hand off to implementation.
*/
static
int
randio(struct device *dev, struct uio *uio)
{
struct random_softc *rs = dev->d_data;
static int randio(struct device *dev, struct uio *uio) {
struct random_softc *rs = dev->d_data;
if (uio->uio_rw != UIO_READ) {
return EIO;
}
if (uio->uio_rw != UIO_READ) {
return EIO;
}
return rs->rs_read(rs->rs_devdata, uio);
return rs->rs_read(rs->rs_devdata, uio);
}
/*
* VFS ioctl function.
*/
static
int
randioctl(struct device *dev, int op, userptr_t data)
{
/*
* We don't support any ioctls.
*/
(void)dev;
(void)op;
(void)data;
return EIOCTL;
static int randioctl(struct device *dev, int op, userptr_t data) {
/*
* We don't support any ioctls.
*/
(void)dev;
(void)op;
(void)data;
return EIOCTL;
}
static const struct device_ops random_devops = {
.devop_eachopen = randeachopen,
.devop_io = randio,
.devop_ioctl = randioctl,
.devop_eachopen = randeachopen,
.devop_io = randio,
.devop_ioctl = randioctl,
};
/*
* Config function.
*/
int
config_random(struct random_softc *rs, int unit)
{
int result;
int config_random(struct random_softc *rs, int unit) {
int result;
/* We use only the first random device. */
if (unit!=0) {
return ENODEV;
}
/* We use only the first random device. */
if (unit != 0) {
return ENODEV;
}
KASSERT(the_random==NULL);
the_random = rs;
KASSERT(the_random == NULL);
the_random = rs;
rs->rs_dev.d_ops = &random_devops;
rs->rs_dev.d_blocks = 0;
rs->rs_dev.d_blocksize = 1;
rs->rs_dev.d_data = rs;
rs->rs_dev.d_ops = &random_devops;
rs->rs_dev.d_blocks = 0;
rs->rs_dev.d_blocksize = 1;
rs->rs_dev.d_data = rs;
/* Add the VFS device structure to the VFS device list. */
result = vfs_adddev("random", &rs->rs_dev, 0);
if (result) {
return result;
}
/* Add the VFS device structure to the VFS device list. */
result = vfs_adddev("random", &rs->rs_dev, 0);
if (result) {
return result;
}
return 0;
return 0;
}
/*
* Random number functions exported to the rest of the kernel.
*/
uint32_t
random(void)
{
if (the_random==NULL) {
panic("No random device\n");
}
return the_random->rs_random(the_random->rs_devdata);
uint32_t random(void) {
if (the_random == NULL) {
panic("No random device\n");
}
return the_random->rs_random(the_random->rs_devdata);
}
uint32_t
randmax(void)
{
if (the_random==NULL) {
panic("No random device\n");
}
return the_random->rs_randmax(the_random->rs_devdata);
uint32_t randmax(void) {
if (the_random == NULL) {
panic("No random device\n");
}
return the_random->rs_randmax(the_random->rs_devdata);
}

View File

@ -34,13 +34,13 @@
struct uio;
struct random_softc {
/* Initialized by lower-level attach routine */
void *rs_devdata;
uint32_t (*rs_random)(void *devdata);
uint32_t (*rs_randmax)(void *devdata);
int (*rs_read)(void *devdata, struct uio *uio);
/* Initialized by lower-level attach routine */
void *rs_devdata;
uint32_t (*rs_random)(void *devdata);
uint32_t (*rs_randmax)(void *devdata);
int (*rs_read)(void *devdata, struct uio *uio);
struct device rs_dev;
struct device rs_dev;
};
#endif /* _GENERIC_RANDOM_H_ */

View File

@ -49,22 +49,18 @@
static struct rtclock_softc *the_clock = NULL;
int
config_rtclock(struct rtclock_softc *rtc, int unit)
{
/* We use only the first clock device. */
if (unit!=0) {
return ENODEV;
}
int config_rtclock(struct rtclock_softc *rtc, int unit) {
/* We use only the first clock device. */
if (unit != 0) {
return ENODEV;
}
KASSERT(the_clock==NULL);
the_clock = rtc;
return 0;
KASSERT(the_clock == NULL);
the_clock = rtc;
return 0;
}
void
gettime(struct timespec *ts)
{
KASSERT(the_clock!=NULL);
the_clock->rtc_gettime(the_clock->rtc_devdata, ts);
void gettime(struct timespec *ts) {
KASSERT(the_clock != NULL);
the_clock->rtc_gettime(the_clock->rtc_devdata, ts);
}

View File

@ -38,8 +38,8 @@
struct timespec;
struct rtclock_softc {
void *rtc_devdata;
void (*rtc_gettime)(void *devdata, struct timespec *);
void *rtc_devdata;
void (*rtc_gettime)(void *devdata, struct timespec *);
};
#endif /* _GENERIC_RTCLOCK_H_ */

View File

@ -38,18 +38,16 @@
#include <lamebus/ltimer.h>
#include "autoconf.h"
struct beep_softc *
attach_beep_to_ltimer(int beepno, struct ltimer_softc *ls)
{
struct beep_softc *bs = kmalloc(sizeof(struct beep_softc));
if (bs==NULL) {
return NULL;
}
struct beep_softc *attach_beep_to_ltimer(int beepno, struct ltimer_softc *ls) {
struct beep_softc *bs = kmalloc(sizeof(struct beep_softc));
if (bs == NULL) {
return NULL;
}
(void)beepno; // unused
(void)beepno; // unused
bs->bs_devdata = ls;
bs->bs_beep = ltimer_beep;
bs->bs_devdata = ls;
bs->bs_beep = ltimer_beep;
return bs;
return bs;
}

View File

@ -38,22 +38,19 @@
#include <lamebus/lscreen.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lscreen(int consno, struct lscreen_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
struct con_softc *attach_con_to_lscreen(int consno, struct lscreen_softc *ls) {
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs == NULL) {
return NULL;
}
cs->cs_devdata = ls;
cs->cs_send = lscreen_write;
cs->cs_sendpolled = lscreen_write;
cs->cs_devdata = ls;
cs->cs_send = lscreen_write;
cs->cs_sendpolled = lscreen_write;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
return cs;
}

View File

@ -38,24 +38,21 @@
#include <lamebus/lser.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lser(int consno, struct lser_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
struct con_softc *attach_con_to_lser(int consno, struct lser_softc *ls) {
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs == NULL) {
return NULL;
}
(void)consno; // unused
(void)consno; // unused
cs->cs_devdata = ls;
cs->cs_send = lser_write;
cs->cs_sendpolled = lser_writepolled;
cs->cs_devdata = ls;
cs->cs_send = lser_write;
cs->cs_sendpolled = lser_writepolled;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
return cs;
}

File diff suppressed because it is too large Load Diff

View File

@ -30,9 +30,8 @@
#ifndef _LAMEBUS_EMU_H_
#define _LAMEBUS_EMU_H_
#define EMU_MAXIO 16384
#define EMU_ROOTHANDLE 0
#define EMU_MAXIO 16384
#define EMU_ROOTHANDLE 0
/*
* The per-device data used by the emufs device driver.
@ -41,22 +40,21 @@
*/
struct emu_softc {
/* Initialized by lower-level attach code */
void *e_busdata;
uint32_t e_buspos;
int e_unit;
/* Initialized by lower-level attach code */
void *e_busdata;
uint32_t e_buspos;
int e_unit;
/* Initialized by config_emu() */
struct lock *e_lock;
struct semaphore *e_sem;
void *e_iobuf;
/* Initialized by config_emu() */
struct lock *e_lock;
struct semaphore *e_sem;
void *e_iobuf;
/* Written by the interrupt handler */
uint32_t e_result;
/* Written by the interrupt handler */
uint32_t e_result;
};
/* Functions called by lower-level drivers */
void emu_irq(/*struct emu_softc*/ void *);
#endif /* _LAMEBUS_EMU_H_ */

View File

@ -38,29 +38,27 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct emu_softc *
attach_emu_to_lamebus(int emuno, struct lamebus_softc *sc)
{
struct emu_softc *es;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_EMUFS,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct emu_softc *attach_emu_to_lamebus(int emuno, struct lamebus_softc *sc) {
struct emu_softc *es;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_EMUFS, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
es = kmalloc(sizeof(struct emu_softc));
if (es==NULL) {
return NULL;
}
es = kmalloc(sizeof(struct emu_softc));
if (es == NULL) {
return NULL;
}
es->e_busdata = sc;
es->e_buspos = slot;
es->e_unit = emuno;
es->e_busdata = sc;
es->e_buspos = slot;
es->e_unit = emuno;
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, es, emu_irq);
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, es, emu_irq);
return es;
return es;
}

View File

@ -40,147 +40,124 @@
#include <lamebus/lamebus.h>
/* Register offsets within each config region */
#define CFGREG_VID 0 /* Vendor ID */
#define CFGREG_DID 4 /* Device ID */
#define CFGREG_DRL 8 /* Device Revision Level */
#define CFGREG_VID 0 /* Vendor ID */
#define CFGREG_DID 4 /* Device ID */
#define CFGREG_DRL 8 /* Device Revision Level */
/* LAMEbus controller private registers (offsets within its config region) */
#define CTLREG_RAMSZ 0x200
#define CTLREG_IRQS 0x204
#define CTLREG_PWR 0x208
#define CTLREG_IRQE 0x20c
#define CTLREG_CPUS 0x210
#define CTLREG_CPUE 0x214
#define CTLREG_SELF 0x218
#define CTLREG_RAMSZ 0x200
#define CTLREG_IRQS 0x204
#define CTLREG_PWR 0x208
#define CTLREG_IRQE 0x20c
#define CTLREG_CPUS 0x210
#define CTLREG_CPUE 0x214
#define CTLREG_SELF 0x218
/* LAMEbus CPU control registers (offsets within each per-cpu region) */
#define CTLCPU_CIRQE 0x000
#define CTLCPU_CIPI 0x004
#define CTLCPU_CRAM 0x300
#define CTLCPU_CIRQE 0x000
#define CTLCPU_CIPI 0x004
#define CTLCPU_CRAM 0x300
/*
* Read a config register for the given slot.
*/
static
inline
uint32_t
read_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset)
{
/* Note that lb might be NULL on some platforms in some contexts. */
offset += LB_CONFIG_SIZE*slot;
return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
static inline uint32_t read_cfg_register(struct lamebus_softc *lb, int slot,
uint32_t offset) {
/* Note that lb might be NULL on some platforms in some contexts. */
offset += LB_CONFIG_SIZE * slot;
return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
}
/*
* Write a config register for a given slot.
*/
static
inline
void
write_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset,
uint32_t val)
{
offset += LB_CONFIG_SIZE*slot;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_cfg_register(struct lamebus_softc *lb, int slot,
uint32_t offset, uint32_t val) {
offset += LB_CONFIG_SIZE * slot;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Read one of the bus controller's registers.
*/
static
inline
uint32_t
read_ctl_register(struct lamebus_softc *lb, uint32_t offset)
{
/* Note that lb might be NULL on some platforms in some contexts. */
return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
static inline uint32_t read_ctl_register(struct lamebus_softc *lb,
uint32_t offset) {
/* Note that lb might be NULL on some platforms in some contexts. */
return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
}
/*
* Write one of the bus controller's registers.
*/
static
inline
void
write_ctl_register(struct lamebus_softc *lb, uint32_t offset, uint32_t val)
{
write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_ctl_register(struct lamebus_softc *lb, uint32_t offset,
uint32_t val) {
write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Write one of the bus controller's CPU control registers.
*/
static
inline
void
write_ctlcpu_register(struct lamebus_softc *lb, unsigned hw_cpunum,
uint32_t offset, uint32_t val)
{
offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_ctlcpu_register(struct lamebus_softc *lb,
unsigned hw_cpunum, uint32_t offset,
uint32_t val) {
offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Find and create secondary CPUs.
*/
void
lamebus_find_cpus(struct lamebus_softc *lamebus)
{
uint32_t mainboard_vid, mainboard_did;
uint32_t cpumask, self, bit, val;
unsigned i, numcpus, bootcpu;
unsigned hwnum[32];
void lamebus_find_cpus(struct lamebus_softc *lamebus) {
uint32_t mainboard_vid, mainboard_did;
uint32_t cpumask, self, bit, val;
unsigned i, numcpus, bootcpu;
unsigned hwnum[32];
mainboard_vid = read_cfg_register(lamebus, LB_CONTROLLER_SLOT,
CFGREG_VID);
mainboard_did = read_cfg_register(lamebus, LB_CONTROLLER_SLOT,
CFGREG_DID);
if (mainboard_vid == LB_VENDOR_CS161 &&
mainboard_did == LBCS161_UPBUSCTL) {
/* Old uniprocessor mainboard; no cpu registers. */
lamebus->ls_uniprocessor = 1;
return;
}
mainboard_vid = read_cfg_register(lamebus, LB_CONTROLLER_SLOT, CFGREG_VID);
mainboard_did = read_cfg_register(lamebus, LB_CONTROLLER_SLOT, CFGREG_DID);
if (mainboard_vid == LB_VENDOR_CS161 && mainboard_did == LBCS161_UPBUSCTL) {
/* Old uniprocessor mainboard; no cpu registers. */
lamebus->ls_uniprocessor = 1;
return;
}
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
numcpus = 0;
bootcpu = 0;
for (i=0; i<32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
bootcpu = numcpus;
curcpu->c_hardware_number = i;
}
hwnum[numcpus] = i;
numcpus++;
}
}
numcpus = 0;
bootcpu = 0;
for (i = 0; i < 32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
bootcpu = numcpus;
curcpu->c_hardware_number = i;
}
hwnum[numcpus] = i;
numcpus++;
}
}
for (i=0; i<numcpus; i++) {
if (i != bootcpu) {
cpu_create(hwnum[i]);
}
}
for (i = 0; i < numcpus; i++) {
if (i != bootcpu) {
cpu_create(hwnum[i]);
}
}
/*
* By default, route all interrupts only to the boot cpu. We
* could be arbitrarily more elaborate, up to things like
* dynamic load balancing.
*/
/*
* By default, route all interrupts only to the boot cpu. We
* could be arbitrarily more elaborate, up to things like
* dynamic load balancing.
*/
for (i=0; i<numcpus; i++) {
if (i != bootcpu) {
val = 0;
}
else {
val = 0xffffffff;
}
write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
}
for (i = 0; i < numcpus; i++) {
if (i != bootcpu) {
val = 0;
} else {
val = 0xffffffff;
}
write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
}
}
/*
@ -193,43 +170,40 @@ lamebus_find_cpus(struct lamebus_softc *lamebus)
* LAMEbus; if in some environment there are other CPUs about as well
* this logic will have to be made more complex.
*/
void
lamebus_start_cpus(struct lamebus_softc *lamebus)
{
uint32_t cpumask, self, bit;
uint32_t ctlcpuoffset;
uint32_t *cram;
unsigned i;
unsigned cpunum;
void lamebus_start_cpus(struct lamebus_softc *lamebus) {
uint32_t cpumask, self, bit;
uint32_t ctlcpuoffset;
uint32_t *cram;
unsigned i;
unsigned cpunum;
if (lamebus->ls_uniprocessor) {
return;
}
if (lamebus->ls_uniprocessor) {
return;
}
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
/* Poke in the startup address. */
cpunum = 1;
for (i=0; i<32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
continue;
}
ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
cram = lamebus_map_area(lamebus,
LB_CONTROLLER_SLOT,
ctlcpuoffset + CTLCPU_CRAM);
cram[0] = (uint32_t)cpu_start_secondary;
cram[1] = cpunum++;
}
}
/* Ensure all the above writes get flushed. */
membar_store_store();
/* Poke in the startup address. */
cpunum = 1;
for (i = 0; i < 32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
continue;
}
ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
cram = lamebus_map_area(lamebus, LB_CONTROLLER_SLOT,
ctlcpuoffset + CTLCPU_CRAM);
cram[0] = (uint32_t)cpu_start_secondary;
cram[1] = cpunum++;
}
}
/* Ensure all the above writes get flushed. */
membar_store_store();
/* Now, enable them all. */
write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
/* Now, enable them all. */
write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
}
/*
@ -247,58 +221,55 @@ lamebus_start_cpus(struct lamebus_softc *lamebus)
* more specific checks.
*/
int
lamebus_probe(struct lamebus_softc *sc,
uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret)
{
int slot;
uint32_t val;
int lamebus_probe(struct lamebus_softc *sc, uint32_t vendorid,
uint32_t deviceid, uint32_t lowver, uint32_t *version_ret) {
int slot;
uint32_t val;
/*
* Because the slot information in sc is used when dispatching
* interrupts, disable interrupts while working with it.
*/
/*
* Because the slot information in sc is used when dispatching
* interrupts, disable interrupts while working with it.
*/
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
for (slot=0; slot<LB_NSLOTS; slot++) {
if (sc->ls_slotsinuse & (1<<slot)) {
/* Slot already in use; skip */
continue;
}
for (slot = 0; slot < LB_NSLOTS; slot++) {
if (sc->ls_slotsinuse & (1 << slot)) {
/* Slot already in use; skip */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_VID);
if (val!=vendorid) {
/* Wrong vendor id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_VID);
if (val != vendorid) {
/* Wrong vendor id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DID);
if (val != deviceid) {
/* Wrong device id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DID);
if (val != deviceid) {
/* Wrong device id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DRL);
if (val < lowver) {
/* Unsupported device revision */
continue;
}
if (version_ret != NULL) {
*version_ret = val;
}
val = read_cfg_register(sc, slot, CFGREG_DRL);
if (val < lowver) {
/* Unsupported device revision */
continue;
}
if (version_ret != NULL) {
*version_ret = val;
}
/* Found something */
/* Found something */
spinlock_release(&sc->ls_lock);
return slot;
}
spinlock_release(&sc->ls_lock);
return slot;
}
/* Found nothing */
/* Found nothing */
spinlock_release(&sc->ls_lock);
return -1;
spinlock_release(&sc->ls_lock);
return -1;
}
/*
@ -306,360 +277,328 @@ lamebus_probe(struct lamebus_softc *sc,
* This prevents the probe routine from returning the same device over
* and over again.
*/
void
lamebus_mark(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_mark(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)!=0) {
panic("lamebus_mark: slot %d already in use\n", slot);
}
if ((sc->ls_slotsinuse & mask) != 0) {
panic("lamebus_mark: slot %d already in use\n", slot);
}
sc->ls_slotsinuse |= mask;
sc->ls_slotsinuse |= mask;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Mark that a slot is no longer in use.
*/
void
lamebus_unmark(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_unmark(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_mark: slot %d not marked in use\n", slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_mark: slot %d not marked in use\n", slot);
}
sc->ls_slotsinuse &= ~mask;
sc->ls_slotsinuse &= ~mask;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Register a function (and a device context pointer) to be called
* when a particular slot signals an interrupt.
*/
void
lamebus_attach_interrupt(struct lamebus_softc *sc, int slot,
void *devdata,
void (*irqfunc)(void *devdata))
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_attach_interrupt(struct lamebus_softc *sc, int slot, void *devdata,
void (*irqfunc)(void *devdata)) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_attach_interrupt: slot %d not marked in use\n",
slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_attach_interrupt: slot %d not marked in use\n", slot);
}
KASSERT(sc->ls_devdata[slot]==NULL);
KASSERT(sc->ls_irqfuncs[slot]==NULL);
KASSERT(sc->ls_devdata[slot] == NULL);
KASSERT(sc->ls_irqfuncs[slot] == NULL);
sc->ls_devdata[slot] = devdata;
sc->ls_irqfuncs[slot] = irqfunc;
sc->ls_devdata[slot] = devdata;
sc->ls_irqfuncs[slot] = irqfunc;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Unregister a function that was being called when a particular slot
* signaled an interrupt.
*/
void
lamebus_detach_interrupt(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_detach_interrupt(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_detach_interrupt: slot %d not marked in use\n",
slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_detach_interrupt: slot %d not marked in use\n", slot);
}
KASSERT(sc->ls_irqfuncs[slot]!=NULL);
KASSERT(sc->ls_irqfuncs[slot] != NULL);
sc->ls_devdata[slot] = NULL;
sc->ls_irqfuncs[slot] = NULL;
sc->ls_devdata[slot] = NULL;
sc->ls_irqfuncs[slot] = NULL;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Mask/unmask an interrupt using the global IRQE register.
*/
void
lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot)
{
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
void lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot) {
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits &= ~mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits &= ~mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
}
void
lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot)
{
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
void lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot) {
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits |= mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits |= mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
}
/*
* LAMEbus interrupt handling function. (Machine-independent!)
*/
void
lamebus_interrupt(struct lamebus_softc *lamebus)
{
/*
* Note that despite the fact that "spl" stands for "set
* priority level", we don't actually support interrupt
* priorities. When an interrupt happens, we look through the
* slots to find the first interrupting device and call its
* interrupt routine, no matter what that device is.
*
* Note that the entire LAMEbus uses only one on-cpu interrupt line.
* Thus, we do not use any on-cpu interrupt priority system either.
*/
void lamebus_interrupt(struct lamebus_softc *lamebus) {
/*
* Note that despite the fact that "spl" stands for "set
* priority level", we don't actually support interrupt
* priorities. When an interrupt happens, we look through the
* slots to find the first interrupting device and call its
* interrupt routine, no matter what that device is.
*
* Note that the entire LAMEbus uses only one on-cpu interrupt line.
* Thus, we do not use any on-cpu interrupt priority system either.
*/
int slot;
uint32_t mask;
uint32_t irqs;
void (*handler)(void *);
void *data;
int slot;
uint32_t mask;
uint32_t irqs;
void (*handler)(void *);
void *data;
/* For keeping track of how many bogus things happen in a row. */
static int duds = 0;
int duds_this_time = 0;
/* For keeping track of how many bogus things happen in a row. */
static int duds = 0;
int duds_this_time = 0;
/* and we better have a valid bus instance. */
KASSERT(lamebus != NULL);
/* and we better have a valid bus instance. */
KASSERT(lamebus != NULL);
/* Lock the softc */
spinlock_acquire(&lamebus->ls_lock);
/* Lock the softc */
spinlock_acquire(&lamebus->ls_lock);
/*
* Read the LAMEbus controller register that tells us which
* slots are asserting an interrupt condition.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
/*
* Read the LAMEbus controller register that tells us which
* slots are asserting an interrupt condition.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
if (irqs == 0) {
/*
* Huh? None of them? Must be a glitch.
*/
kprintf("lamebus: stray interrupt on cpu %u\n",
curcpu->c_number);
duds++;
duds_this_time++;
if (irqs == 0) {
/*
* Huh? None of them? Must be a glitch.
*/
kprintf("lamebus: stray interrupt on cpu %u\n", curcpu->c_number);
duds++;
duds_this_time++;
/*
* We could just return now, but instead we'll
* continue ahead. Because irqs == 0, nothing in the
* loop will execute, and passing through it gets us
* to the code that checks how many duds we've
* seen. This is important, because we just might get
* a stray interrupt that latches itself on. If that
* happens, we're pretty much toast, but it's better
* to panic and hopefully reset the system than to
* loop forever printing "stray interrupt".
*/
}
/*
* We could just return now, but instead we'll
* continue ahead. Because irqs == 0, nothing in the
* loop will execute, and passing through it gets us
* to the code that checks how many duds we've
* seen. This is important, because we just might get
* a stray interrupt that latches itself on. If that
* happens, we're pretty much toast, but it's better
* to panic and hopefully reset the system than to
* loop forever printing "stray interrupt".
*/
}
/*
* Go through the bits in the value we got back to see which
* ones are set.
*/
/*
* Go through the bits in the value we got back to see which
* ones are set.
*/
for (mask=1, slot=0; slot<LB_NSLOTS; mask<<=1, slot++) {
if ((irqs & mask) == 0) {
/* Nope. */
continue;
}
for (mask = 1, slot = 0; slot < LB_NSLOTS; mask <<= 1, slot++) {
if ((irqs & mask) == 0) {
/* Nope. */
continue;
}
/*
* This slot is signalling an interrupt.
*/
/*
* This slot is signalling an interrupt.
*/
if ((lamebus->ls_slotsinuse & mask)==0) {
/*
* No device driver is using this slot.
*/
duds++;
duds_this_time++;
continue;
}
if ((lamebus->ls_slotsinuse & mask) == 0) {
/*
* No device driver is using this slot.
*/
duds++;
duds_this_time++;
continue;
}
if (lamebus->ls_irqfuncs[slot]==NULL) {
/*
* The device driver hasn't installed an interrupt
* handler.
*/
duds++;
duds_this_time++;
continue;
}
if (lamebus->ls_irqfuncs[slot] == NULL) {
/*
* The device driver hasn't installed an interrupt
* handler.
*/
duds++;
duds_this_time++;
continue;
}
/*
* Call the interrupt handler. Release the spinlock
* while we do so, in case other CPUs are handling
* interrupts on other devices.
*/
handler = lamebus->ls_irqfuncs[slot];
data = lamebus->ls_devdata[slot];
spinlock_release(&lamebus->ls_lock);
/*
* Call the interrupt handler. Release the spinlock
* while we do so, in case other CPUs are handling
* interrupts on other devices.
*/
handler = lamebus->ls_irqfuncs[slot];
data = lamebus->ls_devdata[slot];
spinlock_release(&lamebus->ls_lock);
handler(data);
handler(data);
spinlock_acquire(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
/*
* Reload the mask of pending IRQs - if we just called
* hardclock, we might not have come back to this
* context for some time, and it might have changed.
*/
/*
* Reload the mask of pending IRQs - if we just called
* hardclock, we might not have come back to this
* context for some time, and it might have changed.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
}
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
}
/*
* If we get interrupts for a slot with no driver or no
* interrupt handler, it's fairly serious. Because LAMEbus
* uses level-triggered interrupts, if we don't shut off the
* condition, we'll keep getting interrupted continuously and
* the system will make no progress. But we don't know how to
* do that if there's no driver or no interrupt handler.
*
* So, if we get too many dud interrupts, panic, since it's
* better to panic and reset than to hang.
*
* If we get through here without seeing any duds this time,
* the condition, whatever it was, has gone away. It might be
* some stupid device we don't have a driver for, or it might
* have been an electrical transient. In any case, warn and
* clear the dud count.
*/
/*
* If we get interrupts for a slot with no driver or no
* interrupt handler, it's fairly serious. Because LAMEbus
* uses level-triggered interrupts, if we don't shut off the
* condition, we'll keep getting interrupted continuously and
* the system will make no progress. But we don't know how to
* do that if there's no driver or no interrupt handler.
*
* So, if we get too many dud interrupts, panic, since it's
* better to panic and reset than to hang.
*
* If we get through here without seeing any duds this time,
* the condition, whatever it was, has gone away. It might be
* some stupid device we don't have a driver for, or it might
* have been an electrical transient. In any case, warn and
* clear the dud count.
*/
if (duds_this_time == 0 && duds > 0) {
kprintf("lamebus: %d dud interrupts\n", duds);
duds = 0;
}
if (duds_this_time == 0 && duds > 0) {
kprintf("lamebus: %d dud interrupts\n", duds);
duds = 0;
}
if (duds > 10000) {
panic("lamebus: too many (%d) dud interrupts\n", duds);
}
if (duds > 10000) {
panic("lamebus: too many (%d) dud interrupts\n", duds);
}
/* Unlock the softc */
spinlock_release(&lamebus->ls_lock);
/* Unlock the softc */
spinlock_release(&lamebus->ls_lock);
}
/*
* Have the bus controller power the system off.
*/
void
lamebus_poweroff(struct lamebus_softc *lamebus)
{
/*
* Write 0 to the power register to shut the system off.
*/
void lamebus_poweroff(struct lamebus_softc *lamebus) {
/*
* Write 0 to the power register to shut the system off.
*/
cpu_irqoff();
write_ctl_register(lamebus, CTLREG_PWR, 0);
cpu_irqoff();
write_ctl_register(lamebus, CTLREG_PWR, 0);
/* The power doesn't go off instantly... so halt the cpu. */
cpu_halt();
/* The power doesn't go off instantly... so halt the cpu. */
cpu_halt();
}
/*
* Ask the bus controller how much memory we have.
*/
uint32_t
lamebus_ramsize(void)
{
/*
* Note that this has to work before bus initialization.
* On machines where lamebus_read_register doesn't work
* before bus initialization, this function can't be used
* for initial RAM size lookup.
*/
uint32_t lamebus_ramsize(void) {
/*
* Note that this has to work before bus initialization.
* On machines where lamebus_read_register doesn't work
* before bus initialization, this function can't be used
* for initial RAM size lookup.
*/
return read_ctl_register(NULL, CTLREG_RAMSZ);
return read_ctl_register(NULL, CTLREG_RAMSZ);
}
/*
* Turn on or off the interprocessor interrupt line for a given CPU.
*/
void
lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target)
{
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number,
CTLCPU_CIPI, 1);
void lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target) {
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number, CTLCPU_CIPI, 1);
}
void
lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target)
{
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number,
CTLCPU_CIPI, 0);
void lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target) {
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number, CTLCPU_CIPI, 0);
}
/*
* Initial setup.
* Should be called from mainbus_bootstrap().
*/
struct lamebus_softc *
lamebus_init(void)
{
struct lamebus_softc *lamebus;
int i;
struct lamebus_softc *lamebus_init(void) {
struct lamebus_softc *lamebus;
int i;
/* Allocate space for lamebus data */
lamebus = kmalloc(sizeof(struct lamebus_softc));
if (lamebus==NULL) {
panic("lamebus_init: Out of memory\n");
}
/* Allocate space for lamebus data */
lamebus = kmalloc(sizeof(struct lamebus_softc));
if (lamebus == NULL) {
panic("lamebus_init: Out of memory\n");
}
spinlock_init(&lamebus->ls_lock);
spinlock_init(&lamebus->ls_lock);
/*
* Initialize the LAMEbus data structure.
*/
lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
/*
* Initialize the LAMEbus data structure.
*/
lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
for (i=0; i<LB_NSLOTS; i++) {
lamebus->ls_devdata[i] = NULL;
lamebus->ls_irqfuncs[i] = NULL;
}
for (i = 0; i < LB_NSLOTS; i++) {
lamebus->ls_devdata[i] = NULL;
lamebus->ls_irqfuncs[i] = NULL;
}
lamebus->ls_uniprocessor = 0;
lamebus->ls_uniprocessor = 0;
return lamebus;
return lamebus;
}

View File

@ -39,39 +39,38 @@
* Machine-independent definitions.
*/
/* Vendors */
#define LB_VENDOR_CS161 1
#define LB_VENDOR_CS161 1
/* CS161 devices */
#define LBCS161_UPBUSCTL 1
#define LBCS161_TIMER 2
#define LBCS161_DISK 3
#define LBCS161_SERIAL 4
#define LBCS161_SCREEN 5
#define LBCS161_NET 6
#define LBCS161_EMUFS 7
#define LBCS161_TRACE 8
#define LBCS161_RANDOM 9
#define LBCS161_MPBUSCTL 10
#define LBCS161_UPBUSCTL 1
#define LBCS161_TIMER 2
#define LBCS161_DISK 3
#define LBCS161_SERIAL 4
#define LBCS161_SCREEN 5
#define LBCS161_NET 6
#define LBCS161_EMUFS 7
#define LBCS161_TRACE 8
#define LBCS161_RANDOM 9
#define LBCS161_MPBUSCTL 10
/* LAMEbus controller always goes in slot 31 */
#define LB_CONTROLLER_SLOT 31
#define LB_CONTROLLER_SLOT 31
/* Number of slots */
#define LB_NSLOTS 32
#define LB_NSLOTS 32
/* LAMEbus controller per-slot config space */
#define LB_CONFIG_SIZE 1024
#define LB_CONFIG_SIZE 1024
/* LAMEbus controller per-cpu control space */
#define LB_CTLCPU_SIZE 1024
#define LB_CTLCPU_SIZE 1024
/* LAMEbus controller slot offset to per-cpu control space */
#define LB_CTLCPU_OFFSET 32768
#define LB_CTLCPU_OFFSET 32768
/* LAMEbus mapping size per slot */
#define LB_SLOT_SIZE 65536
#define LB_SLOT_SIZE 65536
/* Pointer to kind of function called on interrupt */
typedef void (*lb_irqfunc)(void *devdata);
@ -80,15 +79,15 @@ typedef void (*lb_irqfunc)(void *devdata);
* Driver data
*/
struct lamebus_softc {
struct spinlock ls_lock;
struct spinlock ls_lock;
/* Accessed from interrupts; synchronized with ls_lock */
uint32_t ls_slotsinuse;
void *ls_devdata[LB_NSLOTS];
lb_irqfunc ls_irqfuncs[LB_NSLOTS];
/* Accessed from interrupts; synchronized with ls_lock */
uint32_t ls_slotsinuse;
void *ls_devdata[LB_NSLOTS];
lb_irqfunc ls_irqfuncs[LB_NSLOTS];
/* Read-only once set early in boot */
unsigned ls_uniprocessor;
/* Read-only once set early in boot */
unsigned ls_uniprocessor;
};
/*
@ -113,9 +112,8 @@ void lamebus_start_cpus(struct lamebus_softc *lamebus);
*
* Returns a slot number (0-31) or -1 if no such device is found.
*/
int lamebus_probe(struct lamebus_softc *,
uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret);
int lamebus_probe(struct lamebus_softc *, uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret);
/*
* Mark a slot in-use (that is, has a device driver attached to it),
@ -128,9 +126,8 @@ void lamebus_unmark(struct lamebus_softc *, int slot);
/*
* Attach to an interrupt.
*/
void lamebus_attach_interrupt(struct lamebus_softc *, int slot,
void *devdata,
void (*irqfunc)(void *devdata));
void lamebus_attach_interrupt(struct lamebus_softc *, int slot, void *devdata,
void (*irqfunc)(void *devdata));
/*
* Detach from interrupt.
*/
@ -168,15 +165,13 @@ void lamebus_clear_ipi(struct lamebus_softc *, struct cpu *targetcpu);
* (Machine dependent.)
*/
uint32_t lamebus_read_register(struct lamebus_softc *, int slot,
uint32_t offset);
void lamebus_write_register(struct lamebus_softc *, int slot,
uint32_t offset, uint32_t val);
uint32_t offset);
void lamebus_write_register(struct lamebus_softc *, int slot, uint32_t offset,
uint32_t val);
/*
* Map a buffer that starts at offset OFFSET within slot SLOT.
*/
void *lamebus_map_area(struct lamebus_softc *, int slot,
uint32_t offset);
void *lamebus_map_area(struct lamebus_softc *, int slot, uint32_t offset);
#endif /* _LAMEBUS_H_ */

View File

@ -43,68 +43,60 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LHD_REG_NSECT 0 /* Number of sectors */
#define LHD_REG_STAT 4 /* Status */
#define LHD_REG_SECT 8 /* Sector for I/O */
#define LHD_REG_RPM 12 /* Disk rotation speed (revs per minute) */
#define LHD_REG_NSECT 0 /* Number of sectors */
#define LHD_REG_STAT 4 /* Status */
#define LHD_REG_SECT 8 /* Sector for I/O */
#define LHD_REG_RPM 12 /* Disk rotation speed (revs per minute) */
/* Status codes */
#define LHD_IDLE 0 /* Device idle */
#define LHD_WORKING 1 /* Operation in progress */
#define LHD_OK 4 /* Operation succeeded */
#define LHD_INVSECT 12 /* Invalid sector requested */
#define LHD_MEDIA 20 /* Media error */
#define LHD_ISWRITE 2 /* OR with above: I/O is a write */
#define LHD_STATEMASK 0x1d /* mask for masking out LHD_ISWRITE */
#define LHD_IDLE 0 /* Device idle */
#define LHD_WORKING 1 /* Operation in progress */
#define LHD_OK 4 /* Operation succeeded */
#define LHD_INVSECT 12 /* Invalid sector requested */
#define LHD_MEDIA 20 /* Media error */
#define LHD_ISWRITE 2 /* OR with above: I/O is a write */
#define LHD_STATEMASK 0x1d /* mask for masking out LHD_ISWRITE */
/* Buffer (offset within slot) */
#define LHD_BUFFER 32768
#define LHD_BUFFER 32768
/*
* Shortcut for reading a register.
*/
static
inline
uint32_t lhd_rdreg(struct lhd_softc *lh, uint32_t reg)
{
return bus_read_register(lh->lh_busdata, lh->lh_buspos, reg);
static inline uint32_t lhd_rdreg(struct lhd_softc *lh, uint32_t reg) {
return bus_read_register(lh->lh_busdata, lh->lh_buspos, reg);
}
/*
* Shortcut for writing a register.
*/
static
inline
void lhd_wreg(struct lhd_softc *lh, uint32_t reg, uint32_t val)
{
bus_write_register(lh->lh_busdata, lh->lh_buspos, reg, val);
static inline void lhd_wreg(struct lhd_softc *lh, uint32_t reg, uint32_t val) {
bus_write_register(lh->lh_busdata, lh->lh_buspos, reg, val);
}
/*
* Convert a result code from the hardware to an errno value.
*/
static
int lhd_code_to_errno(struct lhd_softc *lh, int code)
{
switch (code & LHD_STATEMASK) {
case LHD_OK: return 0;
case LHD_INVSECT: return EINVAL;
case LHD_MEDIA: return EIO;
}
kprintf("lhd%d: Unknown result code %d\n", lh->lh_unit, code);
return EAGAIN;
static int lhd_code_to_errno(struct lhd_softc *lh, int code) {
switch (code & LHD_STATEMASK) {
case LHD_OK:
return 0;
case LHD_INVSECT:
return EINVAL;
case LHD_MEDIA:
return EIO;
}
kprintf("lhd%d: Unknown result code %d\n", lh->lh_unit, code);
return EAGAIN;
}
/*
* Record that an I/O has completed: save the result and poke the
* completion semaphore.
*/
static
void
lhd_iodone(struct lhd_softc *lh, int err)
{
lh->lh_result = err;
V(lh->lh_done);
static void lhd_iodone(struct lhd_softc *lh, int err) {
lh->lh_result = err;
V(lh->lh_done);
}
/*
@ -112,57 +104,49 @@ lhd_iodone(struct lhd_softc *lh, int err)
* Read the status register; if an operation finished, clear the status
* register and report completion.
*/
void
lhd_irq(void *vlh)
{
struct lhd_softc *lh = vlh;
uint32_t val;
void lhd_irq(void *vlh) {
struct lhd_softc *lh = vlh;
uint32_t val;
val = lhd_rdreg(lh, LHD_REG_STAT);
val = lhd_rdreg(lh, LHD_REG_STAT);
switch (val & LHD_STATEMASK) {
case LHD_IDLE:
case LHD_WORKING:
break;
case LHD_OK:
case LHD_INVSECT:
case LHD_MEDIA:
lhd_wreg(lh, LHD_REG_STAT, 0);
lhd_iodone(lh, lhd_code_to_errno(lh, val));
break;
}
switch (val & LHD_STATEMASK) {
case LHD_IDLE:
case LHD_WORKING:
break;
case LHD_OK:
case LHD_INVSECT:
case LHD_MEDIA:
lhd_wreg(lh, LHD_REG_STAT, 0);
lhd_iodone(lh, lhd_code_to_errno(lh, val));
break;
}
}
/*
* Function called when we are open()'d.
*/
static
int
lhd_eachopen(struct device *d, int openflags)
{
/*
* Don't need to do anything.
*/
(void)d;
(void)openflags;
static int lhd_eachopen(struct device *d, int openflags) {
/*
* Don't need to do anything.
*/
(void)d;
(void)openflags;
return 0;
return 0;
}
/*
* Function for handling ioctls.
*/
static
int
lhd_ioctl(struct device *d, int op, userptr_t data)
{
/*
* We don't support any ioctls.
*/
(void)d;
(void)op;
(void)data;
return EIOCTL;
static int lhd_ioctl(struct device *d, int op, userptr_t data) {
/*
* We don't support any ioctls.
*/
(void)d;
(void)op;
(void)data;
return EIOCTL;
}
#if 0
@ -182,127 +166,122 @@ lhd_reset(struct lhd_softc *lh)
/*
* I/O function (for both reads and writes)
*/
static
int
lhd_io(struct device *d, struct uio *uio)
{
struct lhd_softc *lh = d->d_data;
static int lhd_io(struct device *d, struct uio *uio) {
struct lhd_softc *lh = d->d_data;
uint32_t sector = uio->uio_offset / LHD_SECTSIZE;
uint32_t sectoff = uio->uio_offset % LHD_SECTSIZE;
uint32_t len = uio->uio_resid / LHD_SECTSIZE;
uint32_t lenoff = uio->uio_resid % LHD_SECTSIZE;
uint32_t i;
uint32_t statval = LHD_WORKING;
int result;
uint32_t sector = uio->uio_offset / LHD_SECTSIZE;
uint32_t sectoff = uio->uio_offset % LHD_SECTSIZE;
uint32_t len = uio->uio_resid / LHD_SECTSIZE;
uint32_t lenoff = uio->uio_resid % LHD_SECTSIZE;
uint32_t i;
uint32_t statval = LHD_WORKING;
int result;
/* Don't allow I/O that isn't sector-aligned. */
if (sectoff != 0 || lenoff != 0) {
return EINVAL;
}
/* Don't allow I/O that isn't sector-aligned. */
if (sectoff != 0 || lenoff != 0) {
return EINVAL;
}
/* Don't allow I/O past the end of the disk. */
/* XXX this check can overflow */
if (sector+len > lh->lh_dev.d_blocks) {
return EINVAL;
}
/* Don't allow I/O past the end of the disk. */
/* XXX this check can overflow */
if (sector + len > lh->lh_dev.d_blocks) {
return EINVAL;
}
/* Set up the value to write into the status register. */
if (uio->uio_rw==UIO_WRITE) {
statval |= LHD_ISWRITE;
}
/* Set up the value to write into the status register. */
if (uio->uio_rw == UIO_WRITE) {
statval |= LHD_ISWRITE;
}
/* Loop over all the sectors we were asked to do. */
for (i=0; i<len; i++) {
/* Loop over all the sectors we were asked to do. */
for (i = 0; i < len; i++) {
/* Wait until nobody else is using the device. */
P(lh->lh_clear);
/* Wait until nobody else is using the device. */
P(lh->lh_clear);
/*
* Are we writing? If so, transfer the data to the
* on-card buffer.
*/
if (uio->uio_rw == UIO_WRITE) {
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
membar_store_store();
if (result) {
V(lh->lh_clear);
return result;
}
}
/*
* Are we writing? If so, transfer the data to the
* on-card buffer.
*/
if (uio->uio_rw == UIO_WRITE) {
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
membar_store_store();
if (result) {
V(lh->lh_clear);
return result;
}
}
/* Tell it what sector we want... */
lhd_wreg(lh, LHD_REG_SECT, sector+i);
/* Tell it what sector we want... */
lhd_wreg(lh, LHD_REG_SECT, sector + i);
/* and start the operation. */
lhd_wreg(lh, LHD_REG_STAT, statval);
/* and start the operation. */
lhd_wreg(lh, LHD_REG_STAT, statval);
/* Now wait until the interrupt handler tells us we're done. */
P(lh->lh_done);
/* Now wait until the interrupt handler tells us we're done. */
P(lh->lh_done);
/* Get the result value saved by the interrupt handler. */
result = lh->lh_result;
/* Get the result value saved by the interrupt handler. */
result = lh->lh_result;
/*
* Are we reading? If so, and if we succeeded,
* transfer the data out of the on-card buffer.
*/
if (result==0 && uio->uio_rw==UIO_READ) {
membar_load_load();
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
}
/*
* Are we reading? If so, and if we succeeded,
* transfer the data out of the on-card buffer.
*/
if (result == 0 && uio->uio_rw == UIO_READ) {
membar_load_load();
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
}
/* Tell another thread it's cleared to go ahead. */
V(lh->lh_clear);
/* Tell another thread it's cleared to go ahead. */
V(lh->lh_clear);
/* If we failed, return the error. */
if (result) {
return result;
}
}
/* If we failed, return the error. */
if (result) {
return result;
}
}
return 0;
return 0;
}
static const struct device_ops lhd_devops = {
.devop_eachopen = lhd_eachopen,
.devop_io = lhd_io,
.devop_ioctl = lhd_ioctl,
.devop_eachopen = lhd_eachopen,
.devop_io = lhd_io,
.devop_ioctl = lhd_ioctl,
};
/*
* Setup routine called by autoconf.c when an lhd is found.
*/
int
config_lhd(struct lhd_softc *lh, int lhdno)
{
char name[32];
int config_lhd(struct lhd_softc *lh, int lhdno) {
char name[32];
/* Figure out what our name is. */
snprintf(name, sizeof(name), "lhd%d", lhdno);
/* Figure out what our name is. */
snprintf(name, sizeof(name), "lhd%d", lhdno);
/* Get a pointer to the on-chip buffer. */
lh->lh_buf = bus_map_area(lh->lh_busdata, lh->lh_buspos, LHD_BUFFER);
/* Get a pointer to the on-chip buffer. */
lh->lh_buf = bus_map_area(lh->lh_busdata, lh->lh_buspos, LHD_BUFFER);
/* Create the semaphores. */
lh->lh_clear = sem_create("lhd-clear", 1);
if (lh->lh_clear == NULL) {
return ENOMEM;
}
lh->lh_done = sem_create("lhd-done", 0);
if (lh->lh_done == NULL) {
sem_destroy(lh->lh_clear);
lh->lh_clear = NULL;
return ENOMEM;
}
/* Create the semaphores. */
lh->lh_clear = sem_create("lhd-clear", 1);
if (lh->lh_clear == NULL) {
return ENOMEM;
}
lh->lh_done = sem_create("lhd-done", 0);
if (lh->lh_done == NULL) {
sem_destroy(lh->lh_clear);
lh->lh_clear = NULL;
return ENOMEM;
}
/* Set up the VFS device structure. */
lh->lh_dev.d_ops = &lhd_devops;
lh->lh_dev.d_blocks = bus_read_register(lh->lh_busdata, lh->lh_buspos,
LHD_REG_NSECT);
lh->lh_dev.d_blocksize = LHD_SECTSIZE;
lh->lh_dev.d_data = lh;
/* Set up the VFS device structure. */
lh->lh_dev.d_ops = &lhd_devops;
lh->lh_dev.d_blocks =
bus_read_register(lh->lh_busdata, lh->lh_buspos, LHD_REG_NSECT);
lh->lh_dev.d_blocksize = LHD_SECTSIZE;
lh->lh_dev.d_data = lh;
/* Add the VFS device structure to the VFS device list. */
return vfs_adddev(name, &lh->lh_dev, 1);
/* Add the VFS device structure to the VFS device list. */
return vfs_adddev(name, &lh->lh_dev, 1);
}

View File

@ -35,30 +35,30 @@
/*
* Our sector size
*/
#define LHD_SECTSIZE 512
#define LHD_SECTSIZE 512
/*
* Hardware device data associated with lhd (LAMEbus hard disk)
*/
struct lhd_softc {
/* Initialized by lower-level attach code */
void *lh_busdata; /* The bus we're on */
uint32_t lh_buspos; /* Our slot on that bus */
int lh_unit; /* What number lhd we are */
/* Initialized by lower-level attach code */
void *lh_busdata; /* The bus we're on */
uint32_t lh_buspos; /* Our slot on that bus */
int lh_unit; /* What number lhd we are */
/*
* Initialized by config_lhd
*/
/*
* Initialized by config_lhd
*/
void *lh_buf; /* Pointer to on-card I/O buffer */
int lh_result; /* Result from I/O operation */
struct semaphore *lh_clear; /* Synchronization */
struct semaphore *lh_done;
void *lh_buf; /* Pointer to on-card I/O buffer */
int lh_result; /* Result from I/O operation */
struct semaphore *lh_clear; /* Synchronization */
struct semaphore *lh_done;
struct device lh_dev; /* VFS device structure */
struct device lh_dev; /* VFS device structure */
};
/* Functions called by lower-level drivers */
void lhd_irq(/*struct lhd_softc*/ void *); /* Interrupt handler */
void lhd_irq(/*struct lhd_softc*/ void *); /* Interrupt handler */
#endif /* _LAMEBUS_LHD_H_ */

View File

@ -37,33 +37,31 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 2
#define LOW_VERSION 2
struct lhd_softc *
attach_lhd_to_lamebus(int lhdno, struct lamebus_softc *sc)
{
struct lhd_softc *lh;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_DISK,
LOW_VERSION, NULL);
if (slot < 0) {
/* None found */
return NULL;
}
struct lhd_softc *attach_lhd_to_lamebus(int lhdno, struct lamebus_softc *sc) {
struct lhd_softc *lh;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_DISK, LOW_VERSION, NULL);
if (slot < 0) {
/* None found */
return NULL;
}
lh = kmalloc(sizeof(struct lhd_softc));
if (lh==NULL) {
/* Out of memory */
return NULL;
}
lh = kmalloc(sizeof(struct lhd_softc));
if (lh == NULL) {
/* Out of memory */
return NULL;
}
/* Record what the lhd is attached to */
lh->lh_busdata = sc;
lh->lh_buspos = slot;
lh->lh_unit = lhdno;
/* Record what the lhd is attached to */
lh->lh_busdata = sc;
lh->lh_buspos = slot;
lh->lh_unit = lhdno;
/* Mark the slot in use and collect interrupts */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lh, lhd_irq);
/* Mark the slot in use and collect interrupts */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lh, lhd_irq);
return lh;
return lh;
}

View File

@ -33,14 +33,10 @@
/*#include <lamebus/lnet.h>*/ /* not yet */
#include "autoconf.h"
int
config_lnet(struct lnet_softc *sc, int lnetno)
{
(void)sc;
int config_lnet(struct lnet_softc *sc, int lnetno) {
(void)sc;
kprintf("lnet%d: No network support in system\n", lnetno);
kprintf("lnet%d: No network support in system\n", lnetno);
return ENODEV;
return ENODEV;
}

View File

@ -33,20 +33,19 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Highest revision we support */
#define HIGH_VERSION 1
#define HIGH_VERSION 1
struct lnet_softc *
attach_lnet_to_lamebus(int lnetno, struct lamebus_softc *sc)
{
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_NET,
LOW_VERSION, HIGH_VERSION);
if (slot < 0) {
return NULL;
}
struct lnet_softc *attach_lnet_to_lamebus(int lnetno,
struct lamebus_softc *sc) {
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_NET, LOW_VERSION,
HIGH_VERSION);
if (slot < 0) {
return NULL;
}
kprintf("lnet%d: No network support in system\n", lnetno);
kprintf("lnet%d: No network support in system\n", lnetno);
return NULL;
return NULL;
}

View File

@ -38,48 +38,39 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LR_REG_RAND 0 /* random register */
#define LR_REG_RAND 0 /* random register */
/* Constants */
#define LR_RANDMAX 0xffffffff
#define LR_RANDMAX 0xffffffff
int
config_lrandom(struct lrandom_softc *lr, int lrandomno)
{
(void)lrandomno;
(void)lr;
return 0;
int config_lrandom(struct lrandom_softc *lr, int lrandomno) {
(void)lrandomno;
(void)lr;
return 0;
}
uint32_t
lrandom_random(void *devdata)
{
struct lrandom_softc *lr = devdata;
return bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
uint32_t lrandom_random(void *devdata) {
struct lrandom_softc *lr = devdata;
return bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
}
uint32_t
lrandom_randmax(void *devdata)
{
(void)devdata;
return LR_RANDMAX;
uint32_t lrandom_randmax(void *devdata) {
(void)devdata;
return LR_RANDMAX;
}
int
lrandom_read(void *devdata, struct uio *uio)
{
struct lrandom_softc *lr = devdata;
uint32_t val;
int result;
int lrandom_read(void *devdata, struct uio *uio) {
struct lrandom_softc *lr = devdata;
uint32_t val;
int result;
while (uio->uio_resid > 0) {
val = bus_read_register(lr->lr_bus, lr->lr_buspos,
LR_REG_RAND);
result = uiomove(&val, sizeof(val), uio);
if (result) {
return result;
}
}
while (uio->uio_resid > 0) {
val = bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
result = uiomove(&val, sizeof(val), uio);
if (result) {
return result;
}
}
return 0;
return 0;
}

View File

@ -33,9 +33,9 @@
struct uio;
struct lrandom_softc {
/* Initialized by lower-level attach routine */
void *lr_bus;
uint32_t lr_buspos;
/* Initialized by lower-level attach routine */
void *lr_bus;
uint32_t lr_buspos;
};
/* Functions called by higher-level drivers */

View File

@ -34,29 +34,28 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct lrandom_softc *
attach_lrandom_to_lamebus(int lrandomno, struct lamebus_softc *sc)
{
struct lrandom_softc *lr;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_RANDOM,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct lrandom_softc *attach_lrandom_to_lamebus(int lrandomno,
struct lamebus_softc *sc) {
struct lrandom_softc *lr;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_RANDOM, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
lr = kmalloc(sizeof(struct lrandom_softc));
if (lr==NULL) {
return NULL;
}
lr = kmalloc(sizeof(struct lrandom_softc));
if (lr == NULL) {
return NULL;
}
(void)lrandomno; // unused
(void)lrandomno; // unused
lr->lr_bus = sc;
lr->lr_buspos = slot;
lr->lr_bus = sc;
lr->lr_buspos = slot;
lamebus_mark(sc, slot);
lamebus_mark(sc, slot);
return lr;
return lr;
}

View File

@ -41,37 +41,29 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LSCR_REG_POSN 0 /* Cursor position */
#define LSCR_REG_SIZE 4 /* Display size */
#define LSCR_REG_CHAR 8 /* Character in */
#define LSCR_REG_RIRQ 12 /* Read interrupt status */
#define LSCR_REG_POSN 0 /* Cursor position */
#define LSCR_REG_SIZE 4 /* Display size */
#define LSCR_REG_CHAR 8 /* Character in */
#define LSCR_REG_RIRQ 12 /* Read interrupt status */
/* Bits in the IRQ registers */
#define LSCR_IRQ_ENABLE 1
#define LSCR_IRQ_ACTIVE 2
#define LSCR_IRQ_ENABLE 1
#define LSCR_IRQ_ACTIVE 2
/* Offset within slot of screen buffer */
#define LSCR_SCREEN 32768
#define LSCR_SCREEN 32768
/* Convert a 32-bit X/Y pair to X and Y coordinates. */
static
inline
void
splitxy(uint32_t xy, unsigned *x, unsigned *y)
{
*x = xy >> 16;
*y = xy & 0xffff;
static inline void splitxy(uint32_t xy, unsigned *x, unsigned *y) {
*x = xy >> 16;
*y = xy & 0xffff;
}
/* Convert X and Y coordinates to a single 32-bit value. */
static
inline
uint32_t
mergexy(unsigned x, unsigned y)
{
uint32_t val = x;
static inline uint32_t mergexy(unsigned x, unsigned y) {
uint32_t val = x;
return (val << 16) | y;
return (val << 16) | y;
}
////////////////////////////////////////////////////////////
@ -79,29 +71,25 @@ mergexy(unsigned x, unsigned y)
/*
* Interrupt handler.
*/
void
lscreen_irq(void *vsc)
{
struct lscreen_softc *sc = vsc;
uint32_t ch, x;
void lscreen_irq(void *vsc) {
struct lscreen_softc *sc = vsc;
uint32_t ch, x;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
if (x & LSCR_IRQ_ACTIVE) {
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_CHAR);
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
if (x & LSCR_IRQ_ACTIVE) {
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_CHAR);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ,
LSCR_IRQ_ENABLE);
spinlock_release(&sc->ls_lock);
if (sc->ls_input) {
sc->ls_input(sc->ls_devdata, ch);
}
}
else {
spinlock_release(&sc->ls_lock);
}
spinlock_release(&sc->ls_lock);
if (sc->ls_input) {
sc->ls_input(sc->ls_devdata, ch);
}
} else {
spinlock_release(&sc->ls_lock);
}
}
////////////////////////////////////////////////////////////
@ -109,74 +97,68 @@ lscreen_irq(void *vsc)
/*
* Handle a newline on the screen.
*/
static
void
lscreen_newline(struct lscreen_softc *sc)
{
if (sc->ls_cy >= sc->ls_height-1) {
/*
* Scroll
*/
static void lscreen_newline(struct lscreen_softc *sc) {
if (sc->ls_cy >= sc->ls_height - 1) {
/*
* Scroll
*/
memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
sc->ls_width * (sc->ls_height-1));
bzero(sc->ls_screen + sc->ls_width * (sc->ls_height-1),
sc->ls_width);
}
else {
sc->ls_cy++;
}
sc->ls_cx=0;
memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
sc->ls_width * (sc->ls_height - 1));
bzero(sc->ls_screen + sc->ls_width * (sc->ls_height - 1), sc->ls_width);
} else {
sc->ls_cy++;
}
sc->ls_cx = 0;
}
/*
* Handle a printable character being written to the screen.
*/
static
void
lscreen_char(struct lscreen_softc *sc, int ch)
{
if (sc->ls_cx >= sc->ls_width) {
lscreen_newline(sc);
}
static void lscreen_char(struct lscreen_softc *sc, int ch) {
if (sc->ls_cx >= sc->ls_width) {
lscreen_newline(sc);
}
sc->ls_screen[sc->ls_cy*sc->ls_width + sc->ls_cx] = ch;
sc->ls_cx++;
sc->ls_screen[sc->ls_cy * sc->ls_width + sc->ls_cx] = ch;
sc->ls_cx++;
}
/*
* Send a character to the screen.
* This should probably know about backspace and tab.
*/
void
lscreen_write(void *vsc, int ch)
{
struct lscreen_softc *sc = vsc;
int ccx, ccy;
void lscreen_write(void *vsc, int ch) {
struct lscreen_softc *sc = vsc;
int ccx, ccy;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
switch (ch) {
case '\n': lscreen_newline(sc); break;
default: lscreen_char(sc, ch); break;
}
switch (ch) {
case '\n':
lscreen_newline(sc);
break;
default:
lscreen_char(sc, ch);
break;
}
/*
* ccx/ccy = corrected cursor position
* (The cursor marks the next space text will appear in. But
* at the very end of the line, it should not move off the edge.)
*/
ccx = sc->ls_cx;
ccy = sc->ls_cy;
if (ccx==sc->ls_width) {
ccx--;
}
/*
* ccx/ccy = corrected cursor position
* (The cursor marks the next space text will appear in. But
* at the very end of the line, it should not move off the edge.)
*/
ccx = sc->ls_cx;
ccy = sc->ls_cy;
if (ccx == sc->ls_width) {
ccx--;
}
/* Set the cursor position */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_POSN, mergexy(ccx, ccy));
/* Set the cursor position */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_POSN,
mergexy(ccx, ccy));
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
////////////////////////////////////////////////////////////
@ -184,42 +166,36 @@ lscreen_write(void *vsc, int ch)
/*
* Setup routine called by autoconf.c when an lscreen is found.
*/
int
config_lscreen(struct lscreen_softc *sc, int lscreenno)
{
uint32_t val;
int config_lscreen(struct lscreen_softc *sc, int lscreenno) {
uint32_t val;
(void)lscreenno;
(void)lscreenno;
spinlock_init(&sc->ls_lock);
spinlock_init(&sc->ls_lock);
/*
* Enable interrupting.
*/
/*
* Enable interrupting.
*/
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ,
LSCR_IRQ_ENABLE);
/*
* Get screen size.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_SIZE);
splitxy(val, &sc->ls_width, &sc->ls_height);
/*
* Get screen size.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_SIZE);
splitxy(val, &sc->ls_width, &sc->ls_height);
/*
* Get cursor position.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_POSN);
splitxy(val, &sc->ls_cx, &sc->ls_cy);
/*
* Get cursor position.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_POSN);
splitxy(val, &sc->ls_cx, &sc->ls_cy);
/*
* Get a pointer to the memory-mapped screen area.
*/
sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos,
LSCR_SCREEN);
/*
* Get a pointer to the memory-mapped screen area.
*/
sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos, LSCR_SCREEN);
return 0;
return 0;
}

View File

@ -34,24 +34,24 @@
* Hardware device data for memory-mapped fullscreen text console.
*/
struct lscreen_softc {
/* Initialized by config function */
struct spinlock ls_lock; // protects data and device regs
unsigned ls_width, ls_height; // screen size
unsigned ls_cx, ls_cy; // cursor position
char *ls_screen; // memory-mapped screen buffer
/* Initialized by config function */
struct spinlock ls_lock; // protects data and device regs
unsigned ls_width, ls_height; // screen size
unsigned ls_cx, ls_cy; // cursor position
char *ls_screen; // memory-mapped screen buffer
/* Initialized by lower-level attachment function */
void *ls_busdata; // bus we're on
uint32_t ls_buspos; // position on that bus
/* Initialized by lower-level attachment function */
void *ls_busdata; // bus we're on
uint32_t ls_buspos; // position on that bus
/* Initialized by higher-level attachment function */
void *ls_devdata; // data and functions for
void (*ls_start)(void *devdata); // upper device (perhaps
void (*ls_input)(void *devdata, int ch); // console)
/* Initialized by higher-level attachment function */
void *ls_devdata; // data and functions for
void (*ls_start)(void *devdata); // upper device (perhaps
void (*ls_input)(void *devdata, int ch); // console)
};
/* Functions called by lower-level drivers */
void lscreen_irq(/*struct lser_softc*/ void *sc); // interrupt handler
void lscreen_irq(/*struct lser_softc*/ void *sc); // interrupt handler
/* Functions called by higher-level drivers */
void lscreen_write(/*struct lser_softc*/ void *sc, int ch); // output function

View File

@ -37,34 +37,33 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Highest revision we support */
#define HIGH_VERSION 1
#define HIGH_VERSION 1
struct lscreen_softc *
attach_lscreen_to_lamebus(int lscreenno, struct lamebus_softc *sc)
{
struct lscreen_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SCREEN,
LOW_VERSION, HIGH_VERSION);
if (slot < 0) {
/* Not found */
return NULL;
}
struct lscreen_softc *attach_lscreen_to_lamebus(int lscreenno,
struct lamebus_softc *sc) {
struct lscreen_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SCREEN, LOW_VERSION,
HIGH_VERSION);
if (slot < 0) {
/* Not found */
return NULL;
}
ls = kmalloc(sizeof(struct lscreen_softc));
if (ls==NULL) {
/* Out of memory */
return NULL;
}
ls = kmalloc(sizeof(struct lscreen_softc));
if (ls == NULL) {
/* Out of memory */
return NULL;
}
/* Record what it's attached to */
ls->ls_busdata = sc;
ls->ls_buspos = slot;
/* Record what it's attached to */
ls->ls_busdata = sc;
ls->ls_buspos = slot;
/* Mark the slot in use and hook the interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lscreen_irq);
/* Mark the slot in use and hook the interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lscreen_irq);
return ls;
return ls;
}

View File

@ -35,158 +35,139 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LSER_REG_CHAR 0 /* Character in/out */
#define LSER_REG_WIRQ 4 /* Write interrupt status */
#define LSER_REG_RIRQ 8 /* Read interrupt status */
#define LSER_REG_CHAR 0 /* Character in/out */
#define LSER_REG_WIRQ 4 /* Write interrupt status */
#define LSER_REG_RIRQ 8 /* Read interrupt status */
/* Bits in the IRQ registers */
#define LSER_IRQ_ENABLE 1
#define LSER_IRQ_ACTIVE 2
#define LSER_IRQ_FORCE 4
#define LSER_IRQ_ENABLE 1
#define LSER_IRQ_ACTIVE 2
#define LSER_IRQ_FORCE 4
void
lser_irq(void *vsc)
{
struct lser_softc *sc = vsc;
uint32_t x;
bool clear_to_write = false;
bool got_a_read = false;
uint32_t ch = 0;
void lser_irq(void *vsc) {
struct lser_softc *sc = vsc;
uint32_t x;
bool clear_to_write = false;
bool got_a_read = false;
uint32_t ch = 0;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
sc->ls_wbusy = 0;
clear_to_write = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
sc->ls_wbusy = 0;
clear_to_write = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_CHAR);
got_a_read = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_RIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR);
got_a_read = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ, x);
}
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
if (clear_to_write && sc->ls_start != NULL) {
sc->ls_start(sc->ls_devdata);
}
if (got_a_read && sc->ls_input != NULL) {
sc->ls_input(sc->ls_devdata, ch);
}
if (clear_to_write && sc->ls_start != NULL) {
sc->ls_start(sc->ls_devdata);
}
if (got_a_read && sc->ls_input != NULL) {
sc->ls_input(sc->ls_devdata, ch);
}
}
void
lser_write(void *vls, int ch)
{
struct lser_softc *ls = vls;
void lser_write(void *vls, int ch) {
struct lser_softc *ls = vls;
spinlock_acquire(&ls->ls_lock);
spinlock_acquire(&ls->ls_lock);
if (ls->ls_wbusy) {
/*
* We're not clear to write.
*
* This should not happen. It's the job of the driver
* attached to us to not write until we call
* ls->ls_start.
*
* (Note: if we're the console, the panic will go to
* lser_writepolled for printing, because we hold a
* spinlock and interrupts are off; it won't recurse.)
*/
panic("lser: Not clear to write\n");
}
ls->ls_wbusy = true;
if (ls->ls_wbusy) {
/*
* We're not clear to write.
*
* This should not happen. It's the job of the driver
* attached to us to not write until we call
* ls->ls_start.
*
* (Note: if we're the console, the panic will go to
* lser_writepolled for printing, because we hold a
* spinlock and interrupts are off; it won't recurse.)
*/
panic("lser: Not clear to write\n");
}
ls->ls_wbusy = true;
bus_write_register(ls->ls_busdata, ls->ls_buspos, LSER_REG_CHAR, ch);
bus_write_register(ls->ls_busdata, ls->ls_buspos, LSER_REG_CHAR, ch);
spinlock_release(&ls->ls_lock);
spinlock_release(&ls->ls_lock);
}
static
void
lser_poll_until_write(struct lser_softc *sc)
{
uint32_t val;
static void lser_poll_until_write(struct lser_softc *sc) {
uint32_t val;
KASSERT(spinlock_do_i_hold(&sc->ls_lock));
KASSERT(spinlock_do_i_hold(&sc->ls_lock));
do {
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ);
}
while ((val & LSER_IRQ_ACTIVE) == 0);
do {
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
} while ((val & LSER_IRQ_ACTIVE) == 0);
}
void
lser_writepolled(void *vsc, int ch)
{
struct lser_softc *sc = vsc;
bool irqpending;
void lser_writepolled(void *vsc, int ch) {
struct lser_softc *sc = vsc;
bool irqpending;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if (sc->ls_wbusy) {
irqpending = true;
lser_poll_until_write(sc);
/* Clear the ready condition, but leave the IRQ asserted */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ,
LSER_IRQ_FORCE|LSER_IRQ_ENABLE);
}
else {
irqpending = false;
/* Clear the interrupt enable bit */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, 0);
}
if (sc->ls_wbusy) {
irqpending = true;
lser_poll_until_write(sc);
/* Clear the ready condition, but leave the IRQ asserted */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_FORCE | LSER_IRQ_ENABLE);
} else {
irqpending = false;
/* Clear the interrupt enable bit */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, 0);
}
/* Send the character. */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR, ch);
/* Send the character. */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR, ch);
/* Wait until it's done. */
lser_poll_until_write(sc);
/* Wait until it's done. */
lser_poll_until_write(sc);
/*
* If there wasn't already an IRQ pending, clear the ready
* condition and turn interruption back on. But if there was,
* leave the register alone, with the ready condition set (and
* the force bit still on); in due course we'll get to the
* interrupt handler and they'll be cleared.
*/
if (!irqpending) {
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, LSER_IRQ_ENABLE);
}
/*
* If there wasn't already an IRQ pending, clear the ready
* condition and turn interruption back on. But if there was,
* leave the register alone, with the ready condition set (and
* the force bit still on); in due course we'll get to the
* interrupt handler and they'll be cleared.
*/
if (!irqpending) {
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_ENABLE);
}
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
int
config_lser(struct lser_softc *sc, int lserno)
{
(void)lserno;
int config_lser(struct lser_softc *sc, int lserno) {
(void)lserno;
/*
* Enable interrupting.
*/
/*
* Enable interrupting.
*/
spinlock_init(&sc->ls_lock);
sc->ls_wbusy = false;
spinlock_init(&sc->ls_lock);
sc->ls_wbusy = false;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_RIRQ, LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ,
LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_ENABLE);
return 0;
return 0;
}

View File

@ -33,18 +33,18 @@
#include <spinlock.h>
struct lser_softc {
/* Initialized by config function */
struct spinlock ls_lock; /* protects ls_wbusy and device regs */
volatile bool ls_wbusy; /* true if write in progress */
/* Initialized by config function */
struct spinlock ls_lock; /* protects ls_wbusy and device regs */
volatile bool ls_wbusy; /* true if write in progress */
/* Initialized by lower-level attachment function */
void *ls_busdata;
uint32_t ls_buspos;
/* Initialized by lower-level attachment function */
void *ls_busdata;
uint32_t ls_buspos;
/* Initialized by higher-level attachment function */
void *ls_devdata;
void (*ls_start)(void *devdata);
void (*ls_input)(void *devdata, int ch);
/* Initialized by higher-level attachment function */
void *ls_devdata;
void (*ls_start)(void *devdata);
void (*ls_input)(void *devdata, int ch);
};
/* Functions called by lower-level drivers */

View File

@ -34,30 +34,29 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct lser_softc *
attach_lser_to_lamebus(int lserno, struct lamebus_softc *sc)
{
struct lser_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SERIAL,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct lser_softc *attach_lser_to_lamebus(int lserno,
struct lamebus_softc *sc) {
struct lser_softc *ls;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SERIAL, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
ls = kmalloc(sizeof(struct lser_softc));
if (ls==NULL) {
return NULL;
}
ls = kmalloc(sizeof(struct lser_softc));
if (ls == NULL) {
return NULL;
}
(void)lserno; // unused
(void)lserno; // unused
ls->ls_busdata = sc;
ls->ls_buspos = slot;
ls->ls_busdata = sc;
ls->ls_buspos = slot;
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lser_irq);
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lser_irq);
return ls;
return ls;
}

View File

@ -39,92 +39,87 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LT_REG_SEC 0 /* time of day: seconds */
#define LT_REG_NSEC 4 /* time of day: nanoseconds */
#define LT_REG_ROE 8 /* Restart On countdown-timer Expiry flag */
#define LT_REG_IRQ 12 /* Interrupt status register */
#define LT_REG_COUNT 16 /* Time for countdown timer (usec) */
#define LT_REG_SPKR 20 /* Beep control */
#define LT_REG_SEC 0 /* time of day: seconds */
#define LT_REG_NSEC 4 /* time of day: nanoseconds */
#define LT_REG_ROE 8 /* Restart On countdown-timer Expiry flag */
#define LT_REG_IRQ 12 /* Interrupt status register */
#define LT_REG_COUNT 16 /* Time for countdown timer (usec) */
#define LT_REG_SPKR 20 /* Beep control */
/* Granularity of countdown timer (usec) */
#define LT_GRANULARITY 1000000
#define LT_GRANULARITY 1000000
static bool havetimerclock;
/*
* Setup routine called by autoconf stuff when an ltimer is found.
*/
int
config_ltimer(struct ltimer_softc *lt, int ltimerno)
{
/*
* Running on System/161 2.x, we always use the processor
* on-chip timer for hardclock and we don't need ltimer as
* hardclock.
*
* Ideally there should be code here that will use an ltimer
* for hardclock if nothing else is available; e.g. if we
* wanted to make OS/161 2.x run on System/161 1.x. However,
* that requires a good bit more infrastructure for handling
* timers than we have and it doesn't seem worthwhile.
*
* It would also require some hacking, because all CPUs need
* to receive timer interrupts. (Exercise: how would you make
* sure all CPUs receive exactly one timer interrupt? Remember
* that LAMEbus uses level-triggered interrupts, so the
* hardware interrupt line will cause repeated interrupts if
* it's not reset on the device; but if it's reset on the
* device before all CPUs manage to see it, those CPUs won't
* be interrupted at all.)
*
* Note that the beep and rtclock devices *do* attach to
* ltimer.
*/
(void)ltimerno;
lt->lt_hardclock = 0;
int config_ltimer(struct ltimer_softc *lt, int ltimerno) {
/*
* Running on System/161 2.x, we always use the processor
* on-chip timer for hardclock and we don't need ltimer as
* hardclock.
*
* Ideally there should be code here that will use an ltimer
* for hardclock if nothing else is available; e.g. if we
* wanted to make OS/161 2.x run on System/161 1.x. However,
* that requires a good bit more infrastructure for handling
* timers than we have and it doesn't seem worthwhile.
*
* It would also require some hacking, because all CPUs need
* to receive timer interrupts. (Exercise: how would you make
* sure all CPUs receive exactly one timer interrupt? Remember
* that LAMEbus uses level-triggered interrupts, so the
* hardware interrupt line will cause repeated interrupts if
* it's not reset on the device; but if it's reset on the
* device before all CPUs manage to see it, those CPUs won't
* be interrupted at all.)
*
* Note that the beep and rtclock devices *do* attach to
* ltimer.
*/
(void)ltimerno;
lt->lt_hardclock = 0;
/*
* We do, however, use ltimer for the timer clock, since the
* on-chip timer can't do that.
*/
if (!havetimerclock) {
havetimerclock = true;
lt->lt_timerclock = 1;
/*
* We do, however, use ltimer for the timer clock, since the
* on-chip timer can't do that.
*/
if (!havetimerclock) {
havetimerclock = true;
lt->lt_timerclock = 1;
/* Wire it to go off once every second. */
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_ROE, 1);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_COUNT,
LT_GRANULARITY);
}
/* Wire it to go off once every second. */
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_ROE, 1);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_COUNT, LT_GRANULARITY);
}
return 0;
return 0;
}
/*
* Interrupt handler.
*/
void
ltimer_irq(void *vlt)
{
struct ltimer_softc *lt = vlt;
uint32_t val;
void ltimer_irq(void *vlt) {
struct ltimer_softc *lt = vlt;
uint32_t val;
val = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_IRQ);
if (val) {
/*
* Only call hardclock if we're responsible for hardclock.
* (Any additional timer devices are unused.)
*/
if (lt->lt_hardclock) {
hardclock();
}
/*
* Likewise for timerclock.
*/
if (lt->lt_timerclock) {
timerclock();
}
}
val = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_IRQ);
if (val) {
/*
* Only call hardclock if we're responsible for hardclock.
* (Any additional timer devices are unused.)
*/
if (lt->lt_hardclock) {
hardclock();
}
/*
* Likewise for timerclock.
*/
if (lt->lt_timerclock) {
timerclock();
}
}
}
/*
@ -132,12 +127,10 @@ ltimer_irq(void *vlt)
* doesn't matter what value you write. This function is called if
* the beep device is attached to this timer.
*/
void
ltimer_beep(void *vlt)
{
struct ltimer_softc *lt = vlt;
void ltimer_beep(void *vlt) {
struct ltimer_softc *lt = vlt;
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_SPKR, 440);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_SPKR, 440);
}
/*
@ -145,43 +138,37 @@ ltimer_beep(void *vlt)
* This function gets called if the rtclock device is attached
* to this timer.
*/
void
ltimer_gettime(void *vlt, struct timespec *ts)
{
struct ltimer_softc *lt = vlt;
uint32_t secs1, secs2;
int spl;
void ltimer_gettime(void *vlt, struct timespec *ts) {
struct ltimer_softc *lt = vlt;
uint32_t secs1, secs2;
int spl;
/*
* Read the seconds twice, on either side of the nanoseconds.
* If nsecs is small, use the *later* value of seconds, in case
* the nanoseconds turned over between the time we got the earlier
* value and the time we got nsecs.
*
* Note that the clock in the ltimer device is accurate down
* to a single processor cycle, so this might actually matter
* now and then.
*
* Do it with interrupts off on the current processor to avoid
* getting garbage if we get an interrupt among the register
* reads.
*/
/*
* Read the seconds twice, on either side of the nanoseconds.
* If nsecs is small, use the *later* value of seconds, in case
* the nanoseconds turned over between the time we got the earlier
* value and the time we got nsecs.
*
* Note that the clock in the ltimer device is accurate down
* to a single processor cycle, so this might actually matter
* now and then.
*
* Do it with interrupts off on the current processor to avoid
* getting garbage if we get an interrupt among the register
* reads.
*/
spl = splhigh();
spl = splhigh();
secs1 = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_SEC);
ts->tv_nsec = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_NSEC);
secs2 = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_SEC);
secs1 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC);
ts->tv_nsec = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_NSEC);
secs2 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC);
splx(spl);
splx(spl);
if (ts->tv_nsec < 5000000) {
ts->tv_sec = secs2;
}
else {
ts->tv_sec = secs1;
}
if (ts->tv_nsec < 5000000) {
ts->tv_sec = secs2;
} else {
ts->tv_sec = secs1;
}
}

View File

@ -36,21 +36,21 @@ struct timespec;
* Hardware device data for LAMEbus timer device
*/
struct ltimer_softc {
/* Initialized by config function */
int lt_hardclock; /* true if we should call hardclock() */
int lt_timerclock; /* true if we should call timerclock() */
/* Initialized by config function */
int lt_hardclock; /* true if we should call hardclock() */
int lt_timerclock; /* true if we should call timerclock() */
/* Initialized by lower-level attach routine */
void *lt_bus; /* bus we're on */
uint32_t lt_buspos; /* position (slot) on that bus */
/* Initialized by lower-level attach routine */
void *lt_bus; /* bus we're on */
uint32_t lt_buspos; /* position (slot) on that bus */
};
/* Functions called by lower-level drivers */
void ltimer_irq(/*struct ltimer_softc*/ void *lt); // interrupt handler
void ltimer_irq(/*struct ltimer_softc*/ void *lt); // interrupt handler
/* Functions called by higher-level devices */
void ltimer_beep(/*struct ltimer_softc*/ void *devdata); // for beep device
void ltimer_beep(/*struct ltimer_softc*/ void *devdata); // for beep device
void ltimer_gettime(/*struct ltimer_softc*/ void *devdata,
struct timespec *ts); // for rtclock
struct timespec *ts); // for rtclock
#endif /* _LAMEBUS_LTIMER_H_ */

View File

@ -37,34 +37,33 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct ltimer_softc *
attach_ltimer_to_lamebus(int ltimerno, struct lamebus_softc *sc)
{
struct ltimer_softc *lt;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TIMER,
LOW_VERSION, NULL);
if (slot < 0) {
/* No ltimer (or no additional ltimer) found */
return NULL;
}
struct ltimer_softc *attach_ltimer_to_lamebus(int ltimerno,
struct lamebus_softc *sc) {
struct ltimer_softc *lt;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TIMER, LOW_VERSION, NULL);
if (slot < 0) {
/* No ltimer (or no additional ltimer) found */
return NULL;
}
lt = kmalloc(sizeof(struct ltimer_softc));
if (lt==NULL) {
/* out of memory */
return NULL;
}
lt = kmalloc(sizeof(struct ltimer_softc));
if (lt == NULL) {
/* out of memory */
return NULL;
}
(void)ltimerno; // unused
(void)ltimerno; // unused
/* Record what bus it's on */
lt->lt_bus = sc;
lt->lt_buspos = slot;
/* Record what bus it's on */
lt->lt_bus = sc;
lt->lt_buspos = slot;
/* Mark the slot in use and hook that slot's interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lt, ltimer_irq);
/* Mark the slot in use and hook that slot's interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lt, ltimer_irq);
return lt;
return lt;
}

View File

@ -34,83 +34,67 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LTRACE_REG_TRON 0 /* trace on */
#define LTRACE_REG_TROFF 4 /* trace off */
#define LTRACE_REG_DEBUG 8 /* debug code */
#define LTRACE_REG_DUMP 12 /* dump the system */
#define LTRACE_REG_STOP 16 /* stop for the debugger */
#define LTRACE_REG_PROFEN 20 /* turn profiling on/off */
#define LTRACE_REG_PROFCL 24 /* clear the profile */
#define LTRACE_REG_TRON 0 /* trace on */
#define LTRACE_REG_TROFF 4 /* trace off */
#define LTRACE_REG_DEBUG 8 /* debug code */
#define LTRACE_REG_DUMP 12 /* dump the system */
#define LTRACE_REG_STOP 16 /* stop for the debugger */
#define LTRACE_REG_PROFEN 20 /* turn profiling on/off */
#define LTRACE_REG_PROFCL 24 /* clear the profile */
static struct ltrace_softc *the_trace;
void
ltrace_on(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TRON, code);
}
void ltrace_on(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TRON, code);
}
}
void
ltrace_off(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TROFF, code);
}
void ltrace_off(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TROFF, code);
}
}
void
ltrace_debug(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DEBUG, code);
}
void ltrace_debug(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DEBUG, code);
}
}
void
ltrace_dump(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DUMP, code);
}
void ltrace_dump(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DUMP, code);
}
}
void
ltrace_stop(uint32_t code)
{
if (the_trace != NULL && the_trace->lt_canstop) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_STOP, code);
}
void ltrace_stop(uint32_t code) {
if (the_trace != NULL && the_trace->lt_canstop) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_STOP, code);
}
}
void
ltrace_setprof(uint32_t onoff)
{
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFEN, onoff);
}
void ltrace_setprof(uint32_t onoff) {
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFEN, onoff);
}
}
void
ltrace_eraseprof(void)
{
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFCL, 1);
}
void ltrace_eraseprof(void) {
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFCL, 1);
}
}
int
config_ltrace(struct ltrace_softc *sc, int ltraceno)
{
(void)ltraceno;
the_trace = sc;
return 0;
int config_ltrace(struct ltrace_softc *sc, int ltraceno) {
(void)ltraceno;
the_trace = sc;
return 0;
}

View File

@ -31,11 +31,11 @@
#define _LAMEBUS_LTRACE_H_
struct ltrace_softc {
/* Initialized by lower-level attachment function */
void *lt_busdata;
uint32_t lt_buspos;
bool lt_canstop;
bool lt_canprof;
/* Initialized by lower-level attachment function */
void *lt_busdata;
uint32_t lt_buspos;
bool lt_canstop;
bool lt_canprof;
};
/*

View File

@ -34,36 +34,35 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Revision that supports ltrace_stop() */
#define STOP_VERSION 2
#define STOP_VERSION 2
/* Revision that supports ltrace_prof() */
#define PROF_VERSION 3
#define PROF_VERSION 3
struct ltrace_softc *
attach_ltrace_to_lamebus(int ltraceno, struct lamebus_softc *sc)
{
struct ltrace_softc *lt;
uint32_t drl;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TRACE,
LOW_VERSION, &drl);
if (slot < 0) {
return NULL;
}
struct ltrace_softc *attach_ltrace_to_lamebus(int ltraceno,
struct lamebus_softc *sc) {
struct ltrace_softc *lt;
uint32_t drl;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TRACE, LOW_VERSION, &drl);
if (slot < 0) {
return NULL;
}
lt = kmalloc(sizeof(struct ltrace_softc));
if (lt==NULL) {
return NULL;
}
lt = kmalloc(sizeof(struct ltrace_softc));
if (lt == NULL) {
return NULL;
}
(void)ltraceno; // unused
(void)ltraceno; // unused
lt->lt_busdata = sc;
lt->lt_buspos = slot;
lt->lt_canstop = drl >= STOP_VERSION;
lt->lt_canprof = drl >= PROF_VERSION;
lt->lt_busdata = sc;
lt->lt_buspos = slot;
lt->lt_canstop = drl >= STOP_VERSION;
lt->lt_canprof = drl >= PROF_VERSION;
lamebus_mark(sc, slot);
lamebus_mark(sc, slot);
return lt;
return lt;
}

View File

@ -38,20 +38,19 @@
#include <lamebus/lrandom.h>
#include "autoconf.h"
struct random_softc *
attach_random_to_lrandom(int randomno, struct lrandom_softc *ls)
{
struct random_softc *rs = kmalloc(sizeof(struct random_softc));
if (rs==NULL) {
return NULL;
}
struct random_softc *attach_random_to_lrandom(int randomno,
struct lrandom_softc *ls) {
struct random_softc *rs = kmalloc(sizeof(struct random_softc));
if (rs == NULL) {
return NULL;
}
(void)randomno; // unused
(void)randomno; // unused
rs->rs_devdata = ls;
rs->rs_random = lrandom_random;
rs->rs_randmax = lrandom_randmax;
rs->rs_read = lrandom_read;
rs->rs_devdata = ls;
rs->rs_random = lrandom_random;
rs->rs_randmax = lrandom_randmax;
rs->rs_read = lrandom_read;
return rs;
return rs;
}

View File

@ -44,23 +44,22 @@
#include <lamebus/ltimer.h>
#include "autoconf.h"
struct rtclock_softc *
attach_rtclock_to_ltimer(int rtclockno, struct ltimer_softc *ls)
{
/*
* No need to probe; ltimer always has a clock.
* Just allocate the rtclock, set our fields, and return it.
*/
struct rtclock_softc *rtc = kmalloc(sizeof(struct rtclock_softc));
if (rtc==NULL) {
/* Out of memory */
return NULL;
}
struct rtclock_softc *attach_rtclock_to_ltimer(int rtclockno,
struct ltimer_softc *ls) {
/*
* No need to probe; ltimer always has a clock.
* Just allocate the rtclock, set our fields, and return it.
*/
struct rtclock_softc *rtc = kmalloc(sizeof(struct rtclock_softc));
if (rtc == NULL) {
/* Out of memory */
return NULL;
}
(void)rtclockno; // unused
(void)rtclockno; // unused
rtc->rtc_devdata = ls;
rtc->rtc_gettime = ltimer_gettime;
rtc->rtc_devdata = ls;
rtc->rtc_gettime = ltimer_gettime;
return rtc;
return rtc;
}

View File

@ -42,7 +42,7 @@
* Constants
*/
#define SEMFS_ROOTDIR 0xffffffffU /* semnum for root dir */
#define SEMFS_ROOTDIR 0xffffffffU /* semnum for root dir */
/*
* A user-facing semaphore.
@ -52,11 +52,11 @@
* XXX: or would we? review once all this is done.
*/
struct semfs_sem {
struct lock *sems_lock; /* Lock to protect count */
struct cv *sems_cv; /* CV to wait */
unsigned sems_count; /* Semaphore count */
bool sems_hasvnode; /* The vnode exists */
bool sems_linked; /* In the directory */
struct lock *sems_lock; /* Lock to protect count */
struct cv *sems_cv; /* CV to wait */
unsigned sems_count; /* Semaphore count */
bool sems_hasvnode; /* The vnode exists */
bool sems_linked; /* In the directory */
};
DECLARRAY(semfs_sem, SEMFS_INLINE);
@ -64,8 +64,8 @@ DECLARRAY(semfs_sem, SEMFS_INLINE);
* Directory entry; name and reference to a semaphore.
*/
struct semfs_direntry {
char *semd_name; /* Name */
unsigned semd_semnum; /* Which semaphore */
char *semd_name; /* Name */
unsigned semd_semnum; /* Which semaphore */
};
DECLARRAY(semfs_direntry, SEMFS_INLINE);
@ -77,9 +77,9 @@ DECLARRAY(semfs_direntry, SEMFS_INLINE);
* practice. XXX: review after finishing)
*/
struct semfs_vnode {
struct vnode semv_absvn; /* Abstract vnode */
struct semfs *semv_semfs; /* Back-pointer to fs */
unsigned semv_semnum; /* Which semaphore */
struct vnode semv_absvn; /* Abstract vnode */
struct semfs *semv_semfs; /* Back-pointer to fs */
unsigned semv_semnum; /* Which semaphore */
};
/*
@ -87,14 +87,14 @@ struct semfs_vnode {
* is only one of these.
*/
struct semfs {
struct fs semfs_absfs; /* Abstract fs object */
struct fs semfs_absfs; /* Abstract fs object */
struct lock *semfs_tablelock; /* Lock for following */
struct vnodearray *semfs_vnodes; /* Currently extant vnodes */
struct semfs_semarray *semfs_sems; /* Semaphores */
struct lock *semfs_tablelock; /* Lock for following */
struct vnodearray *semfs_vnodes; /* Currently extant vnodes */
struct semfs_semarray *semfs_sems; /* Semaphores */
struct lock *semfs_dirlock; /* Lock for following */
struct semfs_direntryarray *semfs_dents; /* The root directory */
struct lock *semfs_dirlock; /* Lock for following */
struct semfs_direntryarray *semfs_dents; /* The root directory */
};
/*
@ -104,7 +104,6 @@ struct semfs {
DEFARRAY(semfs_sem, SEMFS_INLINE);
DEFARRAY(semfs_direntry, SEMFS_INLINE);
/*
* Functions.
*/
@ -119,5 +118,4 @@ void semfs_direntry_destroy(struct semfs_direntry *);
/* in semfs_vnops.c */
int semfs_getvnode(struct semfs *, unsigned, struct vnode **ret);
#endif /* SEMFS_H */

View File

@ -42,185 +42,163 @@
/*
* Sync doesn't need to do anything.
*/
static
int
semfs_sync(struct fs *fs)
{
(void)fs;
return 0;
static int semfs_sync(struct fs *fs) {
(void)fs;
return 0;
}
/*
* We have only one volume name and it's hardwired.
*/
static
const char *
semfs_getvolname(struct fs *fs)
{
(void)fs;
return "sem";
static const char *semfs_getvolname(struct fs *fs) {
(void)fs;
return "sem";
}
/*
* Get the root directory vnode.
*/
static
int
semfs_getroot(struct fs *fs, struct vnode **ret)
{
struct semfs *semfs = fs->fs_data;
struct vnode *vn;
int result;
static int semfs_getroot(struct fs *fs, struct vnode **ret) {
struct semfs *semfs = fs->fs_data;
struct vnode *vn;
int result;
result = semfs_getvnode(semfs, SEMFS_ROOTDIR, &vn);
if (result) {
kprintf("semfs: couldn't load root vnode: %s\n",
strerror(result));
return result;
}
*ret = vn;
return 0;
result = semfs_getvnode(semfs, SEMFS_ROOTDIR, &vn);
if (result) {
kprintf("semfs: couldn't load root vnode: %s\n", strerror(result));
return result;
}
*ret = vn;
return 0;
}
////////////////////////////////////////////////////////////
// mount and unmount logic
/*
* Destructor for struct semfs.
*/
static
void
semfs_destroy(struct semfs *semfs)
{
struct semfs_sem *sem;
struct semfs_direntry *dent;
unsigned i, num;
static void semfs_destroy(struct semfs *semfs) {
struct semfs_sem *sem;
struct semfs_direntry *dent;
unsigned i, num;
num = semfs_semarray_num(semfs->semfs_sems);
for (i=0; i<num; i++) {
sem = semfs_semarray_get(semfs->semfs_sems, i);
semfs_sem_destroy(sem);
}
semfs_semarray_setsize(semfs->semfs_sems, 0);
num = semfs_semarray_num(semfs->semfs_sems);
for (i = 0; i < num; i++) {
sem = semfs_semarray_get(semfs->semfs_sems, i);
semfs_sem_destroy(sem);
}
semfs_semarray_setsize(semfs->semfs_sems, 0);
num = semfs_direntryarray_num(semfs->semfs_dents);
for (i=0; i<num; i++) {
dent = semfs_direntryarray_get(semfs->semfs_dents, i);
semfs_direntry_destroy(dent);
}
semfs_direntryarray_setsize(semfs->semfs_dents, 0);
num = semfs_direntryarray_num(semfs->semfs_dents);
for (i = 0; i < num; i++) {
dent = semfs_direntryarray_get(semfs->semfs_dents, i);
semfs_direntry_destroy(dent);
}
semfs_direntryarray_setsize(semfs->semfs_dents, 0);
semfs_direntryarray_destroy(semfs->semfs_dents);
lock_destroy(semfs->semfs_dirlock);
semfs_semarray_destroy(semfs->semfs_sems);
vnodearray_destroy(semfs->semfs_vnodes);
lock_destroy(semfs->semfs_tablelock);
kfree(semfs);
semfs_direntryarray_destroy(semfs->semfs_dents);
lock_destroy(semfs->semfs_dirlock);
semfs_semarray_destroy(semfs->semfs_sems);
vnodearray_destroy(semfs->semfs_vnodes);
lock_destroy(semfs->semfs_tablelock);
kfree(semfs);
}
/*
* Unmount routine. XXX: Since semfs is attached at boot and can't be
* remounted, maybe unmounting it shouldn't be allowed.
*/
static
int
semfs_unmount(struct fs *fs)
{
struct semfs *semfs = fs->fs_data;
static int semfs_unmount(struct fs *fs) {
struct semfs *semfs = fs->fs_data;
lock_acquire(semfs->semfs_tablelock);
if (vnodearray_num(semfs->semfs_vnodes) > 0) {
lock_release(semfs->semfs_tablelock);
return EBUSY;
}
lock_acquire(semfs->semfs_tablelock);
if (vnodearray_num(semfs->semfs_vnodes) > 0) {
lock_release(semfs->semfs_tablelock);
return EBUSY;
}
lock_release(semfs->semfs_tablelock);
semfs_destroy(semfs);
lock_release(semfs->semfs_tablelock);
semfs_destroy(semfs);
return 0;
return 0;
}
/*
* Operations table.
*/
static const struct fs_ops semfs_fsops = {
.fsop_sync = semfs_sync,
.fsop_getvolname = semfs_getvolname,
.fsop_getroot = semfs_getroot,
.fsop_unmount = semfs_unmount,
.fsop_sync = semfs_sync,
.fsop_getvolname = semfs_getvolname,
.fsop_getroot = semfs_getroot,
.fsop_unmount = semfs_unmount,
};
/*
* Constructor for struct semfs.
*/
static
struct semfs *
semfs_create(void)
{
struct semfs *semfs;
static struct semfs *semfs_create(void) {
struct semfs *semfs;
semfs = kmalloc(sizeof(*semfs));
if (semfs == NULL) {
goto fail_total;
}
semfs = kmalloc(sizeof(*semfs));
if (semfs == NULL) {
goto fail_total;
}
semfs->semfs_tablelock = lock_create("semfs_table");
if (semfs->semfs_tablelock == NULL) {
goto fail_semfs;
}
semfs->semfs_vnodes = vnodearray_create();
if (semfs->semfs_vnodes == NULL) {
goto fail_tablelock;
}
semfs->semfs_sems = semfs_semarray_create();
if (semfs->semfs_sems == NULL) {
goto fail_vnodes;
}
semfs->semfs_tablelock = lock_create("semfs_table");
if (semfs->semfs_tablelock == NULL) {
goto fail_semfs;
}
semfs->semfs_vnodes = vnodearray_create();
if (semfs->semfs_vnodes == NULL) {
goto fail_tablelock;
}
semfs->semfs_sems = semfs_semarray_create();
if (semfs->semfs_sems == NULL) {
goto fail_vnodes;
}
semfs->semfs_dirlock = lock_create("semfs_dir");
if (semfs->semfs_dirlock == NULL) {
goto fail_sems;
}
semfs->semfs_dents = semfs_direntryarray_create();
if (semfs->semfs_dents == NULL) {
goto fail_dirlock;
}
semfs->semfs_dirlock = lock_create("semfs_dir");
if (semfs->semfs_dirlock == NULL) {
goto fail_sems;
}
semfs->semfs_dents = semfs_direntryarray_create();
if (semfs->semfs_dents == NULL) {
goto fail_dirlock;
}
semfs->semfs_absfs.fs_data = semfs;
semfs->semfs_absfs.fs_ops = &semfs_fsops;
return semfs;
semfs->semfs_absfs.fs_data = semfs;
semfs->semfs_absfs.fs_ops = &semfs_fsops;
return semfs;
fail_dirlock:
lock_destroy(semfs->semfs_dirlock);
fail_sems:
semfs_semarray_destroy(semfs->semfs_sems);
fail_vnodes:
vnodearray_destroy(semfs->semfs_vnodes);
fail_tablelock:
lock_destroy(semfs->semfs_tablelock);
fail_semfs:
kfree(semfs);
fail_total:
return NULL;
fail_dirlock:
lock_destroy(semfs->semfs_dirlock);
fail_sems:
semfs_semarray_destroy(semfs->semfs_sems);
fail_vnodes:
vnodearray_destroy(semfs->semfs_vnodes);
fail_tablelock:
lock_destroy(semfs->semfs_tablelock);
fail_semfs:
kfree(semfs);
fail_total:
return NULL;
}
/*
* Create the semfs. There is only one semfs and it's attached as
* "sem:" during bootup.
*/
void
semfs_bootstrap(void)
{
struct semfs *semfs;
int result;
void semfs_bootstrap(void) {
struct semfs *semfs;
int result;
semfs = semfs_create();
if (semfs == NULL) {
panic("Out of memory creating semfs\n");
}
result = vfs_addfs("sem", &semfs->semfs_absfs);
if (result) {
panic("Attaching semfs: %s\n", strerror(result));
}
semfs = semfs_create();
if (semfs == NULL) {
panic("Out of memory creating semfs\n");
}
result = vfs_addfs("sem", &semfs->semfs_absfs);
if (result) {
panic("Attaching semfs: %s\n", strerror(result));
}
}

View File

@ -40,74 +40,69 @@
/*
* Constructor for semfs_sem.
*/
struct semfs_sem *
semfs_sem_create(const char *name)
{
struct semfs_sem *sem;
char lockname[32];
char cvname[32];
struct semfs_sem *semfs_sem_create(const char *name) {
struct semfs_sem *sem;
char lockname[32];
char cvname[32];
snprintf(lockname, sizeof(lockname), "sem:l.%s", name);
snprintf(cvname, sizeof(cvname), "sem:%s", name);
snprintf(lockname, sizeof(lockname), "sem:l.%s", name);
snprintf(cvname, sizeof(cvname), "sem:%s", name);
sem = kmalloc(sizeof(*sem));
if (sem == NULL) {
goto fail_return;
}
sem->sems_lock = lock_create(lockname);
if (sem->sems_lock == NULL) {
goto fail_sem;
}
sem->sems_cv = cv_create(cvname);
if (sem->sems_cv == NULL) {
goto fail_lock;
}
sem->sems_count = 0;
sem->sems_hasvnode = false;
sem->sems_linked = false;
return sem;
sem = kmalloc(sizeof(*sem));
if (sem == NULL) {
goto fail_return;
}
sem->sems_lock = lock_create(lockname);
if (sem->sems_lock == NULL) {
goto fail_sem;
}
sem->sems_cv = cv_create(cvname);
if (sem->sems_cv == NULL) {
goto fail_lock;
}
sem->sems_count = 0;
sem->sems_hasvnode = false;
sem->sems_linked = false;
return sem;
fail_lock:
lock_destroy(sem->sems_lock);
fail_sem:
kfree(sem);
fail_return:
return NULL;
fail_lock:
lock_destroy(sem->sems_lock);
fail_sem:
kfree(sem);
fail_return:
return NULL;
}
/*
* Destructor for semfs_sem.
*/
void
semfs_sem_destroy(struct semfs_sem *sem)
{
cv_destroy(sem->sems_cv);
lock_destroy(sem->sems_lock);
kfree(sem);
void semfs_sem_destroy(struct semfs_sem *sem) {
cv_destroy(sem->sems_cv);
lock_destroy(sem->sems_lock);
kfree(sem);
}
/*
* Helper to insert a semfs_sem into the semaphore table.
*/
int
semfs_sem_insert(struct semfs *semfs, struct semfs_sem *sem, unsigned *ret)
{
unsigned i, num;
int semfs_sem_insert(struct semfs *semfs, struct semfs_sem *sem,
unsigned *ret) {
unsigned i, num;
KASSERT(lock_do_i_hold(semfs->semfs_tablelock));
num = semfs_semarray_num(semfs->semfs_sems);
if (num == SEMFS_ROOTDIR) {
/* Too many */
return ENOSPC;
}
for (i=0; i<num; i++) {
if (semfs_semarray_get(semfs->semfs_sems, i) == NULL) {
semfs_semarray_set(semfs->semfs_sems, i, sem);
*ret = i;
return 0;
}
}
return semfs_semarray_add(semfs->semfs_sems, sem, ret);
KASSERT(lock_do_i_hold(semfs->semfs_tablelock));
num = semfs_semarray_num(semfs->semfs_sems);
if (num == SEMFS_ROOTDIR) {
/* Too many */
return ENOSPC;
}
for (i = 0; i < num; i++) {
if (semfs_semarray_get(semfs->semfs_sems, i) == NULL) {
semfs_semarray_set(semfs->semfs_sems, i, sem);
*ret = i;
return 0;
}
}
return semfs_semarray_add(semfs->semfs_sems, sem, ret);
}
////////////////////////////////////////////////////////////
@ -116,30 +111,27 @@ semfs_sem_insert(struct semfs *semfs, struct semfs_sem *sem, unsigned *ret)
/*
* Constructor for semfs_direntry.
*/
struct semfs_direntry *
semfs_direntry_create(const char *name, unsigned semnum)
{
struct semfs_direntry *dent;
struct semfs_direntry *semfs_direntry_create(const char *name,
unsigned semnum) {
struct semfs_direntry *dent;
dent = kmalloc(sizeof(*dent));
if (dent == NULL) {
return NULL;
}
dent->semd_name = kstrdup(name);
if (dent->semd_name == NULL) {
kfree(dent);
return NULL;
}
dent->semd_semnum = semnum;
return dent;
dent = kmalloc(sizeof(*dent));
if (dent == NULL) {
return NULL;
}
dent->semd_name = kstrdup(name);
if (dent->semd_name == NULL) {
kfree(dent);
return NULL;
}
dent->semd_semnum = semnum;
return dent;
}
/*
* Destructor for semfs_direntry.
*/
void
semfs_direntry_destroy(struct semfs_direntry *dent)
{
kfree(dent->semd_name);
kfree(dent);
void semfs_direntry_destroy(struct semfs_direntry *dent) {
kfree(dent->semd_name);
kfree(dent);
}

File diff suppressed because it is too large Load Diff

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