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

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