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