Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/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 "io_inline.h"
31#include "saio_types.h"
32#include "saio_internal.h"
33#include "vbe.h"
34
35/*
36 * Various inline routines for video I/O
37 */
38static inline void
39outi (int port, int index, int val)
40{
41 outw (port, (val << 8) | index);
42}
43
44static inline void
45outib (int port, int index, int val)
46{
47 outb (port, index);
48 outb (port + 1, val);
49}
50
51static inline int
52ini (int port, int index)
53{
54 outb (port, index);
55 return inb (port + 1);
56}
57
58static inline void
59rmwi (int port, int index, int clear, int set)
60{
61 outb (port, index);
62 outb (port + 1, (inb (port + 1) & ~clear) | set);
63}
64
65/*
66 * Globals
67 */
68static biosBuf_t bb;
69
70int getVBEInfo( void * infoBlock )
71{
72 bb.intno = 0x10;
73 bb.eax.rr = funcGetControllerInfo;
74 bb.es = SEG( infoBlock );
75 bb.edi.rr = OFF( infoBlock );
76 bios( &bb );
77 return(bb.eax.r.h);
78}
79
80int getVBEModeInfo( int mode, void * minfo_p )
81{
82 bb.intno = 0x10;
83 bb.eax.rr = funcGetModeInfo;
84 bb.ecx.rr = mode;
85 bb.es = SEG(minfo_p);
86 bb.edi.rr = OFF(minfo_p);
87 bios(&bb);
88 return(bb.eax.r.h);
89}
90
91int getVBEDACFormat(unsigned char *format)
92{
93 bb.intno = 0x10;
94 bb.eax.rr = funcGetSetPaletteFormat;
95 bb.ebx.r.l = subfuncGet;
96 bios(&bb);
97 *format = bb.ebx.r.h;
98 return(bb.eax.r.h);
99}
100
101int setVBEDACFormat(unsigned char format)
102{
103 bb.intno = 0x10;
104 bb.eax.rr = funcGetSetPaletteFormat;
105 bb.ebx.r.l = subfuncSet;
106 bb.ebx.r.h = format;
107 bios(&bb);
108 return(bb.eax.r.h);
109}
110
111/*
112 *EDID/DDC Readings - AutoResolution
113 */
114int getEDID( void *ddcblock, uint8_t blocksleft )
115{
116bb.intno = 0x10;
117bb.eax.rr = FUNC_GET_EDID;
118bb.ebx.r.l = SERVICE_READ_EDID;
119bb.es = SEG( ddcblock );
120bb.edi.rr = OFF( ddcblock );
121bb.edx.rr = blocksleft;
122bios( &bb );
123return( bb.eax.r.h );
124}
125
126/*
127 * Default GTF parameter values.
128 */
129#define kCellGranularity 8.0 // character cell granularity
130#define kMinVSyncPlusBP 550.0 // min VSync + BP interval (us)
131#define kMinFrontPorch 1.0 // minimum front porch in lines(V)/cells(H)
132#define kVSyncLines 3.0 // width of VSync in lines
133#define kHSyncWidth 8.0 // HSync as a percent of total line width
134#define kC 30.0 // C = (C'-J) * (K/256) + J
135#define kM 300.0 // M = K/256 * M'
136
137int Round(double f)
138{
139return (int)(f + 0.5);
140}
141
142/*
143 * from http://www.azillionmonkeys.com/qed/sqroot.html
144 */
145
146double Sqrt( double y )
147{
148double x, z, tempf;
149unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
150
151tempf = y;
152*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
153x = tempf;
154z = y*0.5; /* hoist out the “/2” */
155x = (1.5*x) - (x*x)*(x*z); /* iteration formula */
156x = (1.5*x) - (x*x)*(x*z);
157x = (1.5*x) - (x*x)*(x*z);
158x = (1.5*x) - (x*x)*(x*z);
159x = (1.5*x) - (x*x)*(x*z);
160return x*y;
161}
162
163int generateCRTCTiming( unsigned short width,
164 unsigned short height,
165 unsigned long paramValue,
166 int paramType,
167 VBECRTCInfoBlock * timing )
168{
169 double h_period_est, h_freq, h_period, h_total_pixels, h_sync_pixels;
170 double h_active_pixels, h_ideal_duty_cycle, h_blank_pixels, pixel_freq = 0;
171 double v_sync_plus_bp = 0, v_total_lines = 0, v_field_rate_est, v_frame_rate = 0;
172 const double h_pixels = (double) width;
173 const double v_lines = (double) height;
174
175 enum {
176 left_margin_pixels = 0,
177 right_margin_pixels = 0,
178 top_margin_lines = 0,
179 bot_margin_lines = 0,
180 interlace = 0
181 };
182
183 // Total number of active pixels in image and both margins
184 h_active_pixels = h_pixels + left_margin_pixels + right_margin_pixels;
185
186 if (paramType == kCRTCParamPixelClock)
187 {
188 // Pixel clock provided in MHz
189 pixel_freq = (double) paramValue / 1000000;
190
191 // Ideal horizontal period from the blanking duty cycle equation
192 h_period = ((kC - 100) + (Sqrt(((100 - kC) * (100 - kC)) + (0.4 * kM *
193 (h_active_pixels + right_margin_pixels + left_margin_pixels) /
194 pixel_freq)))) / 2.0 / kM * 1000;
195 }
196 else /* kCRTCParamRefreshRate */
197 {
198 double v_field_rate_in = (double) paramValue;
199
200 // Estimate the horizontal period
201 h_period_est = ((1 / v_field_rate_in) - kMinVSyncPlusBP / 1000000) /
202 (v_lines + (2 * top_margin_lines) + kMinFrontPorch + interlace) *
203 1000000;
204
205 // Number of lines in Vsync + back porch
206 v_sync_plus_bp = Round(kMinVSyncPlusBP / h_period_est);
207
208 // Total number of lines in Vetical field period
209 v_total_lines = v_lines + top_margin_lines + bot_margin_lines +
210 v_sync_plus_bp + interlace + kMinFrontPorch;
211
212 // Estimate the vertical field frequency
213 v_field_rate_est = 1 / h_period_est / v_total_lines * 1000000;
214
215 // Find the actual horizontal period
216 h_period = h_period_est / (v_field_rate_in / v_field_rate_est);
217
218 // Find the vertical frame rate (no interlace)
219 v_frame_rate = 1 / h_period / v_total_lines * 1000000;
220 }
221
222 // Ideal blanking duty cycle from the blanking duty cycle equation
223 h_ideal_duty_cycle = kC - (kM * h_period / 1000);
224
225 // Number of pixels in the blanking time to the nearest double character cell
226 h_blank_pixels = Round(h_active_pixels * h_ideal_duty_cycle /
227 (100 - h_ideal_duty_cycle) / (2 * kCellGranularity)) *
228 (2 * kCellGranularity);
229
230 // Total number of horizontal pixels
231 h_total_pixels = h_active_pixels + h_blank_pixels;
232
233 if (paramType == kCRTCParamPixelClock)
234 {
235 // Horizontal frequency
236 h_freq = pixel_freq / h_total_pixels * 1000;
237
238 // Number of lines in V sync + back porch
239 v_sync_plus_bp = Round(kMinVSyncPlusBP * h_freq / 1000);
240
241 // Total number of lines in vertical field period
242 v_total_lines = v_lines + top_margin_lines + bot_margin_lines +
243 interlace + v_sync_plus_bp + kMinFrontPorch;
244
245 // Vertical frame frequency
246 v_frame_rate = Round(h_freq / v_total_lines * 1000);
247 }
248 else
249 {
250 // Find pixel clock frequency
251 pixel_freq = Round(h_total_pixels / h_period);
252 }
253
254 h_sync_pixels = Round(h_total_pixels * kHSyncWidth / 100 / kCellGranularity) *
255 kCellGranularity;
256
257 timing->HTotal = h_total_pixels;
258 timing->HSyncStart = h_active_pixels + (h_blank_pixels / 2) - h_sync_pixels;
259 timing->HSyncEnd = timing->HSyncStart + h_sync_pixels;
260 timing->VTotal = v_total_lines;
261 timing->VSyncStart = v_total_lines - v_sync_plus_bp;
262 timing->VSyncEnd = timing->VSyncStart + kVSyncLines;
263 timing->Flags = kCRTCNegativeHorizontalSync;
264 timing->PixelClock = pixel_freq * 1000000;
265 timing->RefreshRate = v_frame_rate * 100;
266
267 return 0;
268}
269
270int setVBEMode(unsigned short mode, const VBECRTCInfoBlock * timing)
271{
272 bb.intno = 0x10;
273 bb.eax.rr = funcSetMode;
274 bb.ebx.rr = mode;
275 if (timing) {
276 bb.es = SEG(timing);
277 bb.edi.rr = OFF(timing);
278 }
279 bios(&bb);
280 return(bb.eax.r.h);
281}
282
283int setVBEPalette(void *palette)
284{
285 bb.intno = 0x10;
286 bb.eax.rr = funcGetSetPaletteData;
287 bb.ebx.r.l = subfuncSet;
288 bb.ecx.rr = 256;
289 bb.edx.rr = 0;
290 bb.es = SEG(palette);
291 bb.edi.rr = OFF(palette);
292 bios(&bb);
293 return(bb.eax.r.h);
294}
295
296int getVBEPalette(void *palette)
297{
298 bb.intno = 0x10;
299 bb.eax.rr = funcGetSetPaletteData;
300 bb.ebx.r.l = subfuncGet;
301 bb.ecx.rr = 256;
302 bb.edx.rr = 0;
303 bb.es = SEG(palette);
304 bb.edi.rr = OFF(palette);
305 bios(&bb);
306 return(bb.eax.r.h);
307}
308
309int getVBECurrentMode(unsigned short *mode)
310{
311 bb.intno = 0x10;
312 bb.eax.rr = funcGetCurrentMode;
313 bios(&bb);
314 *mode = bb.ebx.rr;
315 return(bb.eax.r.h);
316}
317
318int getVBEPixelClock(unsigned short mode, unsigned long * pixelClock)
319{
320 bb.intno = 0x10;
321 bb.eax.rr = funcGetSetPixelClock;
322 bb.ebx.r.l = 0;
323 bb.ecx.rx = *pixelClock;
324 bb.edx.rr = mode;
325 bios(&bb);
326 *pixelClock = bb.ecx.rx;
327 return(bb.eax.r.h);
328}
329

Archive Download this file

Revision: 840