fdcb67aaf0b6de0cd340a8d8f88946232d0f80a7
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / xboxvideo.c
1 /* $Id$
2 *
3 * FreeLoader
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * Note: much of this code was based on knowledge and/or code developed
20 * by the Xbox Linux group: http://www.xbox-linux.org
21 */
22
23 #include "freeldr.h"
24 #include "debug.h"
25 #include "rtl.h"
26 #include "machine.h"
27 #include "machxbox.h"
28 #include "portio.h"
29
30 #define I2C_IO_BASE 0xc000
31
32 static PVOID FrameBuffer;
33 static ULONG ScreenWidth;
34 static ULONG ScreenHeight;
35 static ULONG BytesPerPixel;
36 static ULONG Delta;
37
38 #define CHAR_WIDTH 8
39 #define CHAR_HEIGHT 16
40
41 #define TOP_BOTTOM_LINES 0
42
43 #define FB_SIZE_MB 4
44
45 #define MAKE_COLOR(Red, Green, Blue) (0xff000000 | (((Red) & 0xff) << 16) | (((Green) & 0xff) << 8) | ((Blue) & 0xff))
46
47 static VOID
48 XboxVideoOutputChar(UCHAR Char, unsigned X, unsigned Y, ULONG FgColor, ULONG BgColor)
49 {
50 PUCHAR FontPtr;
51 PULONG Pixel;
52 UCHAR Mask;
53 unsigned Line;
54 unsigned Col;
55
56 FontPtr = XboxFont8x16 + Char * 16;
57 Pixel = (PULONG) ((char *) FrameBuffer + (Y * CHAR_HEIGHT + TOP_BOTTOM_LINES) * Delta
58 + X * CHAR_WIDTH * BytesPerPixel);
59 for (Line = 0; Line < CHAR_HEIGHT; Line++)
60 {
61 Mask = 0x80;
62 for (Col = 0; Col < CHAR_WIDTH; Col++)
63 {
64 Pixel[Col] = (0 != (FontPtr[Line] & Mask) ? FgColor : BgColor);
65 Mask = Mask >> 1;
66 }
67 Pixel = (PULONG) ((char *) Pixel + Delta);
68 }
69 }
70
71 static ULONG
72 XboxVideoAttrToSingleColor(UCHAR Attr)
73 {
74 UCHAR Intensity;
75
76 Intensity = (0 == (Attr & 0x08) ? 127 : 255);
77
78 return 0xff000000 |
79 (0 == (Attr & 0x04) ? 0 : (Intensity << 16)) |
80 (0 == (Attr & 0x02) ? 0 : (Intensity << 8)) |
81 (0 == (Attr & 0x01) ? 0 : Intensity);
82 }
83
84 static VOID
85 XboxVideoAttrToColors(UCHAR Attr, ULONG *FgColor, ULONG *BgColor)
86 {
87 *FgColor = XboxVideoAttrToSingleColor(Attr & 0xf);
88 *BgColor = XboxVideoAttrToSingleColor((Attr >> 4) & 0xf);
89 }
90
91 static VOID
92 XboxVideoClearScreenColor(ULONG Color, BOOL FullScreen)
93 {
94 ULONG Line, Col;
95 PULONG p;
96
97 for (Line = 0; Line < ScreenHeight - (FullScreen ? 0 : 2 * TOP_BOTTOM_LINES); Line++)
98 {
99 p = (PULONG) ((char *) FrameBuffer + (Line + (FullScreen ? 0 : TOP_BOTTOM_LINES)) * Delta);
100 for (Col = 0; Col < ScreenWidth; Col++)
101 {
102 *p++ = Color;
103 }
104 }
105 }
106
107 VOID
108 XboxVideoClearScreen(UCHAR Attr)
109 {
110 ULONG FgColor, BgColor;
111
112 XboxVideoAttrToColors(Attr, &FgColor, &BgColor);
113
114 XboxVideoClearScreenColor(BgColor, FALSE);
115 }
116
117 VOID
118 XboxVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
119 {
120 ULONG FgColor, BgColor;
121
122 XboxVideoAttrToColors(Attr, &FgColor, &BgColor);
123
124 XboxVideoOutputChar(Ch, X, Y, FgColor, BgColor);
125 }
126
127 static BOOL
128 ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, ULONG *Data_to_smbus)
129 {
130 int nRetriesToLive=50;
131
132 while (0 != (READ_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0)) & 0x0800))
133 {
134 ; /* Franz's spin while bus busy with any master traffic */
135 }
136
137 while (0 != nRetriesToLive--)
138 {
139 UCHAR b;
140 int temp;
141
142 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 4), (Address << 1) | 1);
143 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 8), bRegister);
144
145 temp = READ_PORT_USHORT((USHORT *) (I2C_IO_BASE + 0));
146 WRITE_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */
147
148 switch (Size)
149 {
150 case 4:
151 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0d); /* DWORD modus ? */
152 break;
153 case 2:
154 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0b); /* WORD modus */
155 break;
156 default:
157 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0a); // BYTE
158 break;
159 }
160
161 b = 0;
162
163 while (0 == (b & 0x36))
164 {
165 b = READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 0));
166 }
167
168 if (0 != (b & 0x24))
169 {
170 /* printf("I2CTransmitByteGetReturn error %x\n", b); */
171 }
172
173 if(0 == (b & 0x10))
174 {
175 /* printf("I2CTransmitByteGetReturn no complete, retry\n"); */
176 }
177 else
178 {
179 switch (Size)
180 {
181 case 4:
182 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 6));
183 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
184 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
185 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
186 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
187 break;
188 case 2:
189 *Data_to_smbus = READ_PORT_USHORT((USHORT *) (I2C_IO_BASE + 6));
190 break;
191 default:
192 *Data_to_smbus = READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 6));
193 break;
194 }
195
196
197 return TRUE;
198 }
199 }
200
201 return FALSE;
202 }
203
204
205 static BOOL
206 I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat, UCHAR bDataToWrite, ULONG *Return)
207 {
208 return ReadfromSMBus(bPicAddressI2cFormat, bDataToWrite, 1, Return);
209 }
210
211
212 VOID
213 XboxVideoInit(VOID)
214 {
215 ULONG AvMode;
216
217 FrameBuffer = (PVOID)((ULONG) XboxMemReserveMemory(FB_SIZE_MB) | 0xf0000000);
218
219 if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode))
220 {
221 if (1 == AvMode) /* HDTV */
222 {
223 ScreenWidth = 720;
224 }
225 else
226 {
227 /* FIXME Other possible values of AvMode:
228 * 0 - AV_SCART_RGB
229 * 2 - AV_VGA_SOG
230 * 4 - AV_SVIDEO
231 * 6 - AV_COMPOSITE
232 * 7 - AV_VGA
233 * other AV_COMPOSITE
234 */
235 ScreenWidth = 640;
236 }
237 }
238 else
239 {
240 ScreenWidth = 640;
241 }
242
243 ScreenHeight = 480;
244 BytesPerPixel = 4;
245 Delta = (ScreenWidth * BytesPerPixel + 3) & ~ 0x3;
246
247 XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
248
249 /* Tell the nVidia controller about the framebuffer */
250 *((PULONG) 0xfd600800) = (ULONG) FrameBuffer;
251 }
252
253 VIDEODISPLAYMODE
254 XboxVideoSetDisplayMode(char *DisplayMode, BOOL Init)
255 {
256 /* We only have one mode, semi-text */
257 return VideoTextMode;
258 }
259
260 VOID
261 XboxVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth)
262 {
263 *Width = ScreenWidth / CHAR_WIDTH;
264 *Height = (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT;
265 *Depth = 0;
266 }
267
268 ULONG
269 XboxVideoGetBufferSize(VOID)
270 {
271 return (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT * (ScreenWidth / CHAR_WIDTH) * 2;
272 }
273
274 VOID
275 XboxVideoSetTextCursorPosition(ULONG X, ULONG Y)
276 {
277 /* We don't have a cursor yet */
278 }
279
280 VOID
281 XboxVideoHideShowTextCursor(BOOL Show)
282 {
283 /* We don't have a cursor yet */
284 }
285
286 VOID
287 XboxVideoCopyOffScreenBufferToVRAM(PVOID Buffer)
288 {
289 PUCHAR OffScreenBuffer = (PUCHAR) Buffer;
290 ULONG Col, Line;
291
292 for (Line = 0; Line < (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; Line++)
293 {
294 for (Col = 0; Col < ScreenWidth / CHAR_WIDTH; Col++)
295 {
296 XboxVideoPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Line);
297 OffScreenBuffer += 2;
298 }
299 }
300 }
301
302 BOOL
303 XboxVideoIsPaletteFixed(VOID)
304 {
305 return FALSE;
306 }
307
308 VOID
309 XboxVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue)
310 {
311 /* Not supported */
312 }
313
314 VOID
315 XboxVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue)
316 {
317 /* Not supported */
318 }
319
320 VOID
321 XboxVideoSync()
322 {
323 /* Not supported */
324 }
325
326 VOID
327 XboxVideoPrepareForReactOS(VOID)
328 {
329 XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
330 }
331
332 /* EOF */