Merge branch 'master' of git.mutabah.net:acess2
[tpg/acess2.git] / KernelLand / Modules / Display / VIAVideo / main.c
1 /*
2  * Acess2 VIA Video Driver
3  * - By John Hodge
4  * 
5  * main.c
6  * - Driver core
7  *
8  * NOTE: Based off the UniChrome driver for X, http://unichrome.sourceforge.net/
9  */
10 #define DEBUG   0
11 #include <acess.h>
12 #include <fs_devfs.h>
13 #include <drv_pci.h>
14 #include <modules.h>
15 #include <api_drv_video.h>
16 #include "common.h"
17
18 #define VERSION VER2(0,1)
19
20 // === CONSTANTS ===
21 const struct sVGA_Timings
22 {
23          int    HFP, HSync, HDisplay, HBP;
24          int    VFP, VSync, VDisplay, VBP;
25 } csaTimings[] = {
26         {40, 128, 800, 88,    1, 4, 600, 23},   // SVGA @ 60Hz
27         {24, 136, 1024, 160,  3, 6, 768, 29},   // XGA @ 60Hz
28         {38, 112, 1280, 248,  1, 3, 1024, 38}   // 1280x1024 @ 60Hz
29 };
30
31 // === PROTOTYPES ===
32  int    VIAVideo_Initialise(char **Arguments);
33 void    VIAVideo_Cleanup(void);
34
35 size_t  VIAVideo_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer);
36  int    VIAVideo_IOCtl(tVFS_Node *Node, int ID, void *Data);
37
38 void    VIAVideo_int_SetMode(const struct sVGA_Timings *Timings, int Depth);
39 void    VIAVideo_int_ResetCRTC(int Index, BOOL Reset);
40
41 static void     _SRMask(int Reg, Uint8 Byte, Uint8 Mask);
42 static void     _CRMask(int Reg, Uint8 Byte, Uint8 Mask);
43
44 // === GLOBALS ===
45 MODULE_DEFINE(0, VERSION, VIAVideo, VIAVideo_Initialise, VIAVideo_Cleanup, NULL);
46 tVFS_NodeType   gVIAVideo_NodeType = {
47         .Write = VIAVideo_Write,
48         .IOCtl = VIAVideo_IOCtl
49         };
50 tDevFS_Driver   gVIAVideo_DriverStruct = {
51         NULL, "VIAVideo",
52         {.Type = &gVIAVideo_NodeType}
53         };
54  int    giVIAVideo_DriverID;
55 tVIAVideo_Dev   gVIAVideo_Info;
56
57 // === CODE ===
58 int VIAVideo_Initialise(char **Arguments)
59 {
60          int    count = 0;
61         
62         count += PCI_CountDevices(0x1106, 0x3108);
63         if(count == 0)  return MODULE_ERR_NOTNEEDED;
64         
65
66         for( int i = 0; (i = PCI_GetDevice(0x1106, 0x3108, i)) != -1; i ++ )
67         {
68                 // TODO: Support MMIO
69                 Log_Log("VIAVideo", "BAR0 = 0x%x", PCI_GetBAR(i, 0));
70                 Log_Log("VIAVideo", "BAR1 = 0x%x", PCI_GetBAR(i, 1));
71                 Log_Log("VIAVideo", "BAR2 = 0x%x", PCI_GetBAR(i, 2));
72                 Log_Log("VIAVideo", "BAR3 = 0x%x", PCI_GetBAR(i, 3));
73                 Log_Log("VIAVideo", "BAR4 = 0x%x", PCI_GetBAR(i, 4));
74                 Log_Log("VIAVideo", "BAR5 = 0x%x", PCI_GetBAR(i, 5));
75                 
76                 if( gVIAVideo_Info.FramebufferPhys )    continue ;
77                 
78                 gVIAVideo_Info.FramebufferPhys = PCI_GetBAR(i, 0);
79                 gVIAVideo_Info.MMIOPhys = PCI_GetBAR(i, 1);
80                 
81                 gVIAVideo_Info.Framebuffer = (void*)MM_MapHWPages(gVIAVideo_Info.FramebufferPhys, (1024*768*4)/PAGE_SIZE);
82                 // TODO: Map MMIO
83
84                 memset(gVIAVideo_Info.Framebuffer, 128, 1024*4*200);
85
86                 gVIAVideo_Info.BufInfo.Framebuffer = gVIAVideo_Info.Framebuffer;
87                 gVIAVideo_Info.BufInfo.Pitch = 1024*4;
88                 gVIAVideo_Info.BufInfo.Width = 1024;
89                 gVIAVideo_Info.BufInfo.Height = 768;
90                 gVIAVideo_Info.BufInfo.Depth = 32;      
91
92         }
93
94         VIAVideo_int_SetMode( &csaTimings[1], 32 );
95
96         // Install Device
97         giVIAVideo_DriverID = DevFS_AddDevice( &gVIAVideo_DriverStruct );
98         if(giVIAVideo_DriverID == -1)   return MODULE_ERR_MISC;
99
100         return MODULE_ERR_OK;
101 }
102
103 void VIAVideo_Cleanup(void)
104 {
105         return ;
106 }
107
108 size_t VIAVideo_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)
109 {
110         #if 0
111         return DrvUtil_Video_WriteLFB(&gVIAVideo_Info.BufInfo, Offset, Length, Buffer);
112         #endif
113         return 0;
114         #if 0
115         if( Offset >= gVIAVideo_Info.FBSize )
116                 return 0;
117         if( Length > gVIAVideo_Info.FBSize )
118                 Length = gVIAVideo_Info.FBSize;
119         if( Offset + Length > gVIAVideo_Info.FBSize )
120                 Length = gVIAVideo_Info.FBSize - Offset;
121         
122         memcpy( (Uint8*)gVIAVideo_Info.Framebuffer + Offset, Buffer, Length );
123         
124         return Length;
125         #endif
126 }
127
128 int VIAVideo_IOCtl(tVFS_Node *Node, int ID, void *Data)
129 {
130         return 0;
131 }
132
133 // --- Modeset!
134 void VIAVideo_int_SetMode(const struct sVGA_Timings *Timings, int Depth)
135 {
136          int    temp;
137         
138         // ??? Some Magic (Unichrome - VGACRMask(pVia, 0x17, 0x00, 0x80);)      
139
140         // Reset CRTC1
141         VIAVideo_int_ResetCRTC(0, TRUE);
142         
143         // -- Set framebuffer --
144         // Set colour depth bits
145         // VGASRMask(Crtc, 0x15, {0x00,0x14,0x0C}[Depth=8,16,24/32], 0x1C)
146         switch(Depth) {
147         case 8:  _SRMask(0x15, 0x00, 0x1C);     break;
148         case 16: _SRMask(0x15, 0x14, 0x1C);     break;
149         case 24: _SRMask(0x15, 0x0C, 0x1C);     break;
150         case 32: _SRMask(0x15, 0x0C, 0x1C);     break;
151         default:        return ;
152         }
153         // Set line length
154         {
155                  int    pitch = Timings->HDisplay * (Depth/8) / 8;
156                 // (Pitch/8) -> CR13 + CR35&0xE0
157                 _CRMask(0x13, pitch, 0xFF);
158                 _CRMask(0x35, (pitch>>8)<<5, 0xE0);
159         }
160         // - Set frame origin? (->FrameSet(Crtc, X, Y))
161         // DWORD Offset in memory
162         // Stored in CR0D + CR0C + CR34 + CR48&0x03
163
164         // -- Set CRTC Mode --
165         // NOTES:
166         // - VGA Represents the signal cycle as Display, Blank with Sync anywhere in that
167         // - Hence, I program the blanking as HBP, Sync, HFP (with the sync in the blanking area)
168
169         // Set mode
170         // VGAMiscMask(Crtc, (HSyncEnabled ? 0x40 : 0x00), 0x40);
171         // VGAMiscMask(Crtc, (VSyncEnabled ? 0x80 : 0x00), 0x80);
172         // HTotal:   CR00 + CR36&0x08 = /8-5
173         temp = (Timings->HFP + Timings->HSync + Timings->HDisplay + Timings->HBP) / 8 - 5;
174         _CRMask(0x00, temp, 0xFF);
175         _CRMask(0x36, (temp>>8)<<3, 0x08);
176         // HDisplay: CR01 = /8-1
177         temp = Timings->HDisplay / 8 - 1;
178         _CRMask(0x01, temp, 0xFF);
179         // HBlank Start: CR02 = /8-1
180         temp = (Timings->HDisplay) / 8 - 1;
181         _CRMask(0x02, temp, 0xFF);
182         // HBlank End:   CR03&0x1F + CR05&0x80 + CR33&0x20 = /8-1
183         temp = (Timings->HBP + Timings->HSync + Timings->HFP) / 8 - 1;
184         if( temp >> 7 ) Log_Error("VIA", "HBlank End doesn't fit (%i not 7 bits)", temp);
185         _CRMask(0x03, temp, 0x1F);
186         _CRMask(0x05, (temp>>5)<<7, 0x80);
187         _CRMask(0x33, (temp>>6)<<5, 0x20);
188         // HSync Start: CR04 + CR33&0x10 = /8
189         temp = (Timings->HDisplay + Timings->HBP) / 8;
190         _CRMask(0x04, temp, 0xFF);
191         _CRMask(0x33, (temp>>8)<<4, 0x10);
192         // HSync End:   CR05&0x1F = /8
193         temp = (Timings->HSync) / 8;
194         _CRMask(0x05, temp, 0x1F);
195         // VTotal:   CR06 + CR07&0x01 + CR07&0x20 + CR35&0x01 = -2
196         temp = (Timings->VFP + Timings->VBP + Timings->VSync + Timings->VDisplay) - 2;
197         _CRMask(0x06, temp, 0xFF);
198         _CRMask(0x07, (temp>>8)<<0, 0x01);
199         _CRMask(0x07, (temp>>9)<<5, 0x20);
200         _CRMask(0x35, (temp>>10)<<0, 0x01);
201         // VDisplay: CR12 + CR07&0x02 + CR07&0x40 + CR35&0x04 = -1
202         temp = (Timings->VDisplay) - 1;
203         _CRMask(0x12, temp, 0xFF);
204         _CRMask(0x07, (temp>>8)<<1, 0x02);
205         _CRMask(0x07, (temp>>9)<<6, 0x40);
206         _CRMask(0x07, (temp>>10)<<2, 0x04);
207         // 0:  CR0C + CR0D + CD34 + CR48&0x03 ("Primary starting address")
208         temp = 0;
209         _CRMask(0x0C, temp, 0xFF);
210         _CRMask(0x0D, (temp>>8), 0xFF);
211         _CRMask(0x34, (temp>>16), 0xFF);
212         _CRMask(0x48, (temp>>24), 0x03);
213         // VSyncStart: CR10 + CR07&0x04 + CR07&0x80 + CR35&0x02
214         temp = (Timings->VDisplay + Timings->HBP);
215         _CRMask(0x10, temp, 0xFF);
216         _CRMask(0x07, (temp>>8)<<2, 0x04);
217         _CRMask(0x07, (temp>>9)<<7, 0x80);
218         _CRMask(0x35, (temp>>10)<<1, 0x02);
219         // VSyncEnd:   CR11&0x0F
220         temp = (Timings->VSync);
221         _CRMask(0x11, temp, 0x0F);
222         // 0x3FFF: CR18 + CR07&0x10 + CR09&0x40 + CR33&0x06 + CR35&0x10 ("line compare")
223         temp = 0x3FFF;
224         _CRMask(0x18, temp, 0xFF);
225         _CRMask(0x07, (temp>>8)<<4, 0x10);
226         _CRMask(0x09, (temp>>9)<<6, 0x40);
227         _CRMask(0x33, (temp>>10)<<1, 0x06);
228         _CRMask(0x35, (temp>>12)<<4, 0x10);
229         // 0:  CR09&0x1F ("Maximum scanline")
230         temp = 0;
231         _CRMask(0x09, temp, 0x1F);
232         // 0: Cursor location
233         temp = 0;
234         _CRMask(0x14, temp, 0xFF);
235         // VBlankStart: CR15 + CR07&0x08 + CR09&0x20 + CR35&0x08 = -1
236         temp = (Timings->VDisplay) - 1;
237         _CRMask(0x15, temp, 0xFF);
238         _CRMask(0x07, (temp>>8)<<3, 0x08);
239         _CRMask(0x09, (temp>>9)<<5, 0x20);
240         _CRMask(0x35, (temp>>10)<<3, 0x08);
241         // VBlankEnd:   CR16 = -1
242         temp = (Timings->VBP + Timings->VSync + Timings->VFP) - 1;
243         _CRMask(0x16, temp, 0xFF);
244         // 0:  CR08 (Preset Row Scan Register)
245         _CRMask(0x08, 0, 0xFF);
246         // 0:  CR32 (???)
247         _CRMask(0x32, 0, 0xFF);
248         // 0:  CR33&0xC8
249         _CRMask(0x33, 0, 0xC8);
250
251         // Set scaling?
252
253         // Disable CRTC reset
254         VIAVideo_int_ResetCRTC(0, FALSE);
255 }
256
257 void VIAVideo_int_ResetCRTC(int Index, BOOL Reset)
258 {
259         // VGASRMask(Crtc, 0x00, (Reset ? 0x00 : 0x02), 0x02);
260         _SRMask(0x00, (Reset ? 0x00 : 0x02), 0x02);
261 }
262
263 void _SRMask(int Reg, Uint8 Byte, Uint8 Mask)
264 {
265         Uint8   cv = 0;
266         outb(0x3C4, Reg);
267         if(Mask != 0xFF)        cv = inb(0x3C5) & ~Mask;
268         cv |= Byte & Mask;
269         outb(0x3C5, cv);
270 }
271
272 void _CRMask(int Reg, Uint8 Byte, Uint8 Mask)
273 {
274         Uint8   cv = 0;
275         outb(0x3D4, Reg);
276         if(Mask != 0xFF)        cv = inb(0x3D5) & ~Mask;
277         cv |= Byte & Mask;
278         outb(0x3D5, cv);
279 }
280

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