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

Archive Download this file

Revision: 2062