7668d4cee826a8639c0af62251921ab2a0e255d5
[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
25 #define I2C_IO_BASE 0xc000
26
27 static PVOID FrameBuffer;
28 static ULONG ScreenWidth;
29 static ULONG ScreenHeight;
30 static ULONG BytesPerPixel;
31 static ULONG Delta;
32
33 #define CHAR_WIDTH 8
34 #define CHAR_HEIGHT 16
35
36 #define TOP_BOTTOM_LINES 0
37
38 #define FB_SIZE_MB 4
39
40 #define MAKE_COLOR(Red, Green, Blue) (0xff000000 | (((Red) & 0xff) << 16) | (((Green) & 0xff) << 8) | ((Blue) & 0xff))
41
42 static VOID
43 XboxVideoOutputChar(UCHAR Char, unsigned X, unsigned Y, ULONG FgColor, ULONG BgColor)
44 {
45 PUCHAR FontPtr;
46 PULONG Pixel;
47 UCHAR Mask;
48 unsigned Line;
49 unsigned Col;
50
51 FontPtr = XboxFont8x16 + Char * 16;
52 Pixel = (PULONG) ((char *) FrameBuffer + (Y * CHAR_HEIGHT + TOP_BOTTOM_LINES) * Delta
53 + X * CHAR_WIDTH * BytesPerPixel);
54 for (Line = 0; Line < CHAR_HEIGHT; Line++)
55 {
56 Mask = 0x80;
57 for (Col = 0; Col < CHAR_WIDTH; Col++)
58 {
59 Pixel[Col] = (0 != (FontPtr[Line] & Mask) ? FgColor : BgColor);
60 Mask = Mask >> 1;
61 }
62 Pixel = (PULONG) ((char *) Pixel + Delta);
63 }
64 }
65
66 static ULONG
67 XboxVideoAttrToSingleColor(UCHAR Attr)
68 {
69 UCHAR Intensity;
70
71 Intensity = (0 == (Attr & 0x08) ? 127 : 255);
72
73 return 0xff000000 |
74 (0 == (Attr & 0x04) ? 0 : (Intensity << 16)) |
75 (0 == (Attr & 0x02) ? 0 : (Intensity << 8)) |
76 (0 == (Attr & 0x01) ? 0 : Intensity);
77 }
78
79 static VOID
80 XboxVideoAttrToColors(UCHAR Attr, ULONG *FgColor, ULONG *BgColor)
81 {
82 *FgColor = XboxVideoAttrToSingleColor(Attr & 0xf);
83 *BgColor = XboxVideoAttrToSingleColor((Attr >> 4) & 0xf);
84 }
85
86 static VOID
87 XboxVideoClearScreenColor(ULONG Color, BOOL FullScreen)
88 {
89 ULONG Line, Col;
90 PULONG p;
91
92 for (Line = 0; Line < ScreenHeight - (FullScreen ? 0 : 2 * TOP_BOTTOM_LINES); Line++)
93 {
94 p = (PULONG) ((char *) FrameBuffer + (Line + (FullScreen ? 0 : TOP_BOTTOM_LINES)) * Delta);
95 for (Col = 0; Col < ScreenWidth; Col++)
96 {
97 *p++ = Color;
98 }
99 }
100 }
101
102 VOID
103 XboxVideoClearScreen(UCHAR Attr)
104 {
105 ULONG FgColor, BgColor;
106
107 XboxVideoAttrToColors(Attr, &FgColor, &BgColor);
108
109 XboxVideoClearScreenColor(BgColor, FALSE);
110 }
111
112 VOID
113 XboxVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y)
114 {
115 ULONG FgColor, BgColor;
116
117 XboxVideoAttrToColors(Attr, &FgColor, &BgColor);
118
119 XboxVideoOutputChar(Ch, X, Y, FgColor, BgColor);
120 }
121
122 static BOOL
123 ReadfromSMBus(UCHAR Address, UCHAR bRegister, UCHAR Size, ULONG *Data_to_smbus)
124 {
125 int nRetriesToLive=50;
126
127 while (0 != (READ_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0)) & 0x0800))
128 {
129 ; /* Franz's spin while bus busy with any master traffic */
130 }
131
132 while (0 != nRetriesToLive--)
133 {
134 UCHAR b;
135 int temp;
136
137 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 4), (Address << 1) | 1);
138 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 8), bRegister);
139
140 temp = READ_PORT_USHORT((USHORT *) (I2C_IO_BASE + 0));
141 WRITE_PORT_USHORT((PUSHORT) (I2C_IO_BASE + 0), temp); /* clear down all preexisting errors */
142
143 switch (Size)
144 {
145 case 4:
146 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0d); /* DWORD modus ? */
147 break;
148 case 2:
149 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0b); /* WORD modus */
150 break;
151 default:
152 WRITE_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 2), 0x0a); // BYTE
153 break;
154 }
155
156 b = 0;
157
158 while (0 == (b & 0x36))
159 {
160 b = READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 0));
161 }
162
163 if (0 != (b & 0x24))
164 {
165 /* printf("I2CTransmitByteGetReturn error %x\n", b); */
166 }
167
168 if(0 == (b & 0x10))
169 {
170 /* printf("I2CTransmitByteGetReturn no complete, retry\n"); */
171 }
172 else
173 {
174 switch (Size)
175 {
176 case 4:
177 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 6));
178 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
179 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
180 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
181 READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 9));
182 break;
183 case 2:
184 *Data_to_smbus = READ_PORT_USHORT((USHORT *) (I2C_IO_BASE + 6));
185 break;
186 default:
187 *Data_to_smbus = READ_PORT_UCHAR((PUCHAR) (I2C_IO_BASE + 6));
188 break;
189 }
190
191
192 return TRUE;
193 }
194 }
195
196 return FALSE;
197 }
198
199
200 static BOOL
201 I2CTransmitByteGetReturn(UCHAR bPicAddressI2cFormat, UCHAR bDataToWrite, ULONG *Return)
202 {
203 return ReadfromSMBus(bPicAddressI2cFormat, bDataToWrite, 1, Return);
204 }
205
206
207 VOID
208 XboxVideoInit(VOID)
209 {
210 ULONG AvMode;
211
212 FrameBuffer = (PVOID)((ULONG) XboxMemReserveMemory(FB_SIZE_MB) | 0xf0000000);
213
214 if (I2CTransmitByteGetReturn(0x10, 0x04, &AvMode))
215 {
216 if (1 == AvMode) /* HDTV */
217 {
218 ScreenWidth = 720;
219 }
220 else
221 {
222 /* FIXME Other possible values of AvMode:
223 * 0 - AV_SCART_RGB
224 * 2 - AV_VGA_SOG
225 * 4 - AV_SVIDEO
226 * 6 - AV_COMPOSITE
227 * 7 - AV_VGA
228 * other AV_COMPOSITE
229 */
230 ScreenWidth = 640;
231 }
232 }
233 else
234 {
235 ScreenWidth = 640;
236 }
237
238 ScreenHeight = 480;
239 BytesPerPixel = 4;
240 Delta = (ScreenWidth * BytesPerPixel + 3) & ~ 0x3;
241
242 XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
243
244 /* Tell the nVidia controller about the framebuffer */
245 *((PULONG) 0xfd600800) = (ULONG) FrameBuffer;
246 }
247
248 VIDEODISPLAYMODE
249 XboxVideoSetDisplayMode(char *DisplayMode, BOOL Init)
250 {
251 /* We only have one mode, semi-text */
252 return VideoTextMode;
253 }
254
255 VOID
256 XboxVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth)
257 {
258 *Width = ScreenWidth / CHAR_WIDTH;
259 *Height = (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT;
260 *Depth = 0;
261 }
262
263 ULONG
264 XboxVideoGetBufferSize(VOID)
265 {
266 return (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT * (ScreenWidth / CHAR_WIDTH) * 2;
267 }
268
269 VOID
270 XboxVideoSetTextCursorPosition(ULONG X, ULONG Y)
271 {
272 /* We don't have a cursor yet */
273 }
274
275 VOID
276 XboxVideoHideShowTextCursor(BOOL Show)
277 {
278 /* We don't have a cursor yet */
279 }
280
281 VOID
282 XboxVideoCopyOffScreenBufferToVRAM(PVOID Buffer)
283 {
284 PUCHAR OffScreenBuffer = (PUCHAR) Buffer;
285 ULONG Col, Line;
286
287 for (Line = 0; Line < (ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; Line++)
288 {
289 for (Col = 0; Col < ScreenWidth / CHAR_WIDTH; Col++)
290 {
291 XboxVideoPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Line);
292 OffScreenBuffer += 2;
293 }
294 }
295 }
296
297 BOOL
298 XboxVideoIsPaletteFixed(VOID)
299 {
300 return FALSE;
301 }
302
303 VOID
304 XboxVideoSetPaletteColor(UCHAR Color, UCHAR Red, UCHAR Green, UCHAR Blue)
305 {
306 /* Not supported */
307 }
308
309 VOID
310 XboxVideoGetPaletteColor(UCHAR Color, UCHAR* Red, UCHAR* Green, UCHAR* Blue)
311 {
312 /* Not supported */
313 }
314
315 VOID
316 XboxVideoSync()
317 {
318 /* Not supported */
319 }
320
321 VOID
322 XboxVideoPrepareForReactOS(VOID)
323 {
324 XboxVideoClearScreenColor(MAKE_COLOR(0, 0, 0), TRUE);
325 }
326
327 /* EOF */