📄 vga_support.c
字号:
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
// 0x70
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
{ 0xFF, 0xFF, 0xFF, 0xFF, },
};
static int KBIndexTab[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
//-----------------------------------------------------------------------------
static __inline__ cyg_uint8
inb(cyg_uint32 port)
{
cyg_uint8 val;
val = localbus_readl(port<<2);
return val;
}
static __inline__ void
outb(cyg_uint32 port, cyg_uint8 val)
{
localbus_writel(val, port<<2);
}
static cyg_bool
KeyboardInit(void)
{
unsigned char c, s;
/* flush input queue */
while ((inb(KBSTATPORT) & KBINRDY)) {
(void)inb(KBDATAPORT);
}
/* Send self-test - controller local */
while (inb(KBSTATPORT) & KBOUTRDY) c = inb(KBDATAPORT);
outb(KBCMDPORT,0xAA);
while ((inb(KBSTATPORT) & KBINRDY) == 0) ; /* wait input ready */
if ((c = inb(KBDATAPORT)) != 0x55) {
#ifdef DEBUG_KBD_INIT
diag_printf("Keyboard self test failed - result: %x\n", c);
#endif
return false;
}
/* Enable interrupts and keyboard controller */
while (inb(KBSTATPORT) & KBOUTRDY) ;
outb(KBCMDPORT,0x60);
while (inb(KBSTATPORT) & KBOUTRDY) ;
outb(KBCMDPORT,0x45);
CYGACC_CALL_IF_DELAY_US(10000); // 10ms
while (inb(KBSTATPORT) & KBOUTRDY) ;
outb(KBCMDPORT,0xAE); // Enable keyboard
/* See if a keyboard is connected */
while (inb(KBSTATPORT) & KBOUTRDY) ;
outb(KBDATAPORT,0xFF);
while (((s = inb(KBSTATPORT)) & (KBINRDY|KBTXTO)) == 0) ; /* wait input ready */
if ((s & KBTXTO) || ((c = inb(KBDATAPORT)) != 0xFA)) {
#ifdef DEBUG_KBD_INIT
diag_printf("Keyboard reset failed - no ACK: %x, stat: %x\n", c, s);
#endif
return false;
}
while (((s = inb(KBSTATPORT)) & KBINRDY) == 0) ; /* wait input ready */
if ((s & KBTXTO) || ((c = inb(KBDATAPORT)) != 0xAA)) {
#ifdef DEBUG_KBD_INIT
diag_printf("Keyboard reset failed - bad code: %x, stat: %x\n", c, s);
#endif
return false;
}
// Set scan mode
while (inb(KBSTATPORT) & KBOUTRDY) ;
outb(KBCMDPORT,0x20);
while ((inb(KBSTATPORT) & KBINRDY) == 0) ; /* wait input ready */
if (! (inb(KBDATAPORT) & 0x40)) {
/*
* Quote from PS/2 System Reference Manual:
*
* "Address hex 0060 and address hex 0064 should be
* written only when the input-buffer-full bit and
* output-buffer-full bit in the Controller Status
* register are set 0." (KBINRDY and KBOUTRDY)
*/
while (inb(KBSTATPORT) & (KBINRDY | KBOUTRDY)) ;
outb(KBDATAPORT,0xF0);
while (inb(KBSTATPORT) & (KBINRDY | KBOUTRDY)) ;
outb(KBDATAPORT,0x01);
}
KBFlags = 0;
return true;
} /* KeyboardInit */
//-----------------------------------------------------------------------------
static CYG_BYTE
KeyboardAscii(CYG_BYTE scancode)
{
CYG_BYTE ascii = 0xFF;
// Start by handling all shift/ctl keys:
switch( scancode ) {
case 0xe0:
KBFlags |= KBExtend;
return 0xFF;
case 0xfa:
KBFlags |= KBAck;
return 0xFF;
case 0xfe:
KBFlags |= KBResend;
return 0xFF;
case LSHIFT:
KBFlags |= KBShiftL;
return 0xFF;
case LSHIFT | BREAK:
KBFlags &= ~KBShiftL;
return 0xFF;
case RSHIFT:
KBFlags |= KBShiftR;
return 0xFF;
case RSHIFT | BREAK:
KBFlags &= ~KBShiftR;
return 0xFF;
case CTRL:
if( KBFlags & KBExtend )
{
KBFlags |= KBCtrlR;
KBFlags &= ~KBExtend;
}
else KBFlags |= KBCtrlL;
return 0xFF;
case CTRL | BREAK:
if( KBFlags & KBExtend )
{
KBFlags &= ~KBCtrlR;
KBFlags &= ~KBExtend;
}
else KBFlags &= ~KBCtrlL;
return 0xFF;
case ALT:
if( KBFlags & KBExtend )
{
KBFlags |= KBAltR;
KBFlags &= ~KBExtend;
}
else KBFlags |= KBAltL;
return 0xFF;
case ALT | BREAK:
if( KBFlags & KBExtend )
{
KBFlags &= ~KBAltR;
KBFlags &= ~KBExtend;
}
else KBFlags &= ~KBAltL;
return 0xFF;
case CAPS:
KBFlags ^= KBCapsLock;
case CAPS | BREAK:
return 0xFF;
case NUMS:
KBFlags ^= KBNumLock;
case NUMS | BREAK:
return 0xFF;
case KBArrowUp:
case KBArrowDown:
screen_pan = 0;
vga_refresh();
break;
case KBArrowLeft:
screen_pan -= SCREEN_PAN;
if (screen_pan < 0) screen_pan = 0;
vga_refresh();
break;
case KBArrowRight:
screen_pan += SCREEN_PAN;
if (screen_pan > (SCREEN_WIDTH-SCREEN_PAN))
screen_pan = SCREEN_WIDTH-SCREEN_PAN;
vga_refresh();
break;
}
// Clear Extend flag if set
KBFlags &= ~KBExtend;
// Ignore all other BREAK codes
if( scancode & 0x80 ) return 0xFF;
// Here the scancode is for something we can turn
// into an ASCII value
ascii = KBScanTable[scancode & 0x7F][KBIndexTab[KBFlags & KBIndex]];
return ascii;
} /* KeyboardAscii */
//-----------------------------------------------------------------------------
static int
KeyboardTest(void)
{
// If there is a pending character, return True
if( KBPending != 0xFF ) return true;
// If there is something waiting at the port, get it
for(;;) {
CYG_BYTE stat, code;
CYG_BYTE c;
stat = inb(KBSTATPORT);
if( (stat & KBINRDY) == 0 )
break;
code = inb(KBDATAPORT);
// Translate to ASCII
c = KeyboardAscii(code);
// if it is a real ASCII char, save it and
// return True.
if( c != 0xFF ) {
KBPending = c;
return true;
}
}
// Otherwise return False
return false;
} /* KeyboardTest */
char
KeyboardChar(void)
{
char c = KBPending;
KBPending = 0xFF;
return c;
}
static int _timeout = 500;
static cyg_bool
vga_comm_getc_nonblock(void* __ch_data, cyg_uint8* ch)
{
if( !KeyboardTest() )
return false;
*ch = KBPending;
KBPending = 0xFF;
return true;
}
static cyg_uint8
vga_comm_getc(void* __ch_data)
{
cyg_uint8 ch;
while (!vga_comm_getc_nonblock(__ch_data, &ch)) ;
return ch;
}
static void
vga_comm_putc(void* __ch_data, cyg_uint8 c)
{
vga_putc(c);
}
static void
vga_comm_write(void* __ch_data, const cyg_uint8* __buf, cyg_uint32 __len)
{
#if 0
CYGARC_HAL_SAVE_GP();
while(__len-- > 0)
vga_comm_putc(__ch_data, *__buf++);
CYGARC_HAL_RESTORE_GP();
#endif
}
static void
vga_comm_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
{
#if 0
CYGARC_HAL_SAVE_GP();
while(__len-- > 0)
*__buf++ = vga_comm_getc(__ch_data);
CYGARC_HAL_RESTORE_GP();
#endif
}
static cyg_bool
vga_comm_getc_timeout(void* __ch_data, cyg_uint8* ch)
{
int delay_count;
cyg_bool res;
delay_count = _timeout * 2; // delay in .5 ms steps
for(;;) {
res = vga_comm_getc_nonblock(__ch_data, ch);
if (res || 0 == delay_count--)
break;
CYGACC_CALL_IF_DELAY_US(500);
}
return res;
}
static int
vga_comm_control(void *__ch_data, __comm_control_cmd_t __func, ...)
{
static int vector = 0;
int ret = -1;
static int irq_state = 0;
CYGARC_HAL_SAVE_GP();
switch (__func) {
case __COMMCTL_IRQ_ENABLE:
ret = irq_state;
irq_state = 1;
break;
case __COMMCTL_IRQ_DISABLE:
ret = irq_state;
irq_state = 0;
break;
case __COMMCTL_DBG_ISR_VECTOR:
ret = vector;
break;
case __COMMCTL_SET_TIMEOUT:
{
va_list ap;
va_start(ap, __func);
ret = _timeout;
_timeout = va_arg(ap, cyg_uint32);
va_end(ap);
break;
}
case __COMMCTL_FLUSH_OUTPUT:
ret = 0;
break;
default:
break;
}
CYGARC_HAL_RESTORE_GP();
return ret;
}
static int
vga_comm_isr(void *__ch_data, int* __ctrlc,
CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
{
#if 0
char ch;
cyg_drv_interrupt_acknowledge(__vector);
*__ctrlc = 0;
if (vga_comm_getc_nonblock(__ch_data, &ch)) {
if (ch == 0x03) {
*__ctrlc = 1;
}
}
return CYG_ISR_HANDLED;
#else
return 0;
#endif
}
void
vga_comm_init(cyg_uint32 *addr)
{
static int init = 0;
if (!init) {
hal_virtual_comm_table_t* comm;
int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
init = 1;
if (!KeyboardInit()) {
// No keyboard - no VGA/CRT display
return;
}
// Initialize screen
cursor_enable = true;
vga_init(addr);
vga_on(true);
vga_screen_clear();
// Setup procs in the vector table
CYGACC_CALL_IF_SET_CONSOLE_COMM(1); // FIXME - should be controlled by CDL
comm = CYGACC_CALL_IF_CONSOLE_PROCS();
//CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
CYGACC_COMM_IF_WRITE_SET(*comm, vga_comm_write);
CYGACC_COMM_IF_READ_SET(*comm, vga_comm_read);
CYGACC_COMM_IF_PUTC_SET(*comm, vga_comm_putc);
CYGACC_COMM_IF_GETC_SET(*comm, vga_comm_getc);
CYGACC_COMM_IF_CONTROL_SET(*comm, vga_comm_control);
CYGACC_COMM_IF_DBG_ISR_SET(*comm, vga_comm_isr);
CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, vga_comm_getc_timeout);
// Restore original console
CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
}
}
#ifdef CYGPKG_REDBOOT
#include <redboot.h>
// Get here when RedBoot is idle. If it's been long enough, then
// dim the VGA. The problem is - how to determine other activities
// so at this doesn't get in the way. In the default case, this will
// be called from RedBoot every 10ms (CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT)
#define MAX_IDLE_TIME (30*100)
static void
idle(bool is_idle)
{
static int idle_time = 0;
static bool was_idled = false;
if (is_idle) {
if (!was_idled) {
if (++idle_time == MAX_IDLE_TIME) {
was_idled = true;
vga_on(false);
}
}
} else {
idle_time = 0;
if (was_idled) {
was_idled = false;
vga_on(true);
}
}
}
RedBoot_idle(idle, RedBoot_AFTER_NETIO);
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -