/*
|
/*
|
* main.c -- start the ball rolling
|
* main.c -- start the ball rolling
|
*/
|
*/
|
|
|
|
|
#include "stdarg.h"
|
#include "stdarg.h"
|
#include "start.h"
|
#include "start.h"
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
int currentTask;
|
int currentTask;
|
unsigned int *currentStkTop;
|
unsigned int *currentStkTop;
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
unsigned int task0Stack[256];
|
unsigned int task0Stack[256];
|
unsigned int *task0StkTop = task0Stack + 256;
|
unsigned int *task0StkTop = task0Stack + 256;
|
|
|
|
|
unsigned char task1Code[] = {
|
unsigned char task1Code[] = {
|
#include "task1.dump"
|
#include "task1.dump"
|
};
|
};
|
|
|
unsigned int task1Stack[256];
|
unsigned int task1Stack[256];
|
unsigned int *task1StkTop = task1Stack + 256;
|
unsigned int *task1StkTop = task1Stack + 256;
|
|
|
|
|
unsigned char task2Code[] = {
|
unsigned char task2Code[] = {
|
#include "task2.dump"
|
#include "task2.dump"
|
};
|
};
|
|
|
unsigned int task2Stack[256];
|
unsigned int task2Stack[256];
|
unsigned int *task2StkTop = task2Stack + 256;
|
unsigned int *task2StkTop = task2Stack + 256;
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void putchar(char c) {
|
void putchar(char c) {
|
unsigned int *base;
|
unsigned int *base;
|
|
|
if (c == '\n') {
|
if (c == '\n') {
|
putchar('\r');
|
putchar('\r');
|
}
|
}
|
base = (unsigned int *) 0xF0300000;
|
base = (unsigned int *) 0xF0300000;
|
while ((*(base + 2) & 1) == 0) ;
|
while ((*(base + 2) & 1) == 0) ;
|
*(base + 3) = c;
|
*(base + 3) = c;
|
}
|
}
|
|
|
|
|
void puts(char *s) {
|
void puts(char *s) {
|
char c;
|
char c;
|
|
|
while ((c = *s++) != '\0') {
|
while ((c = *s++) != '\0') {
|
putchar(c);
|
putchar(c);
|
}
|
}
|
}
|
}
|
|
|
|
|
void printn(int n) {
|
void printn(int n) {
|
int a;
|
int a;
|
|
|
if (n < 0) {
|
if (n < 0) {
|
putchar('-');
|
putchar('-');
|
n = -n;
|
n = -n;
|
}
|
}
|
a = n / 10;
|
a = n / 10;
|
if (a != 0) {
|
if (a != 0) {
|
printn(a);
|
printn(a);
|
}
|
}
|
putchar(n % 10 + '0');
|
putchar(n % 10 + '0');
|
}
|
}
|
|
|
|
|
void printu(unsigned int n, unsigned int b) {
|
void printu(unsigned int n, unsigned int b) {
|
unsigned int a;
|
unsigned int a;
|
|
|
a = n / b;
|
a = n / b;
|
if (a != 0) {
|
if (a != 0) {
|
printu(a, b);
|
printu(a, b);
|
}
|
}
|
putchar("0123456789ABCDEF"[n % b]);
|
putchar("0123456789ABCDEF"[n % b]);
|
}
|
}
|
|
|
|
|
void printf(char *fmt, ...) {
|
void printf(char *fmt, ...) {
|
va_list ap;
|
va_list ap;
|
char c;
|
char c;
|
int n;
|
int n;
|
unsigned int u;
|
unsigned int u;
|
char *s;
|
char *s;
|
|
|
va_start(ap, fmt);
|
va_start(ap, fmt);
|
while (1) {
|
while (1) {
|
while ((c = *fmt++) != '%') {
|
while ((c = *fmt++) != '%') {
|
if (c == '\0') {
|
if (c == '\0') {
|
va_end(ap);
|
va_end(ap);
|
return;
|
return;
|
}
|
}
|
putchar(c);
|
putchar(c);
|
}
|
}
|
c = *fmt++;
|
c = *fmt++;
|
if (c == 'd') {
|
if (c == 'd') {
|
n = va_arg(ap, int);
|
n = va_arg(ap, int);
|
printn(n);
|
printn(n);
|
} else
|
} else
|
if (c == 'u' || c == 'o' || c == 'x') {
|
if (c == 'u' || c == 'o' || c == 'x') {
|
u = va_arg(ap, int);
|
u = va_arg(ap, int);
|
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
|
printu(u, c == 'o' ? 8 : (c == 'x' ? 16 : 10));
|
} else
|
} else
|
if (c == 's') {
|
if (c == 's') {
|
s = va_arg(ap, char *);
|
s = va_arg(ap, char *);
|
puts(s);
|
puts(s);
|
} else {
|
} else {
|
putchar(c);
|
putchar(c);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
static char *exceptionCause[32] = {
|
static char *exceptionCause[32] = {
|
/* 00 */ "terminal 0 transmitter interrupt",
|
/* 00 */ "terminal 0 transmitter interrupt",
|
/* 01 */ "terminal 0 receiver interrupt",
|
/* 01 */ "terminal 0 receiver interrupt",
|
/* 02 */ "terminal 1 transmitter interrupt",
|
/* 02 */ "terminal 1 transmitter interrupt",
|
/* 03 */ "terminal 1 receiver interrupt",
|
/* 03 */ "terminal 1 receiver interrupt",
|
/* 04 */ "keyboard interrupt",
|
/* 04 */ "keyboard interrupt",
|
/* 05 */ "unknown interrupt",
|
/* 05 */ "unknown interrupt",
|
/* 06 */ "unknown interrupt",
|
/* 06 */ "unknown interrupt",
|
/* 07 */ "unknown interrupt",
|
/* 07 */ "unknown interrupt",
|
/* 08 */ "disk interrupt",
|
/* 08 */ "disk interrupt",
|
/* 09 */ "unknown interrupt",
|
/* 09 */ "unknown interrupt",
|
/* 10 */ "unknown interrupt",
|
/* 10 */ "unknown interrupt",
|
/* 11 */ "unknown interrupt",
|
/* 11 */ "unknown interrupt",
|
/* 12 */ "unknown interrupt",
|
/* 12 */ "unknown interrupt",
|
/* 13 */ "unknown interrupt",
|
/* 13 */ "unknown interrupt",
|
/* 14 */ "timer interrupt",
|
/* 14 */ "timer 0 interrupt",
|
/* 15 */ "unknown interrupt",
|
/* 15 */ "timer 1 interrupt",
|
/* 16 */ "bus timeout exception",
|
/* 16 */ "bus timeout exception",
|
/* 17 */ "illegal instruction exception",
|
/* 17 */ "illegal instruction exception",
|
/* 18 */ "privileged instruction exception",
|
/* 18 */ "privileged instruction exception",
|
/* 19 */ "divide instruction exception",
|
/* 19 */ "divide instruction exception",
|
/* 20 */ "trap instruction exception",
|
/* 20 */ "trap instruction exception",
|
/* 21 */ "TLB miss exception",
|
/* 21 */ "TLB miss exception",
|
/* 22 */ "TLB write exception",
|
/* 22 */ "TLB write exception",
|
/* 23 */ "TLB invalid exception",
|
/* 23 */ "TLB invalid exception",
|
/* 24 */ "illegal address exception",
|
/* 24 */ "illegal address exception",
|
/* 25 */ "privileged address exception",
|
/* 25 */ "privileged address exception",
|
/* 26 */ "unknown exception",
|
/* 26 */ "unknown exception",
|
/* 27 */ "unknown exception",
|
/* 27 */ "unknown exception",
|
/* 28 */ "unknown exception",
|
/* 28 */ "unknown exception",
|
/* 29 */ "unknown exception",
|
/* 29 */ "unknown exception",
|
/* 30 */ "unknown exception",
|
/* 30 */ "unknown exception",
|
/* 31 */ "unknown exception"
|
/* 31 */ "unknown exception"
|
};
|
};
|
|
|
|
|
void defaultISR(int irq, unsigned int *registers) {
|
void defaultISR(int irq, unsigned int *registers) {
|
printf("\n%s\n", exceptionCause[irq]);
|
printf("\n%s\n", exceptionCause[irq]);
|
}
|
}
|
|
|
|
|
void initInterrupts(void) {
|
void initInterrupts(void) {
|
int i;
|
int i;
|
|
|
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
setISR(i, defaultISR);
|
setISR(i, defaultISR);
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
unsigned int getNumber(unsigned char *p) {
|
unsigned int getNumber(unsigned char *p) {
|
return (unsigned int) *(p + 0) << 24 |
|
return (unsigned int) *(p + 0) << 24 |
|
(unsigned int) *(p + 1) << 16 |
|
(unsigned int) *(p + 1) << 16 |
|
(unsigned int) *(p + 2) << 8 |
|
(unsigned int) *(p + 2) << 8 |
|
(unsigned int) *(p + 3) << 0;
|
(unsigned int) *(p + 3) << 0;
|
}
|
}
|
|
|
|
|
void loadTask(unsigned char *code,
|
void loadTask(unsigned char *code,
|
unsigned int physCodeAddr,
|
unsigned int physCodeAddr,
|
unsigned int physDataAddr) {
|
unsigned int physDataAddr) {
|
unsigned int magic;
|
unsigned int magic;
|
unsigned int csize;
|
unsigned int csize;
|
unsigned int dsize;
|
unsigned int dsize;
|
unsigned int bsize;
|
unsigned int bsize;
|
unsigned char *virtLoadAddr;
|
unsigned char *virtLoadAddr;
|
int i;
|
int i;
|
|
|
magic = getNumber(code);
|
magic = getNumber(code);
|
code += sizeof(unsigned int);
|
code += sizeof(unsigned int);
|
csize = getNumber(code);
|
csize = getNumber(code);
|
code += sizeof(unsigned int);
|
code += sizeof(unsigned int);
|
dsize = getNumber(code);
|
dsize = getNumber(code);
|
code += sizeof(unsigned int);
|
code += sizeof(unsigned int);
|
bsize = getNumber(code);
|
bsize = getNumber(code);
|
code += sizeof(unsigned int);
|
code += sizeof(unsigned int);
|
if (magic != 0x1AA09232) {
|
if (magic != 0x1AA09232) {
|
printf("Error: Load module is not executable!\n");
|
printf("Error: Load module is not executable!\n");
|
while (1) ;
|
while (1) ;
|
}
|
}
|
code += 4 * sizeof(unsigned int);
|
code += 4 * sizeof(unsigned int);
|
printf("(csize = 0x%x, dsize = 0x%x, bsize = 0x%x)\n",
|
printf("(csize = 0x%x, dsize = 0x%x, bsize = 0x%x)\n",
|
csize, dsize, bsize);
|
csize, dsize, bsize);
|
virtLoadAddr = (unsigned char *) (0xC0000000 | physCodeAddr);
|
virtLoadAddr = (unsigned char *) (0xC0000000 | physCodeAddr);
|
for (i = 0; i < csize; i++) {
|
for (i = 0; i < csize; i++) {
|
*virtLoadAddr++ = *code++;
|
*virtLoadAddr++ = *code++;
|
}
|
}
|
virtLoadAddr = (unsigned char *) (0xC0000000 | physDataAddr);
|
virtLoadAddr = (unsigned char *) (0xC0000000 | physDataAddr);
|
for (i = 0; i < dsize; i++) {
|
for (i = 0; i < dsize; i++) {
|
*virtLoadAddr++ = *code++;
|
*virtLoadAddr++ = *code++;
|
}
|
}
|
for (i = 0; i < bsize; i++) {
|
for (i = 0; i < bsize; i++) {
|
*virtLoadAddr++ = '\0';
|
*virtLoadAddr++ = '\0';
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void trapISR(int irq, unsigned int *registers) {
|
void trapISR(int irq, unsigned int *registers) {
|
/* 'putchar' is the only system call yet */
|
/* 'putchar' is the only system call yet */
|
putchar(registers[4]);
|
putchar(registers[4]);
|
/* skip the trap instruction */
|
/* skip the trap instruction */
|
registers[30] += 4;
|
registers[30] += 4;
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void missISR(int irq, unsigned int *registers) {
|
void missISR(int irq, unsigned int *registers) {
|
if (currentTask == 1) {
|
if (currentTask == 1) {
|
setTLB(5, 0x00000000, 64 << 12 | 0x01); /* code at 256 k */
|
setTLB(5, 0x00000000, 64 << 12 | 0x01); /* code at 256 k */
|
setTLB(27, 0x00001000, 68 << 12 | 0x03); /* data at 272 k */
|
setTLB(27, 0x00001000, 68 << 12 | 0x03); /* data at 272 k */
|
setTLB(22, 0x7FFFF000, 80 << 12 | 0x03); /* user-mode stack at 320 k */
|
setTLB(22, 0x7FFFF000, 80 << 12 | 0x03); /* user-mode stack at 320 k */
|
} else if (currentTask == 2) {
|
} else if (currentTask == 2) {
|
setTLB(5, 0x00000000, 96 << 12 | 0x01); /* code at 384 k */
|
setTLB(5, 0x00000000, 96 << 12 | 0x01); /* code at 384 k */
|
setTLB(27, 0x00001000, 100 << 12 | 0x03); /* data at 400 k */
|
setTLB(27, 0x00001000, 100 << 12 | 0x03); /* data at 400 k */
|
setTLB(22, 0x7FFFF000, 112 << 12 | 0x03); /* user-mode stack at 448 k */
|
setTLB(22, 0x7FFFF000, 112 << 12 | 0x03); /* user-mode stack at 448 k */
|
}
|
}
|
}
|
}
|
|
|
|
|
void flushTLB(void) {
|
void flushTLB(void) {
|
unsigned int invalPage;
|
unsigned int invalPage;
|
int i;
|
int i;
|
|
|
invalPage = 0xC0000000;
|
invalPage = 0xC0000000;
|
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
setTLB(i, invalPage, 0);
|
setTLB(i, invalPage, 0);
|
invalPage += (1 << 12);
|
invalPage += (1 << 12);
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void initTimer(void) {
|
void initTimer(void) {
|
unsigned int *timerBase;
|
unsigned int *timerBase;
|
|
|
timerBase = (unsigned int *) 0xF0000000;
|
timerBase = (unsigned int *) 0xF0000000;
|
*(timerBase + 1) = 1000;
|
*(timerBase + 1) = 50000000;
|
*timerBase = 2;
|
*timerBase = 2;
|
orMask(1 << 14);
|
orMask(1 << 14);
|
}
|
}
|
|
|
|
|
int task1Started = 0;
|
int task1Started = 0;
|
int task2Started = 0;
|
int task2Started = 0;
|
|
|
|
|
void timerISR(int irq, unsigned int *registers) {
|
void timerISR(int irq, unsigned int *registers) {
|
unsigned int *timerBase;
|
unsigned int *timerBase;
|
|
|
timerBase = (unsigned int *) 0xF0000000;
|
timerBase = (unsigned int *) 0xF0000000;
|
*timerBase = 2;
|
*timerBase = 2;
|
printf(">|<");
|
printf(">|<");
|
if (currentTask == 0) {
|
if (currentTask == 0) {
|
if (!task1Started) {
|
if (!task1Started) {
|
/* load & start task1 */
|
/* load & start task1 */
|
printf("\nOS: loading task1\n");
|
printf("\nOS: loading task1\n");
|
loadTask(task1Code, 64 << 12, 68 << 12);
|
loadTask(task1Code, 64 << 12, 68 << 12);
|
printf("OS: starting task1\n");
|
printf("OS: starting task1\n");
|
task1Started = 1;
|
task1Started = 1;
|
currentTask = 1;
|
currentTask = 1;
|
currentStkTop = task1StkTop;
|
currentStkTop = task1StkTop;
|
flushTLB();
|
flushTLB();
|
startTask();
|
startTask();
|
}
|
}
|
} else if (currentTask == 1) {
|
} else if (currentTask == 1) {
|
if (!task2Started) {
|
if (!task2Started) {
|
/* load & start task2 */
|
/* load & start task2 */
|
printf("\nOS: loading task2\n");
|
printf("\nOS: loading task2\n");
|
loadTask(task2Code, 96 << 12, 100 << 12);
|
loadTask(task2Code, 96 << 12, 100 << 12);
|
printf("OS: starting task2\n");
|
printf("OS: starting task2\n");
|
task2Started = 1;
|
task2Started = 1;
|
currentTask = 2;
|
currentTask = 2;
|
currentStkTop = task2StkTop;
|
currentStkTop = task2StkTop;
|
flushTLB();
|
flushTLB();
|
startTask();
|
startTask();
|
} else {
|
} else {
|
/* switch tasks */
|
/* switch tasks */
|
currentTask = 2;
|
currentTask = 2;
|
currentStkTop = task2StkTop;
|
currentStkTop = task2StkTop;
|
flushTLB();
|
flushTLB();
|
}
|
}
|
} else if (currentTask == 2) {
|
} else if (currentTask == 2) {
|
/* switch tasks */
|
/* switch tasks */
|
currentTask = 1;
|
currentTask = 1;
|
currentStkTop = task1StkTop;
|
currentStkTop = task1StkTop;
|
flushTLB();
|
flushTLB();
|
}
|
}
|
}
|
}
|
|
|
|
|
/**************************************************************/
|
/**************************************************************/
|
|
|
|
|
void main(void) {
|
void main(void) {
|
currentTask = 0;
|
currentTask = 0;
|
currentStkTop = task0StkTop;
|
currentStkTop = task0StkTop;
|
printf("\n");
|
printf("\n");
|
printf("OS: initializing interrupts\n");
|
printf("OS: initializing interrupts\n");
|
initInterrupts();
|
initInterrupts();
|
setISR(20, trapISR);
|
setISR(20, trapISR);
|
setISR(21, missISR);
|
setISR(21, missISR);
|
setISR(14, timerISR);
|
setISR(14, timerISR);
|
printf("OS: initializing timer\n");
|
printf("OS: initializing timer\n");
|
initTimer();
|
initTimer();
|
printf("OS: waiting for interrupt...\n");
|
printf("OS: waiting for interrupt...\n");
|
enable();
|
enable();
|
while (1) ;
|
while (1) ;
|
}
|
}
|
|
|