Skip to content
Snippets Groups Projects
console.c 2.9 KiB
Newer Older
#include "types.h"
#include "x86.h"
rtm's avatar
rtm committed
#include "defs.h"
rtm's avatar
rtm committed
#include "spinlock.h"

struct spinlock console_lock;
rtm's avatar
rtm committed
int paniced = 0;
int use_console_lock = 0;
rtm's avatar
rtm committed

/*
 * 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);
}

rtm's avatar
rtm committed
static void
real_cons_putc(int c)
rtm's avatar
rtm committed
{
  int crtport = 0x3d4; // io port of CGA
  unsigned short *crt = (unsigned short *) 0xB8000; // base of CGA memory
  int ind;

rtm's avatar
rtm committed
  if(paniced){
    cli();
    while(1)
      ;
  }
rtm's avatar
rtm committed

  lpt_putc(c);

rtm's avatar
rtm committed
  // 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++;
rtm's avatar
rtm committed
  }

  if((ind / 80) >= 24){
    // scroll up
rsc's avatar
 
rsc committed
    memmove(crt, crt + 80, sizeof(crt[0]) * (23 * 80));
rtm's avatar
rtm committed
    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);
rtm's avatar
rtm committed
}
rtm's avatar
rtm committed

rtm's avatar
rtm committed
void
cons_putc(int c)
{
  if(use_console_lock)
    acquire(&console_lock);
  real_cons_putc(c);
  if(use_console_lock)
    release(&console_lock);
rtm's avatar
rtm committed
}

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)
rtm's avatar
rtm committed
    real_cons_putc(buf[i]);
rtm's avatar
rtm committed
}

/*
rsc's avatar
rsc committed
 * print to the console. only understands %d, %x, %p, %s.
rtm's avatar
rtm committed
 */
void
cprintf(char *fmt, ...)
{
  int i, state = 0, c;
rsc's avatar
 
rsc committed
  unsigned int *ap = (unsigned int *)(void*)&fmt + 1;
rtm's avatar
rtm committed

rtm's avatar
rtm committed
  if(use_console_lock)
    acquire(&console_lock);

rtm's avatar
rtm committed
  for(i = 0; fmt[i]; i++){
    c = fmt[i] & 0xff;
    if(state == 0){
      if(c == '%'){
        state = '%';
      } else {
rtm's avatar
rtm committed
        real_cons_putc(c);
rtm's avatar
rtm committed
      }
    } else if(state == '%'){
      if(c == 'd'){
        printint(*ap, 10, 1);
        ap++;
      } else if(c == 'x' || c == 'p'){
rtm's avatar
rtm committed
        printint(*ap, 16, 0);
        ap++;
rsc's avatar
rsc committed
      } else if(c == 's'){
        char *s = (char*)*ap;
        ap++;
        while(*s != 0){
          real_cons_putc(*s);
          s++;
        }
rtm's avatar
rtm committed
      } else if(c == '%'){
rtm's avatar
rtm committed
        real_cons_putc(c);
rsc's avatar
rsc committed
      } else {
        // Unknown % sequence.  Print it to draw attention.
        real_cons_putc('%');
        real_cons_putc(c);
rtm's avatar
rtm committed
      }
      state = 0;
    }
  }
rtm's avatar
rtm committed

  if(use_console_lock)
    release(&console_lock);
rtm's avatar
rtm committed
}

void
panic(char *s)
{
rtm's avatar
rtm committed
  __asm __volatile("cli");
  use_console_lock = 0;
  cprintf("panic: ");
rtm's avatar
rtm committed
  cprintf(s, 0);
  cprintf("\n", 0);
rtm's avatar
rtm committed
  paniced = 1; // freeze other CPU
rtm's avatar
rtm committed
  while(1)
    ;
}