2  * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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 
  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 
  22  * @APPLE_LICENSE_HEADER_END@ 
  25  * Copyright 1993 NeXT, Inc. 
  26  * All rights reserved. 
  33  * Various inline routines for video I/O 
  36 outi (int port
, int index
, int val
) 
  38     outw (port
, (val 
<< 8) | index
); 
  42 outib (int port
, int index
, int val
) 
  49 ini (int port
, int index
) 
  52     return inb (port 
+ 1); 
  56 rmwi (int port
, int index
, int clear
, int set
) 
  59     outb (port 
+ 1, (inb (port 
+ 1) & ~clear
) | set
); 
  67 int getVBEInfo( void * infoBlock 
) 
  70     bb
.eax
.rr 
= funcGetControllerInfo
; 
  71     bb
.es     
= SEG( infoBlock 
); 
  72     bb
.edi
.rr 
= OFF( infoBlock 
); 
  77 int getVBEModeInfo( int mode
, void * minfo_p 
) 
  80     bb
.eax
.rr 
= funcGetModeInfo
; 
  83     bb
.edi
.rr 
= OFF(minfo_p
); 
  88 int getVBEDACFormat(unsigned char *format
) 
  91     bb
.eax
.rr 
= funcGetSetPaletteFormat
; 
  92     bb
.ebx
.r
.l 
= subfuncGet
; 
  98 int setVBEDACFormat(unsigned char format
) 
 101     bb
.eax
.rr 
= funcGetSetPaletteFormat
; 
 102     bb
.ebx
.r
.l 
= subfuncSet
; 
 109  * Default GTF parameter values. 
 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' 
 119 static inline double Round( double f 
) 
 121     asm volatile ("frndint" : "=t" (f
) : "0" (f
)); 
 125 static inline double Sqrt( double f 
) 
 127     asm volatile ("fsqrt" : "=t" (f
) : "0" (f
)); 
 131 int generateCRTCTiming( unsigned short     width
, 
 132                         unsigned short     height
, 
 133                         unsigned long      paramValue
,   
 135                         VBECRTCInfoBlock 
* timing 
) 
 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
; 
 144         left_margin_pixels  
= 0, 
 145         right_margin_pixels 
= 0, 
 146         top_margin_lines    
= 0, 
 147         bot_margin_lines    
= 0, 
 151     // Total number of active pixels in image and both margins 
 152     h_active_pixels 
= h_pixels 
+ left_margin_pixels 
+ right_margin_pixels
; 
 154     if (paramType 
== kCRTCParamPixelClock
) 
 156         // Pixel clock provided in MHz 
 157         pixel_freq 
= (double) paramValue 
/ 1000000; 
 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; 
 164     else /* kCRTCParamRefreshRate */ 
 166         double v_field_rate_in 
= (double) paramValue
; 
 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
) *  
 173         // Number of lines in Vsync + back porch 
 174         v_sync_plus_bp 
= Round(kMinVSyncPlusBP 
/ h_period_est
); 
 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
; 
 180         // Estimate the vertical field frequency 
 181         v_field_rate_est 
= 1 / h_period_est 
/ v_total_lines 
* 1000000; 
 183         // Find the actual horizontal period 
 184         h_period 
= h_period_est 
/ (v_field_rate_in 
/ v_field_rate_est
); 
 186         // Find the vertical frame rate (no interlace) 
 187         v_frame_rate 
= 1 / h_period 
/ v_total_lines 
* 1000000; 
 190     // Ideal blanking duty cycle from the blanking duty cycle equation 
 191     h_ideal_duty_cycle 
= kC 
- (kM 
* h_period 
/ 1000); 
 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
); 
 198     // Total number of horizontal pixels 
 199     h_total_pixels 
= h_active_pixels 
+ h_blank_pixels
; 
 201     if (paramType 
== kCRTCParamPixelClock
) 
 203         // Horizontal frequency 
 204         h_freq 
= pixel_freq 
/ h_total_pixels 
* 1000; 
 206         // Number of lines in V sync + back porch 
 207         v_sync_plus_bp 
= Round(kMinVSyncPlusBP 
* h_freq 
/ 1000); 
 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
; 
 213         // Vertical frame frequency 
 214         v_frame_rate 
= Round(h_freq 
/ v_total_lines 
* 1000); 
 218         // Find pixel clock frequency 
 219         pixel_freq 
= Round(h_total_pixels 
/ h_period
); 
 222     h_sync_pixels 
= Round(h_total_pixels 
* kHSyncWidth 
/ 100 / kCellGranularity
) * 
 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; 
 238 int setVBEMode(unsigned short mode
, const VBECRTCInfoBlock 
* timing
) 
 241     bb
.eax
.rr 
= funcSetMode
; 
 245         bb
.edi
.rr 
= OFF(timing
); 
 251 int setVBEPalette(void *palette
) 
 254     bb
.eax
.rr 
= funcGetSetPaletteData
; 
 255     bb
.ebx
.r
.l 
= subfuncSet
; 
 258     bb
.es 
= SEG(palette
); 
 259     bb
.edi
.rr 
= OFF(palette
); 
 264 int getVBEPalette(void *palette
) 
 267     bb
.eax
.rr 
= funcGetSetPaletteData
; 
 268     bb
.ebx
.r
.l 
= subfuncGet
; 
 271     bb
.es 
= SEG(palette
); 
 272     bb
.edi
.rr 
= OFF(palette
); 
 277 int getVBECurrentMode(unsigned short *mode
) 
 280     bb
.eax
.rr 
= funcGetCurrentMode
; 
 286 int getVBEPixelClock(unsigned short mode
, unsigned long * pixelClock
) 
 289     bb
.eax
.rr  
= funcGetSetPixelClock
; 
 291     bb
.ecx
.rx  
= *pixelClock
; 
 294     *pixelClock 
= bb
.ecx
.rx
;