Skip to content
Snippets Groups Projects
  • rsc's avatar
    856e1fc1
    · 856e1fc1
    rsc authored
    Attempt to clean up newproc somewhat.
    
    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.
    856e1fc1
    History
    rsc authored
    Attempt to clean up newproc somewhat.
    
    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.
console.c 2.63 KiB
#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)
    ;
}