46bbd72f3e
wakeup1() assumes you hold proc_table_lock sleep(chan, lock) provides atomic sleep-and-release to wait for condition ugly code in swtch/scheduler to implement new sleep fix lots of bugs in pipes, wait, and exit fix bugs if timer interrupt goes off in schedule() console locks per line, not per byte
159 lines
2.6 KiB
C
159 lines
2.6 KiB
C
#include <types.h>
|
|
#include <x86.h>
|
|
#include "defs.h"
|
|
#include "spinlock.h"
|
|
|
|
struct spinlock console_lock;
|
|
int paniced = 0;
|
|
int use_console_lock = 0;
|
|
|
|
/*
|
|
* copy console output to parallel port, which you can tell
|
|
* .bochsrc to copy to the stdout:
|
|
* parport1: enabled=1, file="/dev/stdout"
|
|
*/
|
|
static void
|
|
lpt_putc(int c)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; !(inb(0x378+1) & 0x80) && i < 12800; i++)
|
|
;
|
|
outb(0x378+0, c);
|
|
outb(0x378+2, 0x08|0x04|0x01);
|
|
outb(0x378+2, 0x08);
|
|
}
|
|
|
|
static void
|
|
real_cons_putc(int c)
|
|
{
|
|
int crtport = 0x3d4; // io port of CGA
|
|
unsigned short *crt = (unsigned short *) 0xB8000; // base of CGA memory
|
|
int ind;
|
|
|
|
if(paniced){
|
|
cli();
|
|
while(1)
|
|
;
|
|
}
|
|
|
|
lpt_putc(c);
|
|
|
|
// cursor position, 16 bits, col + 80*row
|
|
outb(crtport, 14);
|
|
ind = inb(crtport + 1) << 8;
|
|
outb(crtport, 15);
|
|
ind |= inb(crtport + 1);
|
|
|
|
c &= 0xff;
|
|
|
|
if(c == '\n'){
|
|
ind -= (ind % 80);
|
|
ind += 80;
|
|
} else {
|
|
c |= 0x0700; // black on white
|
|
crt[ind] = c;
|
|
ind += 1;
|
|
}
|
|
|
|
if((ind / 80) >= 24){
|
|
// scroll up
|
|
memcpy(crt, crt + 80, sizeof(crt[0]) * (23 * 80));
|
|
ind -= 80;
|
|
memset(crt + ind, 0, sizeof(crt[0]) * ((24 * 80) - ind));
|
|
}
|
|
|
|
outb(crtport, 14);
|
|
outb(crtport + 1, ind >> 8);
|
|
outb(crtport, 15);
|
|
outb(crtport + 1, ind);
|
|
}
|
|
|
|
void
|
|
cons_putc(int c)
|
|
{
|
|
if(use_console_lock)
|
|
acquire(&console_lock);
|
|
real_cons_putc(c);
|
|
if(use_console_lock)
|
|
release(&console_lock);
|
|
}
|
|
|
|
void
|
|
printint(int xx, int base, int sgn)
|
|
{
|
|
char buf[16];
|
|
char digits[] = "0123456789ABCDEF";
|
|
int i = 0, neg = 0;
|
|
unsigned int x;
|
|
|
|
if(sgn && xx < 0){
|
|
neg = 1;
|
|
x = 0 - xx;
|
|
} else {
|
|
x = xx;
|
|
}
|
|
|
|
do {
|
|
buf[i++] = digits[x % base];
|
|
} while((x /= base) != 0);
|
|
if(neg)
|
|
buf[i++] = '-';
|
|
|
|
while(i > 0){
|
|
i -= 1;
|
|
real_cons_putc(buf[i]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* print to the console. only understands %d and %x.
|
|
*/
|
|
void
|
|
cprintf(char *fmt, ...)
|
|
{
|
|
int i, state = 0, c;
|
|
unsigned int *ap = (unsigned int *) &fmt + 1;
|
|
|
|
if(use_console_lock)
|
|
acquire(&console_lock);
|
|
|
|
for(i = 0; fmt[i]; i++){
|
|
c = fmt[i] & 0xff;
|
|
if(state == 0){
|
|
if(c == '%'){
|
|
state = '%';
|
|
} else {
|
|
real_cons_putc(c);
|
|
}
|
|
} else if(state == '%'){
|
|
if(c == 'd'){
|
|
printint(*ap, 10, 1);
|
|
ap++;
|
|
} else if(c == 'x' || c == 'p'){
|
|
printint(*ap, 16, 0);
|
|
ap++;
|
|
} else if(c == '%'){
|
|
real_cons_putc(c);
|
|
}
|
|
state = 0;
|
|
}
|
|
}
|
|
|
|
if(use_console_lock)
|
|
release(&console_lock);
|
|
}
|
|
|
|
void
|
|
panic(char *s)
|
|
{
|
|
__asm __volatile("cli");
|
|
use_console_lock = 0;
|
|
cprintf("panic: ");
|
|
cprintf(s, 0);
|
|
cprintf("\n", 0);
|
|
paniced = 1; // freeze other CPU
|
|
while(1)
|
|
;
|
|
}
|