You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

881 lines
25 KiB

/* vxbM6845Vga.c - motorola 6845 VGA console driver */
/*
* Copyright (c) 2007, 2008, 2010, 2012, 2013 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01p,21may13,y_y initialized the paramter escFlags. (WIND00416649)
01o,17aug12,clx Removed unnecessary import function declare. (WIND00365597)
01n,02feb12,sye Removed redundant auto wrapped blank line. (WIND00311642)
01m,06sep10,jxu Replace inclusion of funcBindP.h with selectLibP.h
01l,03may10,h_k cleaned up a compiler warning.
01k,07jan10,jc0 LP64 adaptation.
01j,12dec08,h_k added more information in the API reference manual.
01i,27aug08,jpb Renamed VSB header file
01h,18jun08,jpb Renamed _WRS_VX_SMP to _WRS_CONFIG_SMP. Added include path
for kernel configurations options set in vsb.
01g,16jun08,pmr resource documentation
01f,05may08,tor update version
01e,06mar08,tor resource meta-data update
01d,20sep07,tor VXB_VERSION_3
01c,17aug07,pmr new register access methods
01b,09mar07,pmr SMP-safe.
01a,20feb07,pmr adapted for VxBus from version 01e.
*/
/*
DESCRIPTION
This is the driver fo Video Contoroller Chip (6845) normally used in the
386/486 personal computers.
USER CALLABLE ROUTINES
This driver provides several VxBus methods for external access to its
routines.
All virtual consoles are mapped to the same screen buffer. This is a
very basic implementation of virtual consoles. Multiple screen
buffers are not used to switch between consoles. This implementation
is left for the future. Mutual exclusion for the screen buffer is
guaranteed within the same console but it is not implemented across multiple
virtual consoles because all virtual consoles use the same screen buffer. If
multiple screen buffers are implemented then the mutual exclusion between
virtual consoles can be implemented.
This driver suports the ansi escape sequences and special processing in the
m6845 driver will be done if an escape sequence exists.
If the ansi escape sequences are not required, please rebuild this driver
without defining INCLUDE_ANSI_ESC_SEQUENCE macro, which is explicitly defined
in this file.
TARGET-SPECIFIC PARAMETERS
The parameters are provided through `m6845Vga' registration defined in
hwconf.c in the target BSP.
\is
\i <regBase>
The Video Contoroller Chip register base address.
The parameter type is HCF_RES_INT, or HCF_RES_ADDR for 64-bit address in LP64.
If not specified, 0 will be set in the register base address and VXB_REG_NONE
will be set in the register base flag that will cause a failure at vxbRegMap()
to obtain the access handle.
\i <regBase1>
The address of video memory.
If not specified, the address passed by <memBase> will be set as the video
memory address.
The parameter type is HCF_RES_INT, or HCF_RES_ADDR for 64-bit address in LP64.
\i <memBase>
The address of video memory (for backward compatibility).
If not specified here nor in <regBase1>, 0 will be set as the video memory
address.
The parameter type is HCF_RES_INT, or HCF_RES_ADDR for 64-bit address in LP64.
\i <colorMode>
Specify color mode, COLOR(1) or MONO(0).
If not specified, MONO(0) will be set as the color mode.
The parameter type is HCF_RES_INT.
\i <colorSetting>
Specify the foreground and background display colors.
If not specifed, (ATRB_FG_BRIGHTWHITE | ATRB_BG_BROWN) will be set when the
<colorMode> is COLOR(1) and (ATRB_FG_WHITE | ATRB_BG_BLACK) will be set when
the <colorMode> is MONO(0) for the display attributes.
The parameter type is HCF_RES_INT.
\ie
By convention all the BSP-specific device parameters are registered in
a file called hwconf.c, which is #include'ed by sysLib.c.
The following is an example in pcPentium4 BSP:
\cs
LOCAL const struct hcfResource pentiumM6845VgaResources[] =
{
{ "regBase", HCF_RES_ADDR, {(void *) CTRL_SEL_REG} },
{ "regBase1", HCF_RES_ADDR, {(void *) CTRL_MEM_BASE} },
{ "colorMode", HCF_RES_INT, {(void *) COLOR_MODE} },
{ "colorSetting",HCF_RES_INT, {(void *) DEFAULT_ATR} },
};
#define pentiumM6845VgaNum NELEMENTS(pentiumM6845VgaResources)
const struct hcfDevice hcfDeviceList[] = {
...
{ "m6845Vga", 0, VXB_BUSID_PLB, 0, pentiumM6845VgaNum,
pentiumM6845VgaResources },
...
};
\ce
CONFIGURATION
To use the driver, configure VxWorks with the
DRV_VGA_M6845 component.
The required components for this driver are
INCLUDE_VXBUS
INCLUDE_PLB_BUS
INCLUDE_PC_CONSOLE
which will be dragged by Kernel Configuration tool if not included in the
VxWorks Image Project (VIP) when the DRV_VGA_M6845 is added.
You need to define all the required components when the DRV_VGA_M6845
is added in config.h for BSP build unless they are already defined.
NOTES
The macro N_VIRTUAL_CONSOLES should be defined in config.h file.
This refers to the number of virtual consoles which the user wishes to have.
SEE ALSO: tyLib, vxbPcConsole and VxWorks Device Driver Developer's Guide.
*/
/* includes */
#include <vxWorks.h>
#include <vsbConfig.h>
#include <iv.h>
#include <ioLib.h>
#include <iosLib.h>
#include <memLib.h>
#include <private/funcBindP.h>
#include <intLib.h>
#include <taskLib.h>
#include <errnoLib.h>
#include <stdio.h>
#include <string.h>
#include "font_8x16.h"
#include <private/funcBindP.h>
#include <private/selectLibP.h> /* _func_selWakeupAll */
/* SMP */
#ifdef _WRS_CONFIG_SMP
#include <spinLockLib.h>
#define M6845_LOCK_TAKE(p) \
if (INT_CONTEXT()) \
SPIN_LOCK_ISR_TAKE(&p->pTyDev->spinlockIsr)
#define M6845_LOCK_GIVE(p) \
if (INT_CONTEXT()) \
SPIN_LOCK_ISR_GIVE(&p->pTyDev->spinlockIsr)
#else /* _WRS_CONFIG_SMP */
#define M6845_LOCK_TAKE(p)
#define M6845_LOCK_GIVE(p)
#endif /* _WRS_CONFIG_SMP */
#define DEFAULT_FB_MEM 0x00000000
/* VXBUS */
#include <vxBusLib.h>
#include <hwif/util/hwMemLib.h>
#include <hwif/vxbus/vxBus.h>
#include <hwif/vxbus/vxbPlbLib.h>
#include <hwif/vxbus/hwConf.h>
#include <../src/hwif/h/vxbus/vxbAccess.h>
/*#define INCLUDE_ANSI_ESC_SEQUENCE*/
#include "vxbM6845Vga.h"
/* VxBus structures and methods */
/* imports */
IMPORT TY_DEV * pcConDevBind (int, FUNCPTR, void *);
UINT32 pcConframeBufferAddr;
/* locals */
LOCAL UINT32 defaultFbBase = 0;
LOCAL size_t tyWrtThreshold = 20;
LOCAL BOOL m6845vxbProbe (VXB_DEVICE_ID pDev);
LOCAL void m6845vxbInstInit (VXB_DEVICE_ID pDev);
LOCAL void m6845vxbInstInit2 (VXB_DEVICE_ID pDev);
LOCAL void m6845vxbInstConnect (VXB_DEVICE_ID pDev);
LOCAL struct drvBusFuncs m6845vxbFuncs =
{
m6845vxbInstInit, /* devInstanceInit */
m6845vxbInstInit2, /* devInstanceInit2 */
m6845vxbInstConnect /* devConnect */
};
LOCAL void m6845ScreenRevMethod (VXB_DEVICE_ID, int);
LOCAL void m6845CurAttribMethod (VXB_DEVICE_ID, int);
LOCAL void m6845CursorSetMethod (VXB_DEVICE_ID, int);
LOCAL void m6845CursorMoveMethod (VXB_DEVICE_ID, int);
LOCAL struct vxbDeviceMethod m6845VgaMethods[] =
{
DEVMETHOD(vgaScreenRev, m6845ScreenRevMethod),
DEVMETHOD(vgaCurAttrib, m6845CurAttribMethod),
DEVMETHOD(vgaCursorSet, m6845CursorSetMethod),
DEVMETHOD(vgaCursorMove, m6845CursorMoveMethod),
{0, 0}
};
LOCAL struct vxbDevRegInfo m6845vxbDevRegistration =
{
NULL, /* pNext */
VXB_DEVID_DEVICE, /* devID */
VXB_BUSID_PLB, /* busID = PLB */
VXB_VER_4_0_0, /* vxbVersion */
"m6845Vga", /* drvName */
&m6845vxbFuncs, /* pDrvBusFuncs */
m6845VgaMethods, /* pMethods */
m6845vxbProbe /* devProbe */
};
LOCAL UCHAR * m6845CharTable [] =
{
/* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */
(unsigned char *)
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`abcdefghijklmnopqrstuvwxyz{|}~\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
"\376\245\376\376\376\376\231\376\235\376\376\376\232\376\376\341"
"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
"\376\244\225\242\223\376\224\366\233\227\243\226\201\376\376\230",
/* vt100 graphics */
(unsigned char *)
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
" !\"#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
"\004\261\007\007\007\007\370\361\040\007\331\277\332\300\305\007"
"\007\304\007\007\303\264\301\302\263\007\007\007\007\007\234\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\040\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
"\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
"\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
"\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
"\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
"\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
/* IBM graphics: minimal translations (CR, LF, LL, SO, SI and ESC) */
(unsigned char *)
"\000\001\002\003\004\005\006\007\010\011\000\013\000\000\000\000"
"\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
"\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
"\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
"\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
"\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
};
/* forward declarations */
LOCAL void m6845HrdInit (M6845_CON_DEV *);
LOCAL void m6845StatInit (M6845_CON_DEV *);
LOCAL int m6845WriteString (M6845_CON_DEV *);
/******************************************************************************
*
* m6845HrdInit - initialize the VGA Display
*
* This function is called externally to initialize the m6845 display
*
* RETURNS: N/A
*
* NOMANUAL
*/
#define PCCON_BUFFER_SIZE (1*1024*1024)
LOCAL void m6845HrdInit
(
M6845_CON_DEV * pDrvCtrl
)
{
pcConframeBufferAddr = (UINT32)cacheDmaMalloc(PCCON_BUFFER_SIZE);
defaultFbBase = pcConframeBufferAddr;
m6845StatInit (pDrvCtrl);
}
/*******************************************************************************
*
* m6845StatInit - initialize the VGA Display state
*
* RETURNS: N/A
*/
LOCAL void m6845StatInit
(
M6845_CON_DEV * pDrvCtrl
)
{
HCF_DEVICE * pHcf = hcfDeviceGet (pDrvCtrl->pDev);
pDrvCtrl->memBase = (void*)defaultFbBase;
devResourceGet (pHcf, "colorMode", HCF_RES_INT, (void *)&pDrvCtrl->colorMode);
if (pDrvCtrl->colorMode == COLOR)
pDrvCtrl->defAttrib = ATRB_FG_BRIGHTWHITE | ATRB_BG_BROWN;
else
pDrvCtrl->defAttrib = ATRB_FG_WHITE | ATRB_BG_BLACK;
devResourceGet (pHcf, "colorSetting", HCF_RES_INT, (void *)&pDrvCtrl->defAttrib);
pDrvCtrl->sv_curAttrib = pDrvCtrl->defAttrib;
pDrvCtrl->curAttrib = pDrvCtrl->defAttrib;
pDrvCtrl->sv_col = pDrvCtrl->col = 0;
pDrvCtrl->sv_row = pDrvCtrl->row = 0;
pDrvCtrl->curChrPos = pDrvCtrl->memBase; /* current position */
pDrvCtrl->sv_rev = pDrvCtrl->rev = FALSE;
pDrvCtrl->ncol = (screen_size_x/2/8); /* Number of columns */
pDrvCtrl->nrow = screen_size_y/16; /* Number of text rows */
pDrvCtrl->scst = 0; /* scroll start */
pDrvCtrl->sced = screen_size_y/16-1; /* scroll end */
pDrvCtrl->autoWrap = TRUE; /* auto Wrap mode */
pDrvCtrl->scrollCheck = FALSE; /* scroll flag off */
pDrvCtrl->charSet = m6845CharTable [TEXT_SET]; /* character set */
pDrvCtrl->vgaMode = TEXT_MODE; /* video mode */
pDrvCtrl->insMode = INSERT_MODE_OFF; /* insert mode */
pDrvCtrl->escParaCount = 0; /* zero parameters */
pDrvCtrl->escQuestion = FALSE; /* ? flag set to false */
bzero ((char *)pDrvCtrl->escPara, sizeof(pDrvCtrl->escPara));
bzero (pDrvCtrl->tab_stop, sizeof(pDrvCtrl->tab_stop));
pDrvCtrl->tab_stop [ 0] = 1;
pDrvCtrl->tab_stop [ 8] = 1;
pDrvCtrl->tab_stop [16] = 1;
pDrvCtrl->tab_stop [24] = 1;
pDrvCtrl->tab_stop [32] = 1;
pDrvCtrl->tab_stop [40] = 1;
pDrvCtrl->tab_stop [48] = 1;
pDrvCtrl->tab_stop [56] = 1;
pDrvCtrl->tab_stop [64] = 1;
pDrvCtrl->tab_stop [72] = 1;
}
/******************************************************************************
*
* m6845ScreenRev - Reverse Screen
*
* RETURNS: N/A
*/
LOCAL void m6845ScreenRev
(
FAST M6845_CON_DEV * pDrvCtrl /* pointer to the m6845 descriptor */
)
{
UCHAR * cp; /* to hold the current pointer */
UCHAR atr; /* to hold the attribute character */
for (cp = pDrvCtrl->memBase; cp < pDrvCtrl->memBase + 2000 * 2;
cp += 2)
{
atr = *(cp+1);
*(cp+1) = atr & INT_BLINK_MASK;
*(cp+1) |= (atr << 4) & BG_ATTR_MASK;
*(cp+1) |= (atr >> 4) & FG_ATTR_MASK;
}
}
/******************************************************************************
*
* m6845CursorPos - Put the cursor at a specified location
*
* RETURNS: N/A
*/
LOCAL void m6845CursorPos
(
M6845_CON_DEV * pDrvCtrl,
FAST UINT16 pos /* position of the cursor */
)
{
return;
}
/******************************************************************************
*
* m6845CursorOn - switch the cursor on
*
* RETURNS: N/A
*/
LOCAL void m6845CursorOn
(
M6845_CON_DEV * pDrvCtrl
)
{
return;
}
/******************************************************************************
*
* m6845CursorOff - switch the cursor off
*
* RETURNS: N/A
*/
LOCAL void m6845CursorOff
(
M6845_CON_DEV * pDrvCtrl
)
{
return;
}
/* VxBus routines */
/******************************************************************************
*
* m6845vxbRegister - register m6845vxb driver
*
* This routine registers the m6845vxb driver and device recognition
* data with the vxBus subsystem.
*
* NOTE:
*
* This routine is called early during system initialization, and
* *MUST NOT* make calls to OS facilities such as memory allocation
* and I/O.
*
* RETURNS: N/A
*
* ERRNO
*/
void m6845vxbRegister(void)
{
vxbDevRegister(&m6845vxbDevRegistration);
}
/******************************************************************************
*
* m6845vxbProbe - probe for device presence
*
* NOTE:
*
* This routine is called early during system initialization, and
* *MUST* *NOT* make calls to OS facilities such as memory allocation
* and I/O.
*
* RETURNS: TRUE if probe passes and assumed a valid m6845vxb
* (or compatible) device. FALSE otherwise.
*
*/
LOCAL BOOL m6845vxbProbe
(
VXB_DEVICE_ID pDev /* Device information */
)
{
return (TRUE);
}
/******************************************************************************
*
* m6845vxbInstInit - initialize m6845vxb device
*
* This is the m6845vxb initialization routine.
*
* NOTE:
*
* This routine is called early during system initialization, and
* *MUST NOT* make calls to OS facilities such as memory allocation
* and I/O.
*
* RETURNS: N/A
*
* ERRNO
*/
LOCAL void m6845vxbInstInit
(
VXB_DEVICE_ID pDev
)
{
return;
}
/******************************************************************************
*
* m6845vxbInstInit2 - initialize m6845vxb device
*
* This is the m6845vxb initialization routine.
*
* NOTE:
*
* This routine is called early during system initialization, and
* *MUST NOT* make calls to OS facilities such as memory allocation
* and I/O.
*
* RETURNS: N/A
*
* ERRNO
*/
LOCAL void m6845vxbInstInit2
(
VXB_DEVICE_ID pDev
)
{
M6845_CON_DEV * pDrvCtrl = (M6845_CON_DEV *) malloc (sizeof (M6845_CON_DEV));
pDrvCtrl->pDev = pDev;
pDev->pDrvCtrl = pDrvCtrl;
pDev->pMethods = m6845VgaMethods;
vxbRegMap (pDev, 0, &pDrvCtrl->regHandle);
m6845HrdInit (pDrvCtrl);
}
/******************************************************************************
*
* m6845vxbInstConnect - connect m6845vxb device
*
* This is the m6845vxb connect routine.
*
* NOTE:
*
* This routine is called early during system initialization, and
* *MUST NOT* make calls to OS facilities such as memory allocation
* and I/O.
*
* RETURNS: N/A
*
* ERRNO
*/
LOCAL void m6845vxbInstConnect
(
VXB_DEVICE_ID pDev
)
{
M6845_CON_DEV * pDrvCtrl = pDev->pDrvCtrl;
pDrvCtrl->pTyDev = pcConDevBind (pDev->unitNumber,
m6845WriteString, (void *) pDrvCtrl);
}
void draw_char(unsigned char c, int x, int y)
{
int i,j;
unsigned char *VGA_DEV;
unsigned char *base;
unsigned char line;
VGA_DEV = (unsigned char *)(defaultFbBase + DEFAULT_FB_MEM);
base = &((VGA_DEV)[y*screen_size_x + x * depth]);
for(i=0; i<CHAR_HEIGHT; i++) {
line = FONT[c * CHAR_HEIGHT + i];
for(j=CHAR_WIDTH * depth; j > 0; j -= 2 ) {
base[ j ] = (line & 0x1) ? draw_color_1 : back_color_1;
base[ j - 1] = (line & 0x1) ? draw_color_2 : back_color_2;
line = line >> 1;
}
base += screen_size_x;
}
}
LOCAL char pre = -1;
void fb_putchar(M6845_CON_DEV * pVgaConDv, char c)
{
if(defaultFbBase == 0)
return;
if (c == '\n') {
if(pre != '\r')
{
draw_char('\0', pVgaConDv->col * CHAR_WIDTH , pVgaConDv->row * CHAR_HEIGHT);
}
pVgaConDv->col = 0;
pVgaConDv->row++;
}
else if (c == '\r') {
draw_char('\0', pVgaConDv->col * CHAR_WIDTH , pVgaConDv->row * CHAR_HEIGHT);
pVgaConDv->col = 0;
}
else if (c== '\t') {
/*pVgaConDv->col += 8;*/
}
else if (c == '\b'){
draw_char('\0', pVgaConDv->col * CHAR_WIDTH , pVgaConDv->row * CHAR_HEIGHT);
pVgaConDv->col--;
draw_char('\0', pVgaConDv->col * CHAR_WIDTH , pVgaConDv->row * CHAR_HEIGHT);
}
else {
draw_char(c, pVgaConDv->col * CHAR_WIDTH , pVgaConDv->row * CHAR_HEIGHT);
pVgaConDv->col++;
}
if(pVgaConDv->col > (pVgaConDv->ncol-1)) {
pVgaConDv->col = 0;
pVgaConDv->row++;
}
#ifdef LITTLE_WINDOWS
if(pVgaConDv->row >= pVgaConDv->nrow) {
memcpy(defaultFbBase + (CHAR_HEIGHT * (num_rows - lw_rows)) * screen_size_x,
defaultFbBase + (CHAR_HEIGHT * (num_rows - lw_rows + 1)) * screen_size_x,
screen_size_x * (CHAR_HEIGHT * (lw_rows - 1)));
memset(pVgaConDv->nrow + (CHAR_HEIGHT * (num_rows - 1)) * screen_size_x, 0, screen_size_x * CHAR_HEIGHT);
pVgaConDv->row--;
}
#else
if(pVgaConDv->row >=pVgaConDv->nrow) {
memcpy((void*)defaultFbBase, (void*)(defaultFbBase + screen_size_x*CHAR_HEIGHT), screen_size_x * screen_size_y - screen_size_x*CHAR_HEIGHT);
pVgaConDv->row--;
memset((void*)defaultFbBase + (/*592*/pVgaConDv->nrow*16-16)*screen_size_x, 0, screen_size_x*CHAR_HEIGHT);
}
#endif
if(c != '\r')
{
draw_char(95/*219*/, pVgaConDv->col * CHAR_WIDTH, pVgaConDv->row * CHAR_HEIGHT);
}
pre = c;
}
/*******************************************************************************
*
* m6845WriteString - Write Character string to VGA Display
*
* This function does the write to the m6845 routine. This routine is provided as
* transmitter startup routine when tyDevInit is called.
*
* RETURNS: number of bytes written to the screen
*
* NOMANUAL
*/
LOCAL int m6845WriteString
(
M6845_CON_DEV * pDrvCtrl /* pointer to the console descriptor */
)
{
int dummy;
UCHAR ch;
FAST int nBytes;
FAST UCHAR atr;
TY_DEV * pTyDev = pDrvCtrl->pTyDev;
FAST RING_ID ringId = pTyDev->wrtBuf;
M6845_LOCK_TAKE(pDrvCtrl);
pTyDev->wrtState.busy = TRUE;
atr = pDrvCtrl->curAttrib;
nBytes = 0;
/* check if we need to output XON/XOFF for the read side */
if (pTyDev->wrtState.xoff || pTyDev->wrtState.flushingWrtBuf)
{
pTyDev->wrtState.busy = FALSE;
M6845_LOCK_GIVE(pDrvCtrl);
return nBytes;
}
while (RNG_ELEM_GET (ringId,&ch,dummy) != 0)
{
nBytes++;
fb_putchar(pDrvCtrl, ch);
}
pTyDev->wrtState.busy = FALSE;
M6845_LOCK_GIVE(pDrvCtrl);
if (rngFreeBytes (ringId) >= tyWrtThreshold)
{
semGive (&pTyDev->wrtSyncSem);
if (_func_selWakeupAll != NULL)
(* _func_selWakeupAll) (&pTyDev->selWakeupList, SELWRITE);
}
return nBytes;
}
/*******************************************************************************
*
* m6845ScreenRevMethod - reverse the screen (method)
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void m6845ScreenRevMethod
(
VXB_DEVICE_ID pDev,
int value
)
{
M6845_CON_DEV * pDrvCtrl = pDev->pDrvCtrl;
VGA_QUERY * pQuery = (VGA_QUERY *) value;
if (pQuery->unit != pDev->unitNumber)
return;
pDrvCtrl->rev = pDrvCtrl->rev ? FALSE : TRUE;
m6845ScreenRev (pDrvCtrl);
}
/*******************************************************************************
*
* m6845CurAttribMethod - get or set the color attributes (method)
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void m6845CurAttribMethod
(
VXB_DEVICE_ID pDev,
int value
)
{
M6845_CON_DEV * pDrvCtrl = pDev->pDrvCtrl;
VGA_QUERY * pQuery = (VGA_QUERY *) value;
if (pQuery->unit != pDev->unitNumber)
return;
if (pQuery->get)
*pQuery->pArg = pDrvCtrl->curAttrib;
else
pDrvCtrl->curAttrib = *pQuery->pArg;
}
/*******************************************************************************
*
* m6845CursorSetMethod - turn the cursor off or on (method)
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void m6845CursorSetMethod
(
VXB_DEVICE_ID pDev,
int value
)
{
M6845_CON_DEV * pDrvCtrl = pDev->pDrvCtrl;
VGA_QUERY * pQuery = (VGA_QUERY *) value;
if (pQuery->unit != pDev->unitNumber)
return;
if (*pQuery->pArg == 0)
m6845CursorOff (pDrvCtrl);
else
m6845CursorOn (pDrvCtrl);
}
/*******************************************************************************
*
* m6845CursorMoveMethod - move the cursor (method)
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void m6845CursorMoveMethod
(
VXB_DEVICE_ID pDev,
int value
)
{
M6845_CON_DEV * pDrvCtrl = pDev->pDrvCtrl;
VGA_QUERY * pQuery = (VGA_QUERY *) value;
int arg = *pQuery->pArg;
if (pQuery->unit != pDev->unitNumber)
return;
pDrvCtrl->row = (arg >> 8) & 0xff;
pDrvCtrl->col = arg & 0xff;
if (pDrvCtrl->row >= pDrvCtrl->nrow)
pDrvCtrl->row = pDrvCtrl->nrow - 1;
if (pDrvCtrl->col >= pDrvCtrl->ncol)
pDrvCtrl->col = pDrvCtrl->ncol - 1;
m6845CursorPos (pDrvCtrl, (UINT16) (pDrvCtrl->row * pDrvCtrl->ncol
+ pDrvCtrl->col));
}
#ifdef INCLUDE_ANSI_ESC_SEQUENCE
/*****************************************************************************
*
* m6845EscResponse - This function gives back a response to an escape sequence.
* The valid response Ids are
* 0 for cursor position, 1 for terminal status,
* 2 for terminal device attributes.
*
* RETURNS: N/A
*/
LOCAL void m6845EscResponse
(
M6845_CON_DEV * pDrvCtrl, /* pointer to the m6845 descriptor */
int responseId /* response Id */
)
{
tyIoctl (pDrvCtrl->pTyDev, FIORFLUSH, 0);
if ( responseId == 0)
{
sprintf (pDrvCtrl->escResp, "\033[%d;%dR", pDrvCtrl->row,
pDrvCtrl->col);
}
else if ( responseId == 1)
{
sprintf (pDrvCtrl->escResp, "\033[0n");
}
else if ( responseId == 2)
{
sprintf (pDrvCtrl->escResp, "\033[?1;0c");
}
else
{
pDrvCtrl->escResp[0] = '\0';
}
rngBufPut (pDrvCtrl->pTyDev->rdBuf, pDrvCtrl->escResp,
strlen (pDrvCtrl->escResp) );
semGive (&pDrvCtrl->pTyDev->rdSyncSem);
selWakeupAll (&pDrvCtrl->pTyDev->selWakeupList, SELREAD);
}
#endif /* INCLUDE_ANSI_ESC_SEQUENCE */