54360697dd6a5117bdbc621190d0500a30012c59
[tpg/acess2.git] / Kernel / drv / vga.c
1 /*
2  * Acess2 VGA Controller Driver
3  */
4 #define DEBUG   0
5 #include <acess.h>
6 #include <fs_devfs.h>
7 #include <tpl_drv_video.h>
8 #include <modules.h>
9
10 // === CONSTANTS ===
11 #define VGA_WIDTH       80
12 #define VGA_HEIGHT      25
13
14 // === PROTOTYPES ===
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
22 // === GLOBALS ===
23 MODULE_DEFINE(0, 0x000A, VGA, VGA_Install, NULL, NULL);
24 tDevFS_Driver   gVGA_DevInfo = {
25         NULL, "VGA",
26         {
27         .NumACLs = 0,
28         .Size = VGA_WIDTH*VGA_HEIGHT*sizeof(tVT_Char),
29         //.Read = VGA_Read,
30         .Write = VGA_Write,
31         .IOCtl = VGA_IOCtl
32         }
33 };
34 Uint16  *gVGA_Framebuffer = (void*)( KERNEL_BASE|0xB8000 );
35
36 // === CODE ===
37 /**
38  * \fn int VGA_Install(char **Arguments)
39  */
40 int VGA_Install(char **Arguments)
41 {
42         Uint8   byte;
43         
44         // Enable Bright Backgrounds
45         inb(0x3DA);     // Reset flipflop
46         outb(0x3C0, 0x30);      // Index 0x10, PAS
47         byte = inb(0x3C1);
48         byte &= ~8;     // Disable Blink
49         outb(0x3C0, byte);      // Write value
50         
51         
52         // Install DevFS
53         DevFS_AddDevice( &gVGA_DevInfo );
54         
55         return MODULE_ERR_OK;
56 }
57
58 /**
59  * \fn Uint64 VGA_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
60  * \brief Writes a string of bytes to the VGA controller
61  */
62 Uint64 VGA_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
63 {
64          int    num = Length / sizeof(tVT_Char);
65          int    ofs = Offset / sizeof(tVT_Char);
66          int    i = 0;
67         tVT_Char        *chars = Buffer;
68         Uint16  word;
69         
70         //ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
71         
72         for( ; num--; i ++, ofs ++)
73         {
74                 word = VGA_int_GetWord( &chars[i] );
75                 gVGA_Framebuffer[ ofs ] = word;
76         }
77         
78         //LEAVE('X', Length);
79         return Length;
80 }
81
82 /**
83  * \fn int VGA_IOCtl(tVFS_Node *Node, int Id, void *Data)
84  * \brief IO Control Call
85  */
86 int VGA_IOCtl(tVFS_Node *Node, int Id, void *Data)
87 {
88         switch(Id)
89         {
90         case DRV_IOCTL_TYPE:    return DRV_TYPE_VIDEO;
91         case DRV_IOCTL_IDENT:   memcpy(Data, "VGA\0", 4);       return 1;
92         case DRV_IOCTL_VERSION: *(int*)Data = 50;       return 1;
93         case DRV_IOCTL_LOOKUP:  return 0;
94         
95         case VIDEO_IOCTL_GETSETMODE:    return 0;       // Mode 0 only
96         case VIDEO_IOCTL_FINDMODE:      return 0;       // Text Only!
97         case VIDEO_IOCTL_MODEINFO:
98                 if( ((tVideo_IOCtl_Mode*)Data)->id != 0)        return 0;
99                 ((tVideo_IOCtl_Mode*)Data)->width = VGA_WIDTH;
100                 ((tVideo_IOCtl_Mode*)Data)->height = VGA_HEIGHT;
101                 ((tVideo_IOCtl_Mode*)Data)->bpp = 4;
102                 return 1;
103         
104         case VIDEO_IOCTL_SETBUFFORMAT:
105                 return 0;
106         
107         case VIDEO_IOCTL_SETCURSOR:
108                 VGA_int_SetCursor( ((tVideo_IOCtl_Pos*)Data)->x, ((tVideo_IOCtl_Pos*)Data)->y );
109                 return 1;
110         }
111         return 0;
112 }
113
114 /**
115  * \fn Uint8 VGA_int_GetColourNibble(Uint16 col)
116  * \brief Converts a 12-bit colour into a VGA 4-bit colour
117  */
118 Uint8 VGA_int_GetColourNibble(Uint16 col)
119 {
120         Uint8   ret = 0;
121          int    bright = 0;
122         
123         col = col & 0xCCC;
124         col = ((col>>2)&3) | ((col>>4)&0xC) | ((col>>6)&0x30);
125         bright = ( (col & 2 ? 1 : 0) + (col & 8 ? 1 : 0) + (col & 32 ? 1 : 0) ) / 2;
126         
127         switch(col)
128         {
129         //      Black
130         case 0x00:      ret = 0x0;      break;
131         // Dark Grey
132         case 0x15:      ret = 0x8;      break;
133         // Blues
134         case 0x01:
135         case 0x02:      ret = 0x1;      break;
136         case 0x03:      ret = 0x9;      break;
137         // Green
138         case 0x04:
139         case 0x08:      ret = 0x2;      break;
140         case 0x0C:      ret = 0xA;      break;
141         // Reds
142         case 0x10:
143         case 0x20:      ret = 0x4;      break;
144         case 0x30:      ret = 0xC;      break;
145         // Light Grey
146         case 0x2A:      ret = 0x7;      break;
147         // White
148         case 0x3F:      ret = 0xF;      break;
149         
150         default:
151                 ret |= (col & 0x03 ? 1 : 0);
152                 ret |= (col & 0x0C ? 2 : 0);
153                 ret |= (col & 0x30 ? 4 : 0);
154                 ret |= (bright ? 8 : 0);
155                 break;
156         }
157         return ret;
158 }
159
160 /**
161  * \fn Uint16 VGA_int_GetWord(tVT_Char *Char)
162  * \brief Convers a character structure to a VGA character word
163  */
164 Uint16 VGA_int_GetWord(tVT_Char *Char)
165 {
166         Uint16  ret;
167         Uint16  col;
168         
169         // Get Character
170         if(Char->Ch < 128)
171                 ret = Char->Ch;
172         else {
173                 switch(Char->Ch)
174                 {
175                 default:        ret = 0;        break;
176                 }
177         }
178         
179         col = VGA_int_GetColourNibble(Char->BGCol);
180         ret |= col << 12;
181         
182         col = VGA_int_GetColourNibble(Char->FGCol);
183         ret |= col << 8;
184         
185         return ret;
186 }
187
188 /**
189  * \fn void VGA_int_SetCursor(Sint16 x, Sint16 y)
190  * \brief Updates the cursor position
191  */
192 void VGA_int_SetCursor(Sint16 x, Sint16 y)
193 {
194          int    pos = x+y*VGA_WIDTH;
195         if(x == -1 || y == -1)
196                 pos = -1;
197     outb(0x3D4, 14);
198     outb(0x3D5, pos >> 8);
199     outb(0x3D4, 15);
200     outb(0x3D5, pos);
201 }

UCC git Repository :: git.ucc.asn.au