NetBSD/sys/arch/i386/netboot/cga.c

221 lines
5.1 KiB
C

/* $NetBSD: cga.c,v 1.3 1994/10/27 04:21:10 cgd Exp $ */
/* netboot
*
* source in this file came from
* the original 386BSD boot block.
*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cga.c 5.3 (Berkeley) 4/28/91
*/
#include "proto.h"
#define COL 80
#define ROW 25
#define CHR 2
#define MONO_BASE 0x3B4
#define MONO_BUF 0xB0000
#define CGA_BASE 0x3D4
#define CGA_BUF 0xB8000
static u_char att = 0x7 ;
u_char *Crtat = (u_char *)CGA_BUF;
static unsigned int addr_6845 = CGA_BASE;
static void cursor(int pos) {
outb(addr_6845, 14);
outb(addr_6845+1, pos >> 8);
outb(addr_6845, 15);
outb(addr_6845+1, pos&0xff);
}
void
putc(int c) {
#ifdef USE_BIOS
asm("
movb %0, %%cl
call _prot_to_real
.byte 0x66
mov $0x1, %%ebx
movb $0xe, %%ah
movb %%cl, %%al
sti
int $0x10
cli
.byte 0x66
call _real_to_prot
" : : "g" (ch));
#else
static u_char *crtat = 0;
unsigned cursorat; u_short was;
u_char *cp;
if (crtat == 0) {
/* XXX probe to find if a color or monochrome display */
was = *(u_short *)Crtat;
*(u_short *)Crtat = 0xA55A;
if (*(u_short *)Crtat != 0xA55A) {
Crtat = (u_char *) MONO_BUF;
addr_6845 = MONO_BASE;
}
*(u_short *)Crtat = was;
/* Extract cursor location */
outb(addr_6845,14);
cursorat = inb(addr_6845+1)<<8 ;
outb(addr_6845,15);
cursorat |= inb(addr_6845+1);
if(cursorat <= COL*ROW) {
crtat = Crtat + cursorat*CHR;
/* att = crtat[1]; */ /* use current attribute present */
} else crtat = Crtat;
/* clean display */
for (cp = crtat; cp < Crtat+ROW*COL*CHR; cp += 2) {
cp[0] = ' ';
cp[1] = att;
}
}
switch (c) {
case '\t':
do
putc(' ');
while ((int)crtat % (8*CHR));
break;
case '\010':
crtat -= CHR;
break;
case '\r':
crtat -= (crtat - Crtat) % (COL*CHR);
break;
case '\n':
crtat += COL*CHR ;
break;
default:
crtat[0] = c;
crtat[1] = att;
crtat += CHR;
break ;
}
/* implement a scroll */
if (crtat >= Crtat+COL*ROW*CHR) {
/* move text up */
bcopy((char *)(Crtat+COL*CHR), (char *)Crtat, COL*(ROW-1)*CHR);
/* clear line */
for (cp = Crtat+ COL*(ROW-1)*CHR;
cp < Crtat + COL*ROW*CHR ; cp += 2)
cp[0] = ' ';
crtat -= COL*CHR ;
}
cursor((crtat-Crtat)/CHR);
#endif
}
void
putchar(int c)
{
if (c == '\n')
putc('\r');
putc(c);
}
/* printf - only handles %d as decimal, %c as char, %s as string */
void
printf(format,data)
const char *format;
int data;
{
int *dataptr = &data;
char c;
while ((c = *format++)) {
if (c != '%')
putchar(c);
else {
switch (c = *format++) {
case 'd': {
int num = *dataptr++;
char buf[10], *ptr = buf;
if (num<0) {
num = -num;
putchar('-');
}
do
*ptr++ = '0'+num%10;
while ((num /= 10));
do
putchar(*--ptr);
while (ptr != buf);
break;
}
case 'x': {
int num = *dataptr++, dig;
char buf[8], *ptr = buf;
do
*ptr++ = (dig=(num&0xf)) > 9?
'a' + dig - 10 :
'0' + dig;
while ((num >>= 4));
do
putchar(*--ptr);
while (ptr != buf);
break;
}
case 'c': putchar((*dataptr++)&0xff); break;
case 's': {
char *ptr = (char *)*dataptr++;
while ((c = *ptr++))
putchar(c);
break;
}
}
}
}
}