2 * Acess2 VGA Controller Driver
7 #include <tpl_drv_video.h>
15 int VGA_Install(char **Arguments);
16 Uint64 VGA_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, 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(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 tDevFS_Driver gVGA_DevInfo = {
31 .Size = VGA_WIDTH*VGA_HEIGHT*sizeof(tVT_Char),
37 Uint16 *gVGA_Framebuffer = (void*)( KERNEL_BASE|0xB8000 );
38 int giVGA_BufferFormat = VIDEO_BUFFMT_TEXT;
39 tDrvUtil_Video_2DHandlers gVGA_2DFunctions = {
47 * \fn int VGA_Install(char **Arguments)
49 int VGA_Install(char **Arguments)
53 // Enable Bright Backgrounds
54 inb(0x3DA); // Reset flipflop
55 outb(0x3C0, 0x30); // Index 0x10, PAS
57 byte &= ~8; // Disable Blink
58 outb(0x3C0, byte); // Write value
62 DevFS_AddDevice( &gVGA_DevInfo );
68 * \fn Uint64 VGA_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
69 * \brief Writes a string of bytes to the VGA controller
71 Uint64 VGA_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
73 if( giVGA_BufferFormat == VIDEO_BUFFMT_TEXT )
75 int num = Length / sizeof(tVT_Char);
76 int ofs = Offset / sizeof(tVT_Char);
78 tVT_Char *chars = Buffer;
81 //ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
83 for( ; num--; i ++, ofs ++)
85 word = VGA_int_GetWord( &chars[i] );
86 gVGA_Framebuffer[ ofs ] = word;
92 else if( giVGA_BufferFormat == VIDEO_BUFFMT_2DSTREAM )
94 return DrvUtil_Video_2DStream(NULL, Buffer, Length, &gVGA_2DFunctions, sizeof(gVGA_2DFunctions));
103 * \fn int VGA_IOCtl(tVFS_Node *Node, int Id, void *Data)
104 * \brief IO Control Call
106 int VGA_IOCtl(tVFS_Node *Node, int ID, void *Data)
111 case DRV_IOCTL_TYPE: return DRV_TYPE_VIDEO;
112 case DRV_IOCTL_IDENT: memcpy(Data, "VGA\0", 4); return 1;
113 case DRV_IOCTL_VERSION: *(int*)Data = 50; return 1;
114 case DRV_IOCTL_LOOKUP: return 0;
116 case VIDEO_IOCTL_GETSETMODE: return 0; // Mode 0 only
117 case VIDEO_IOCTL_FINDMODE:
118 if( !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)) ) return -1;
119 ((tVideo_IOCtl_Mode*)Data)->id = 0; // Text Only!
120 case VIDEO_IOCTL_MODEINFO:
121 if( !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)) ) return -1;
122 if( ((tVideo_IOCtl_Mode*)Data)->id != 0) return 0;
123 ((tVideo_IOCtl_Mode*)Data)->width = VGA_WIDTH*giVT_CharWidth;
124 ((tVideo_IOCtl_Mode*)Data)->height = VGA_HEIGHT*giVT_CharHeight;
125 ((tVideo_IOCtl_Mode*)Data)->bpp = 4;
128 case VIDEO_IOCTL_SETBUFFORMAT:
129 if( !CheckMem(Data, sizeof(int)) ) return -1;
130 switch( *(int*)Data )
132 case VIDEO_BUFFMT_TEXT:
133 case VIDEO_BUFFMT_2DSTREAM:
134 rv = giVGA_BufferFormat;
135 giVGA_BufferFormat = *(int*)Data;
136 // Log_Debug("VGA", "Buffer format set to %i", giVGA_BufferFormat);
143 case VIDEO_IOCTL_SETCURSOR:
144 VGA_int_SetCursor( ((tVideo_IOCtl_Pos*)Data)->x, ((tVideo_IOCtl_Pos*)Data)->y );
151 * \fn Uint8 VGA_int_GetColourNibble(Uint16 col)
152 * \brief Converts a 12-bit colour into a VGA 4-bit colour
154 Uint8 VGA_int_GetColourNibble(Uint16 col)
160 col = ((col>>2)&3) | ((col>>4)&0xC) | ((col>>6)&0x30);
161 bright = ( (col & 2 ? 1 : 0) + (col & 8 ? 1 : 0) + (col & 32 ? 1 : 0) ) / 2;
166 case 0x00: ret = 0x0; break;
168 case 0x15: ret = 0x8; break;
171 case 0x02: ret = 0x1; break;
172 case 0x03: ret = 0x9; break;
175 case 0x08: ret = 0x2; break;
176 case 0x0C: ret = 0xA; break;
179 case 0x20: ret = 0x4; break;
180 case 0x30: ret = 0xC; break;
182 case 0x2A: ret = 0x7; break;
184 case 0x3F: ret = 0xF; break;
187 ret |= (col & 0x03 ? 1 : 0);
188 ret |= (col & 0x0C ? 2 : 0);
189 ret |= (col & 0x30 ? 4 : 0);
190 ret |= (bright ? 8 : 0);
197 * \fn Uint16 VGA_int_GetWord(tVT_Char *Char)
198 * \brief Convers a character structure to a VGA character word
200 Uint16 VGA_int_GetWord(tVT_Char *Char)
211 default: ret = 0; break;
215 col = VGA_int_GetColourNibble(Char->BGCol);
218 col = VGA_int_GetColourNibble(Char->FGCol);
225 * \fn void VGA_int_SetCursor(Sint16 x, Sint16 y)
226 * \brief Updates the cursor position
228 void VGA_int_SetCursor(Sint16 x, Sint16 y)
230 int pos = x+y*VGA_WIDTH;
231 if(x == -1 || y == -1)
234 outb(0x3D5, pos >> 8);
239 void VGA_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)
246 Y /= giVT_CharHeight;
247 H /= giVT_CharHeight;
250 ch.BGCol = (Colour & 0x0F0000) >> (16-8);
251 ch.BGCol |= (Colour & 0x000F00) >> (8-4);
252 ch.BGCol |= (Colour & 0x00000F);
253 word = VGA_int_GetWord(&ch);
255 Log("Fill (%i,%i) %ix%i with 0x%x", X, Y, W, H, word);
257 if( X > VGA_WIDTH || Y > VGA_HEIGHT ) return ;
258 if( X + W > VGA_WIDTH ) W = VGA_WIDTH - X;
259 if( Y + H > VGA_HEIGHT ) H = VGA_HEIGHT - Y;
261 buf = gVGA_Framebuffer + Y*VGA_WIDTH + X;
266 for( i = 0; i < W; i ++ )
268 buf += VGA_WIDTH - W;
272 void VGA_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)
276 DstX /= giVT_CharWidth;
277 SrcX /= giVT_CharWidth;
280 DstY /= giVT_CharHeight;
281 SrcY /= giVT_CharHeight;
282 H /= giVT_CharHeight;
284 // Log("(%i,%i) from (%i,%i) %ix%i", DstX, DstY, SrcX, SrcY, W, H);
286 if( SrcX > VGA_WIDTH || SrcY > VGA_HEIGHT ) return ;
287 if( SrcX + W > VGA_WIDTH ) W = VGA_WIDTH - SrcX;
288 if( SrcY + H > VGA_HEIGHT ) H = VGA_HEIGHT - SrcY;
289 if( DstX > VGA_WIDTH || DstY > VGA_HEIGHT ) return ;
290 if( DstX + W > VGA_WIDTH ) W = VGA_WIDTH - DstX;
291 if( DstY + H > VGA_HEIGHT ) H = VGA_HEIGHT - DstY;
294 src = gVGA_Framebuffer + SrcY*VGA_WIDTH + SrcX;
295 dst = gVGA_Framebuffer + DstY*VGA_WIDTH + DstX;
301 memcpy(dst, src, W*2);
314 for( i = W; i --; ) *--dst = *--src;