Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2759