Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/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
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
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 * Default GTF parameter values.
121 */
122#define kCellGranularity 8.0 // character cell granularity
123#define kMinVSyncPlusBP 550.0 // min VSync + BP interval (us)
124#define kMinFrontPorch 1.0 // minimum front porch in lines(V)/cells(H)
125#define kVSyncLines 3.0 // width of VSync in lines
126#define kHSyncWidth 8.0 // HSync as a percent of total line width
127#define kC 30.0 // C = (C'-J) * (K/256) + J
128#define kM 300.0 // M = K/256 * M'
129
130int Round(double f)
131{
132return (int)(f + 0.5);
133}
134
135/*
136 * from http://www.azillionmonkeys.com/qed/sqroot.html
137 */
138
139double Sqrt( double y )
140{
141double x, z, tempf;
142unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
143
144tempf = y;
145*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
146x = tempf;
147z = y*0.5; /* hoist out the “/2” */
148x = (1.5*x) - (x*x)*(x*z); /* iteration formula */
149x = (1.5*x) - (x*x)*(x*z);
150x = (1.5*x) - (x*x)*(x*z);
151x = (1.5*x) - (x*x)*(x*z);
152x = (1.5*x) - (x*x)*(x*z);
153return x*y;
154}
155
156int generateCRTCTiming( unsigned short width,
157 unsigned short height,
158 unsigned long paramValue,
159 int paramType,
160 VBECRTCInfoBlock * timing )
161{
162 double h_period_est, h_freq, h_period, h_total_pixels, h_sync_pixels;
163 double h_active_pixels, h_ideal_duty_cycle, h_blank_pixels, pixel_freq = 0;
164 double v_sync_plus_bp = 0, v_total_lines = 0, v_field_rate_est, v_frame_rate = 0;
165 const double h_pixels = (double) width;
166 const double v_lines = (double) height;
167
168 enum {
169 left_margin_pixels = 0,
170 right_margin_pixels = 0,
171 top_margin_lines = 0,
172 bot_margin_lines = 0,
173 interlace = 0
174 };
175
176 // Total number of active pixels in image and both margins
177 h_active_pixels = h_pixels + left_margin_pixels + right_margin_pixels;
178
179 if (paramType == kCRTCParamPixelClock)
180 {
181 // Pixel clock provided in MHz
182 pixel_freq = (double) paramValue / 1000000;
183
184 // Ideal horizontal period from the blanking duty cycle equation
185 h_period = ((kC - 100) + (Sqrt(((100 - kC) * (100 - kC)) + (0.4 * kM *
186 (h_active_pixels + right_margin_pixels + left_margin_pixels) /
187 pixel_freq)))) / 2.0 / kM * 1000;
188 }
189 else /* kCRTCParamRefreshRate */
190 {
191 double v_field_rate_in = (double) paramValue;
192
193 // Estimate the horizontal period
194 h_period_est = ((1 / v_field_rate_in) - kMinVSyncPlusBP / 1000000) /
195 (v_lines + (2 * top_margin_lines) + kMinFrontPorch + interlace) *
196 1000000;
197
198 // Number of lines in Vsync + back porch
199 v_sync_plus_bp = Round(kMinVSyncPlusBP / h_period_est);
200
201 // Total number of lines in Vetical field period
202 v_total_lines = v_lines + top_margin_lines + bot_margin_lines +
203 v_sync_plus_bp + interlace + kMinFrontPorch;
204
205 // Estimate the vertical field frequency
206 v_field_rate_est = 1 / h_period_est / v_total_lines * 1000000;
207
208 // Find the actual horizontal period
209 h_period = h_period_est / (v_field_rate_in / v_field_rate_est);
210
211 // Find the vertical frame rate (no interlace)
212 v_frame_rate = 1 / h_period / v_total_lines * 1000000;
213 }
214
215 // Ideal blanking duty cycle from the blanking duty cycle equation
216 h_ideal_duty_cycle = kC - (kM * h_period / 1000);
217
218 // Number of pixels in the blanking time to the nearest double character cell
219 h_blank_pixels = Round(h_active_pixels * h_ideal_duty_cycle /
220 (100 - h_ideal_duty_cycle) / (2 * kCellGranularity)) *
221 (2 * kCellGranularity);
222
223 // Total number of horizontal pixels
224 h_total_pixels = h_active_pixels + h_blank_pixels;
225
226 if (paramType == kCRTCParamPixelClock)
227 {
228 // Horizontal frequency
229 h_freq = pixel_freq / h_total_pixels * 1000;
230
231 // Number of lines in V sync + back porch
232 v_sync_plus_bp = Round(kMinVSyncPlusBP * h_freq / 1000);
233
234 // Total number of lines in vertical field period
235 v_total_lines = v_lines + top_margin_lines + bot_margin_lines +
236 interlace + v_sync_plus_bp + kMinFrontPorch;
237
238 // Vertical frame frequency
239 v_frame_rate = Round(h_freq / v_total_lines * 1000);
240 }
241 else
242 {
243 // Find pixel clock frequency
244 pixel_freq = Round(h_total_pixels / h_period);
245 }
246
247 h_sync_pixels = Round(h_total_pixels * kHSyncWidth / 100 / kCellGranularity) *
248 kCellGranularity;
249
250 timing->HTotal = h_total_pixels;
251 timing->HSyncStart = h_active_pixels + (h_blank_pixels / 2) - h_sync_pixels;
252 timing->HSyncEnd = timing->HSyncStart + h_sync_pixels;
253 timing->VTotal = v_total_lines;
254 timing->VSyncStart = v_total_lines - v_sync_plus_bp;
255 timing->VSyncEnd = timing->VSyncStart + kVSyncLines;
256 timing->Flags = kCRTCNegativeHorizontalSync;
257 timing->PixelClock = pixel_freq * 1000000;
258 timing->RefreshRate = v_frame_rate * 100;
259
260 return 0;
261}
262
263int setVBEMode(unsigned short mode, const VBECRTCInfoBlock * timing)
264{
265 bb.intno = 0x10;
266 bb.eax.rr = funcSetMode;
267 bb.ebx.rr = mode;
268 if (timing) {
269 bb.es = SEG(timing);
270 bb.edi.rr = OFF(timing);
271 }
272 bios(&bb);
273 return(bb.eax.r.h);
274}
275
276int setVBEPalette(void *palette)
277{
278 bb.intno = 0x10;
279 bb.eax.rr = funcGetSetPaletteData;
280 bb.ebx.r.l = subfuncSet;
281 bb.ecx.rr = 256;
282 bb.edx.rr = 0;
283 bb.es = SEG(palette);
284 bb.edi.rr = OFF(palette);
285 bios(&bb);
286 return(bb.eax.r.h);
287}
288
289int getVBEPalette(void *palette)
290{
291 bb.intno = 0x10;
292 bb.eax.rr = funcGetSetPaletteData;
293 bb.ebx.r.l = subfuncGet;
294 bb.ecx.rr = 256;
295 bb.edx.rr = 0;
296 bb.es = SEG(palette);
297 bb.edi.rr = OFF(palette);
298 bios(&bb);
299 return(bb.eax.r.h);
300}
301
302int getVBECurrentMode(unsigned short *mode)
303{
304 bb.intno = 0x10;
305 bb.eax.rr = funcGetCurrentMode;
306 bios(&bb);
307 *mode = bb.ebx.rr;
308 return(bb.eax.r.h);
309}
310
311int getVBEPixelClock(unsigned short mode, unsigned long * pixelClock)
312{
313 bb.intno = 0x10;
314 bb.eax.rr = funcGetSetPixelClock;
315 bb.ebx.r.l = 0;
316 bb.ecx.rx = *pixelClock;
317 bb.edx.rr = mode;
318 bios(&bb);
319 *pixelClock = bb.ecx.rx;
320 return(bb.eax.r.h);
321}
322

Archive Download this file

Revision: 2355