2 * Acess2 VGA Controller Driver
7 #include <api_drv_video.h>
15 int VGA_Install(char **Arguments);
16 size_t VGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
17 int VGA_IOCtl(tVFS_Node *Node, int Id, void *Data);
18 Uint8 VGA_int_GetColourNibble(Uint16 col);
19 Uint16 VGA_int_GetWord(const tVT_Char *Char);
20 void VGA_int_SetCursor(Sint16 x, Sint16 y);
21 // --- 2D Acceleration Functions --
22 void VGA_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
23 void VGA_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);
26 MODULE_DEFINE(0, 0x000A, x86_VGAText, VGA_Install, NULL, NULL);
27 tVFS_NodeType gVGA_NodeType = {
32 tDevFS_Driver gVGA_DevInfo = {
36 .Size = VGA_WIDTH*VGA_HEIGHT*sizeof(tVT_Char),
37 .Type = &gVGA_NodeType
40 Uint16 *gVGA_Framebuffer = (void*)( KERNEL_BASE|0xB8000 );
41 int giVGA_BufferFormat = VIDEO_BUFFMT_TEXT;
42 tDrvUtil_Video_2DHandlers gVGA_2DFunctions = {
50 * \fn int VGA_Install(char **Arguments)
52 int VGA_Install(char **Arguments)
56 // Enable Bright Backgrounds
57 inb(0x3DA); // Reset flipflop
58 outb(0x3C0, 0x30); // Index 0x10, PAS
60 byte &= ~8; // Disable Blink
61 outb(0x3C0, byte); // Write value
65 DevFS_AddDevice( &gVGA_DevInfo );
71 * \brief Writes a string of bytes to the VGA controller
73 size_t VGA_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
75 if( giVGA_BufferFormat == VIDEO_BUFFMT_TEXT )
77 int num = Length / sizeof(tVT_Char);
78 int ofs = Offset / sizeof(tVT_Char);
80 const tVT_Char *chars = Buffer;
83 //ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
85 for( ; num--; i ++, ofs ++)
87 word = VGA_int_GetWord( &chars[i] );
88 gVGA_Framebuffer[ ofs ] = word;
94 else if( giVGA_BufferFormat == VIDEO_BUFFMT_2DSTREAM )
96 return DrvUtil_Video_2DStream(NULL, Buffer, Length, &gVGA_2DFunctions, sizeof(gVGA_2DFunctions));
105 * \fn int VGA_IOCtl(tVFS_Node *Node, int Id, void *Data)
106 * \brief IO Control Call
108 int VGA_IOCtl(tVFS_Node *Node, int ID, void *Data)
113 case DRV_IOCTL_TYPE: return DRV_TYPE_VIDEO;
114 case DRV_IOCTL_IDENT: memcpy(Data, "VGA\0", 4); return 1;
115 case DRV_IOCTL_VERSION: *(int*)Data = 50; return 1;
116 case DRV_IOCTL_LOOKUP: return 0;
118 case VIDEO_IOCTL_GETSETMODE: return 0; // Mode 0 only
119 case VIDEO_IOCTL_FINDMODE:
120 if( !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)) ) return -1;
121 ((tVideo_IOCtl_Mode*)Data)->id = 0; // Text Only!
122 case VIDEO_IOCTL_MODEINFO:
123 if( !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)) ) return -1;
124 if( ((tVideo_IOCtl_Mode*)Data)->id != 0) return 0;
125 ((tVideo_IOCtl_Mode*)Data)->width = VGA_WIDTH*giVT_CharWidth;
126 ((tVideo_IOCtl_Mode*)Data)->height = VGA_HEIGHT*giVT_CharHeight;
127 ((tVideo_IOCtl_Mode*)Data)->bpp = 4;
130 case VIDEO_IOCTL_SETBUFFORMAT:
131 if( !CheckMem(Data, sizeof(int)) ) return -1;
132 switch( *(int*)Data )
134 case VIDEO_BUFFMT_TEXT:
135 case VIDEO_BUFFMT_2DSTREAM:
136 rv = giVGA_BufferFormat;
137 giVGA_BufferFormat = *(int*)Data;
138 // Log_Debug("VGA", "Buffer format set to %i", giVGA_BufferFormat);
145 case VIDEO_IOCTL_SETCURSOR:
146 VGA_int_SetCursor( ((tVideo_IOCtl_Pos*)Data)->x, ((tVideo_IOCtl_Pos*)Data)->y );
153 * \fn Uint8 VGA_int_GetColourNibble(Uint16 col)
154 * \brief Converts a 12-bit colour into a VGA 4-bit colour
156 Uint8 VGA_int_GetColourNibble(Uint16 col)
162 col = ((col>>2)&3) | ((col>>4)&0xC) | ((col>>6)&0x30);
163 bright = ( (col & 2 ? 1 : 0) + (col & 8 ? 1 : 0) + (col & 32 ? 1 : 0) ) / 2;
168 case 0x00: ret = 0x0; break;
170 case 0x15: ret = 0x8; break;
173 case 0x02: ret = 0x1; break;
174 case 0x03: ret = 0x9; break;
177 case 0x08: ret = 0x2; break;
178 case 0x0C: ret = 0xA; break;
181 case 0x20: ret = 0x4; break;
182 case 0x30: ret = 0xC; break;
184 case 0x2A: ret = 0x7; break;
186 case 0x3F: ret = 0xF; break;
189 ret |= (col & 0x03 ? 1 : 0);
190 ret |= (col & 0x0C ? 2 : 0);
191 ret |= (col & 0x30 ? 4 : 0);
192 ret |= (bright ? 8 : 0);
199 * \fn Uint16 VGA_int_GetWord(tVT_Char *Char)
200 * \brief Convers a character structure to a VGA character word
202 Uint16 VGA_int_GetWord(const tVT_Char *Char)
213 default: ret = 0; break;
217 col = VGA_int_GetColourNibble(Char->BGCol);
220 col = VGA_int_GetColourNibble(Char->FGCol);
227 * \fn void VGA_int_SetCursor(Sint16 x, Sint16 y)
228 * \brief Updates the cursor position
230 void VGA_int_SetCursor(Sint16 x, Sint16 y)
232 int pos = x+y*VGA_WIDTH;
233 if(x == -1 || y == -1)
236 outb(0x3D5, pos >> 8);
241 void VGA_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)
248 Y /= giVT_CharHeight;
249 H /= giVT_CharHeight;
252 ch.BGCol = (Colour & 0x0F0000) >> (16-8);
253 ch.BGCol |= (Colour & 0x000F00) >> (8-4);
254 ch.BGCol |= (Colour & 0x00000F);
255 word = VGA_int_GetWord(&ch);
257 Log("Fill (%i,%i) %ix%i with 0x%x", X, Y, W, H, word);
259 if( X > VGA_WIDTH || Y > VGA_HEIGHT ) return ;
260 if( X + W > VGA_WIDTH ) W = VGA_WIDTH - X;
261 if( Y + H > VGA_HEIGHT ) H = VGA_HEIGHT - Y;
263 buf = gVGA_Framebuffer + Y*VGA_WIDTH + X;
268 for( i = 0; i < W; i ++ )
270 buf += VGA_WIDTH - W;
274 void VGA_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)
278 DstX /= giVT_CharWidth;
279 SrcX /= giVT_CharWidth;
282 DstY /= giVT_CharHeight;
283 SrcY /= giVT_CharHeight;
284 H /= giVT_CharHeight;
286 // Log("(%i,%i) from (%i,%i) %ix%i", DstX, DstY, SrcX, SrcY, W, H);
288 if( SrcX > VGA_WIDTH || SrcY > VGA_HEIGHT ) return ;
289 if( SrcX + W > VGA_WIDTH ) W = VGA_WIDTH - SrcX;
290 if( SrcY + H > VGA_HEIGHT ) H = VGA_HEIGHT - SrcY;
291 if( DstX > VGA_WIDTH || DstY > VGA_HEIGHT ) return ;
292 if( DstX + W > VGA_WIDTH ) W = VGA_WIDTH - DstX;
293 if( DstY + H > VGA_HEIGHT ) H = VGA_HEIGHT - DstY;
296 src = gVGA_Framebuffer + SrcY*VGA_WIDTH + SrcX;
297 dst = gVGA_Framebuffer + DstY*VGA_WIDTH + DstX;
303 memcpy(dst, src, W*2);
316 for( i = W; i --; ) *--dst = *--src;