856e1fc1ad
Also remove all calls to memcpy in favor of memmove, which has defined semantics when the ranges overlap. The fact that memcpy was working in console.c to scroll the screen is not guaranteed by all implementations.
158 lines
2.6 KiB
C
158 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
|
|
memmove(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 *)(void*)&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)
|
|
;
|
|
}
|