Chameleon

Chameleon Svn Source Tree

Root/branches/prasys/i386/libsaio/vbe.c

1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 2.0 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
27 */
28
29#include "libsaio.h"
30#include "vbe.h"
31
32/*
33 * Various inline routines for video I/O
34 */
35static inline void
36outi (int port, int index, int val)
37{
38 outw (port, (val << 8) | index);
39}
40
41static inline void
42outib (int port, int index, int val)
43{
44 outb (port, index);
45 outb (port + 1, val);
46}
47
48static inline int
49ini (int port, int index)
50{
51 outb (port, index);
52 return inb (port + 1);
53}
54
55static inline void
56rmwi (int port, int index, int clear, int set)
57{
58 outb (port, index);
59 outb (port + 1, (inb (port + 1) & ~clear) | set);
60}
61
62/*
63 * Globals
64 */
65static biosBuf_t bb;
66
67int getVBEInfo( void * infoBlock )
68{
69 bb.intno = 0x10;
70 bb.eax.rr = funcGetControllerInfo;
71 bb.es = SEG( infoBlock );
72 bb.edi.rr = OFF( infoBlock );
73 bios( &bb );
74 return(bb.eax.r.h);
75}
76
77
78int getEDID( void * edidBlock, UInt8 block)
79{
80bzero(&bb, sizeof(bb));
81 bb.intno = 0x10;
82 bb.eax.rr = funcGetEDID;
83bb.ebx.r.l= 0x01;
84bb.edx.rr = block;
85
86 bb.es = SEG( edidBlock );
87 bb.edi.rr = OFF( edidBlock );
88
89 bios( &bb );
90 return(bb.eax.r.h);
91}
92
93
94
95int getVBEModeInfo( int mode, void * minfo_p )
96{
97 bb.intno = 0x10;
98 bb.eax.rr = funcGetModeInfo;
99 bb.ecx.rr = mode;
100 bb.es = SEG(minfo_p);
101 bb.edi.rr = OFF(minfo_p);
102 bios(&bb);
103 return(bb.eax.r.h);
104}
105
106int getVBEDACFormat(unsigned char *format)
107{
108 bb.intno = 0x10;
109 bb.eax.rr = funcGetSetPaletteFormat;
110 bb.ebx.r.l = subfuncGet;
111 bios(&bb);
112 *format = bb.ebx.r.h;
113 return(bb.eax.r.h);
114}
115
116int setVBEDACFormat(unsigned char format)
117{
118 bb.intno = 0x10;
119 bb.eax.rr = funcGetSetPaletteFormat;
120 bb.ebx.r.l = subfuncSet;
121 bb.ebx.r.h = format;
122 bios(&bb);
123 return(bb.eax.r.h);
124}
125
126
127
128/*
129 * Default GTF parameter values.
130 */
131#define kCellGranularity 8.0 // character cell granularity
132#define kMinVSyncPlusBP 550.0 // min VSync + BP interval (us)
133#define kMinFrontPorch 1.0 // minimum front porch in lines(V)/cells(H)
134#define kVSyncLines 3.0 // width of VSync in lines
135#define kHSyncWidth 8.0 // HSync as a percent of total line width
136#define kC 30.0 // C = (C'-J) * (K/256) + J
137#define kM 300.0 // M = K/256 * M'
138
139int Round(double f)
140{
141return (int)(f + 0.5);
142}
143
144/*
145 * from http://www.azillionmonkeys.com/qed/sqroot.html
146 */
147
148double Sqrt( double y )
149{
150double x, z, tempf;
151unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
152
153tempf = y;
154*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
155x = tempf;
156z = y*0.5; /* hoist out the “/2” */
157x = (1.5*x) - (x*x)*(x*z); /* iteration formula */
158x = (1.5*x) - (x*x)*(x*z);
159x = (1.5*x) - (x*x)*(x*z);
160x = (1.5*x) - (x*x)*(x*z);
161x = (1.5*x) - (x*x)*(x*z);
162return x*y;
163}
164
165int generateCRTCTiming( unsigned short width,
166 unsigned short height,
167 unsigned long paramValue,
168 int paramType,
169 VBECRTCInfoBlock * timing )
170{
171 double h_period_est, h_freq, h_period, h_total_pixels, h_sync_pixels;
172 double h_active_pixels, h_ideal_duty_cycle, h_blank_pixels, pixel_freq = 0;
173 double v_sync_plus_bp = 0, v_total_lines = 0, v_field_rate_est, v_frame_rate = 0;
174 const double h_pixels = (double) width;
175 const double v_lines = (double) height;
176
177 enum {
178 left_margin_pixels = 0,
179 right_margin_pixels = 0,
180 top_margin_lines = 0,
181 bot_margin_lines = 0,
182 interlace = 0
183 };
184
185 // Total number of active pixels in image and both margins
186 h_active_pixels = h_pixels + left_margin_pixels + right_margin_pixels;
187
188 if (paramType == kCRTCParamPixelClock)
189 {
190 // Pixel clock provided in MHz
191 pixel_freq = (double) paramValue / 1000000;
192
193 // Ideal horizontal period from the blanking duty cycle equation
194 h_period = ((kC - 100) + (Sqrt(((100 - kC) * (100 - kC)) + (0.4 * kM *
195 (h_active_pixels + right_margin_pixels + left_margin_pixels) /
196 pixel_freq)))) / 2.0 / kM * 1000;
197 }
198 else /* kCRTCParamRefreshRate */
199 {
200 double v_field_rate_in = (double) paramValue;
201
202 // Estimate the horizontal period
203 h_period_est = ((1 / v_field_rate_in) - kMinVSyncPlusBP / 1000000) /
204 (v_lines + (2 * top_margin_lines) + kMinFrontPorch + interlace) *
205 1000000;
206
207 // Number of lines in Vsync + back porch
208 v_sync_plus_bp = Round(kMinVSyncPlusBP / h_period_est);
209
210 // Total number of lines in Vetical field period
211 v_total_lines = v_lines + top_margin_lines + bot_margin_lines +
212 v_sync_plus_bp + interlace + kMinFrontPorch;
213
214 // Estimate the vertical field frequency
215 v_field_rate_est = 1 / h_period_est / v_total_lines * 1000000;
216
217 // Find the actual horizontal period
218 h_period = h_period_est / (v_field_rate_in / v_field_rate_est);
219
220 // Find the vertical frame rate (no interlace)
221 v_frame_rate = 1 / h_period / v_total_lines * 1000000;
222 }
223
224 // Ideal blanking duty cycle from the blanking duty cycle equation
225 h_ideal_duty_cycle = kC - (kM * h_period / 1000);
226
227 // Number of pixels in the blanking time to the nearest double character cell
228 h_blank_pixels = Round(h_active_pixels * h_ideal_duty_cycle /
229 (100 - h_ideal_duty_cycle) / (2 * kCellGranularity)) *
230 (2 * kCellGranularity);
231
232 // Total number of horizontal pixels
233 h_total_pixels = h_active_pixels + h_blank_pixels;
234
235 if (paramType == kCRTCParamPixelClock)
236 {
237 // Horizontal frequency
238 h_freq = pixel_freq / h_total_pixels * 1000;
239
240 // Number of lines in V sync + back porch
241 v_sync_plus_bp = Round(kMinVSyncPlusBP * h_freq / 1000);
242
243 // Total number of lines in vertical field period
244 v_total_lines = v_lines + top_margin_lines + bot_margin_lines +
245 interlace + v_sync_plus_bp + kMinFrontPorch;
246
247 // Vertical frame frequency
248 v_frame_rate = Round(h_freq / v_total_lines * 1000);
249 }
250 else
251 {
252 // Find pixel clock frequency
253 pixel_freq = Round(h_total_pixels / h_period);
254 }
255
256 h_sync_pixels = Round(h_total_pixels * kHSyncWidth / 100 / kCellGranularity) *
257 kCellGranularity;
258
259 timing->HTotal = h_total_pixels;
260 timing->HSyncStart = h_active_pixels + (h_blank_pixels / 2) - h_sync_pixels;
261 timing->HSyncEnd = timing->HSyncStart + h_sync_pixels;
262 timing->VTotal = v_total_lines;
263 timing->VSyncStart = v_total_lines - v_sync_plus_bp;
264 timing->VSyncEnd = timing->VSyncStart + kVSyncLines;
265 timing->Flags = kCRTCNegativeHorizontalSync;
266 timing->PixelClock = pixel_freq * 1000000;
267 timing->RefreshRate = v_frame_rate * 100;
268
269 return 0;
270}
271
272int setVBEMode(unsigned short mode, const VBECRTCInfoBlock * timing)
273{
274 bb.intno = 0x10;
275 bb.eax.rr = funcSetMode;
276 bb.ebx.rr = mode;
277 if (timing) {
278 bb.es = SEG(timing);
279 bb.edi.rr = OFF(timing);
280 }
281 bios(&bb);
282 return(bb.eax.r.h);
283}
284
285int setVBEPalette(void *palette)
286{
287 bb.intno = 0x10;
288 bb.eax.rr = funcGetSetPaletteData;
289 bb.ebx.r.l = subfuncSet;
290 bb.ecx.rr = 256;
291 bb.edx.rr = 0;
292 bb.es = SEG(palette);
293 bb.edi.rr = OFF(palette);
294 bios(&bb);
295 return(bb.eax.r.h);
296}
297
298int getVBEPalette(void *palette)
299{
300 bb.intno = 0x10;
301 bb.eax.rr = funcGetSetPaletteData;
302 bb.ebx.r.l = subfuncGet;
303 bb.ecx.rr = 256;
304 bb.edx.rr = 0;
305 bb.es = SEG(palette);
306 bb.edi.rr = OFF(palette);
307 bios(&bb);
308 return(bb.eax.r.h);
309}
310
311int getVBECurrentMode(unsigned short *mode)
312{
313 bb.intno = 0x10;
314 bb.eax.rr = funcGetCurrentMode;
315 bios(&bb);
316 *mode = bb.ebx.rr;
317 return(bb.eax.r.h);
318}
319
320int getVBEPixelClock(unsigned short mode, unsigned long * pixelClock)
321{
322 bb.intno = 0x10;
323 bb.eax.rr = funcGetSetPixelClock;
324 bb.ebx.r.l = 0;
325 bb.ecx.rx = *pixelClock;
326 bb.edx.rr = mode;
327 bios(&bb);
328 *pixelClock = bb.ecx.rx;
329 return(bb.eax.r.h);
330}
331

Archive Download this file

Revision: 33