console.c 3.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * File      : console.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006, RT-Thread Development Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://openlab.rt-thread.com/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-09-15     QiuYi        the first version
 */

#include <rtthread.h>
#include <rthw.h>

#include <bsp.h>

20 21 22

#include "serial.h"

23 24
static unsigned addr_6845;
static rt_uint16_t *crt_buf;
25
static rt_int16_t  crt_pos;
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

extern void rt_serial_init(void);
extern char rt_keyboard_getc(void);

static void rt_console_putc(int c);

/**
 * @addtogroup QEMU
 */
/*@{*/

/**
 * This function initializes cga
 *
 */
void rt_cga_init(void)
{
	rt_uint16_t volatile *cp;
	rt_uint16_t was;
	rt_uint32_t pos;

47
	cp = (rt_uint16_t *) (CGA_BUF);
48 49 50 51
	was = *cp;
	*cp = (rt_uint16_t) 0xA55A;
	if (*cp != 0xA55A)
	{
52
		cp = (rt_uint16_t *) (MONO_BUF);
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
		addr_6845 = MONO_BASE;
	}
	else
	{
		*cp = was;
		addr_6845 = CGA_BASE;
	}

	/* Extract cursor location */
	outb(addr_6845, 14);
	pos = inb(addr_6845+1) << 8;
	outb(addr_6845, 15);
	pos |= inb(addr_6845+1);

	crt_buf = (rt_uint16_t *)cp;
	crt_pos = pos;
}

/**
 * This function will write a character to cga
 *
 * @param c the char to write
 */
static void rt_cga_putc(int c)
{
	/* if no attribute given, then use black on white */
	if (!(c & ~0xff)) c |= 0x0700;

	switch (c & 0xff)
	{
	case '\b':
		if (crt_pos > 0)
		{
			crt_pos--;
			crt_buf[crt_pos] = (c&~0xff) | ' ';
		}
		break;
	case '\n':
		crt_pos += CRT_COLS;
		/* cascade	*/
	case '\r':
		crt_pos -= (crt_pos % CRT_COLS);
		break;
	case '\t':
		rt_console_putc(' ');
		rt_console_putc(' ');
		rt_console_putc(' ');
		rt_console_putc(' ');
		rt_console_putc(' ');
		break;
	default:
		crt_buf[crt_pos++] = c;		/* write the character */
		break;
	}

	if (crt_pos >= CRT_SIZE)
	{
110
		rt_int32_t i;
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
		rt_memcpy(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) << 1);
		for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)
			crt_buf[i] = 0x0700 | ' ';
		crt_pos -= CRT_COLS;
	}

	outb(addr_6845, 14);
	outb(addr_6845+1, crt_pos >> 8);
	outb(addr_6845, 15);
	outb(addr_6845+1, crt_pos);
}

/**
 * This function will write a character to serial an cga
 *
 * @param c the char to write
 */
static void rt_console_putc(int c)
{
	rt_cga_putc(c);
	rt_serial_putc(c);
}

/**
 * This function initializes console
 *
 */
void rt_console_init(void)
{
	rt_cga_init();
	rt_serial_init();
}

/**
 * This function is used to display a string on console, normally, it's 
 * invoked by rt_kprintf
 *
 * @param str the displayed string
149 150 151 152 153
 *
 * Modified:
 *	caoxl 2009-10-14
 *	the name is change to rt_hw_console_output in the v0.3.0
 *
154
 */
155 156 157

//void rt_console_puts(const char* str)
void rt_hw_console_output(const char* str)
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
{
	while (*str)
	{
		rt_console_putc (*str++);
	}
}

#define BY2CONS 512

static struct
{
	rt_uint8_t buf[BY2CONS];
	rt_uint32_t rpos;
	rt_uint32_t wpos;
}cons;

static void rt_console_intr(char (*proc)(void))
{
	int c;

	while ((c = (*proc)()) != -1)
	{
		if (c == 0)
			continue;
		cons.buf[cons.wpos++] = c;
		if (cons.wpos == BY2CONS)
			cons.wpos = 0;
	}
}

/**
 * return the next input character from the console,either from serial,
 * or keyboard
 *
 */
int rt_console_getc(void)
{
	int c;

	rt_console_intr(rt_serial_getc);
	rt_console_intr(rt_keyboard_getc);

	if (cons.rpos != cons.wpos)
	{
		c = cons.buf[cons.rpos++];
		if (cons.rpos == BY2CONS)
			cons.rpos = 0;
		return c;
	}
	return 0;
}

/*@}*/