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