Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2037