2 * Mesa 3-D graphics library
5 * Copyright (C) 1999 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * DOS/DJGPP device driver v1.6 for Mesa
28 * Copyright (C) 2002 - Borca Daniel
29 * Email : dborca@users.sourceforge.net
30 * Web : http://www.geocities.com/dborca
38 #include <sys/exceptn.h>
39 #include <sys/segments.h>
40 #include <sys/farptr.h>
41 #include <sys/movedata.h>
47 static vl_mode modes
[128];
49 static word16 vesa_ver
;
50 static int banked_selector
, linear_selector
;
51 static int oldmode
= -1;
53 static int vesa_color_precision
= 6;
55 static word16
*vesa_pmcode
;
56 unsigned int vesa_gran_mask
, vesa_gran_shift
;
86 * VESA 3.0 CRTC timings structure
88 typedef struct CRTCInfoBlock
{
89 unsigned short HorizontalTotal
;
90 unsigned short HorizontalSyncStart
;
91 unsigned short HorizontalSyncEnd
;
92 unsigned short VerticalTotal
;
93 unsigned short VerticalSyncStart
;
94 unsigned short VerticalSyncEnd
;
96 unsigned long PixelClock
; /* units of Hz */
97 unsigned short RefreshRate
; /* units of 0.01 Hz */
98 unsigned char reserved
[40];
99 } __PACKED__ CRTCInfoBlock
;
101 #define HNEG (1 << 2)
102 #define VNEG (1 << 3)
103 #define DOUBLESCAN (1 << 0)
106 /* Desc: Attempts to detect VESA, check video modes and create selectors.
119 char vesa_info
[512], tmp
[512];
127 _farpokel(_stubinfo
->ds_selector
, 0, 0x32454256);
130 r
.x
.es
= _stubinfo
->ds_segment
;
131 __dpmi_int(0x10, &r
);
132 movedata(_stubinfo
->ds_selector
, 0, _my_ds(), (unsigned)vesa_info
, 512);
133 if ((r
.x
.ax
!= 0x004f) || ((_32_ vesa_info
[V_SIGN
]) != 0x41534556)) {
137 p
= (word16
*)(((_16_ vesa_info
[V_MODE_SEG
])<<4) + (_16_ vesa_info
[V_MODE_OFS
]));
140 if ((q
->mode
=_farpeekw(__djgpp_dos_sel
, (unsigned long)(p
++))) == 0xffff) {
147 r
.x
.es
= _stubinfo
->ds_segment
;
148 __dpmi_int(0x10, &r
);
149 movedata(_stubinfo
->ds_selector
, 512, _my_ds(), (unsigned)tmp
, 256);
150 switch (tmp
[M_BPP
]) {
152 q
->bpp
= tmp
[M_RED
] + tmp
[M_GREEN
] + tmp
[M_BLUE
];
163 if ((r
.x
.ax
== 0x004f) && ((tmp
[M_ATTR
] & 0x11) == 0x11) && q
->bpp
) {
164 q
->xres
= _16_ tmp
[M_XRES
];
165 q
->yres
= _16_ tmp
[M_YRES
];
166 q
->scanlen
= _16_ tmp
[M_SCANLEN
];
167 q
->gran
= (_16_ tmp
[M_GRAN
])<<10;
168 if (tmp
[M_ATTR
] & 0x80) {
171 linearfb
= _32_ tmp
[M_PHYS_PTR
];
174 if (maxsize
< (q
->scanlen
* q
->yres
)) {
175 maxsize
= q
->scanlen
* q
->yres
;
185 maxsize
= (maxsize
+ 0xfffUL
) & ~0xfffUL
;
186 if (_create_selector(&linear_selector
, linearfb
, maxsize
)) {
190 if (_create_selector(&banked_selector
, 0xa0000, modes
[0].gran
)) {
191 _remove_selector(&linear_selector
);
195 for (q
= modes
; q
->mode
!= 0xffff; q
++) {
196 q
->sel
= (q
->mode
& 0x4000) ? linear_selector
: banked_selector
;
199 if (vesa_info
[V_MAJOR
] >= 2) {
202 __dpmi_int(0x10, &r
);
203 if (r
.x
.ax
== 0x004f) {
204 vesa_pmcode
= (word16
*)malloc(r
.x
.cx
);
205 if (vesa_pmcode
!= NULL
) {
206 movedata(__djgpp_dos_sel
, (r
.x
.es
<< 4) + r
.x
.di
, _my_ds(), (unsigned)vesa_pmcode
, r
.x
.cx
);
207 if (vesa_pmcode
[3]) {
208 p
= (word16
*)((long)vesa_pmcode
+ vesa_pmcode
[3]);
209 while (*p
++ != 0xffff) {
214 if (p
&& (*p
!= 0xffff)) {
218 vesa_swbank
= (void *)((long)vesa_pmcode
+ vesa_pmcode
[0]);
224 vesa_ver
= _16_ vesa_info
[V_MINOR
];
229 /* Desc: Frees all resources allocated by VESA init code.
240 _remove_selector(&linear_selector
);
241 _remove_selector(&banked_selector
);
242 if (vesa_pmcode
!= NULL
) {
250 /* Desc: Uses VESA 3.0 function 0x4F0B to find the closest pixel clock to the requested value.
253 * Out : desired clock
258 _closest_pixclk (int mode_no
, unsigned long vclk
)
266 __dpmi_int(0x10, &r
);
268 return (r
.x
.ax
== 0x004f) ? r
.d
.ecx
: 0;
272 /* Desc: Calculates CRTC mode timings.
274 * In : crtc block, geometry, adjust
280 _crtc_timing (CRTCInfoBlock
*crtc
, int xres
, int yres
, int xadjust
, int yadjust
)
286 int HSWidth
, VSWidth
;
288 int doublescan
= FALSE
;
296 HTotal
= (int)(HDisp
* 1.27) & ~0x7;
297 HSWidth
= (int)((HTotal
- HDisp
) / 5) & ~0x7;
301 VTotal
= VDisp
* 1.07;
302 VSWidth
= (VTotal
/ 100) + 1;
303 VSS
= VDisp
+ ((int)(VTotal
- VDisp
) / 5) + 1;
310 if (SS
< (HDisp
+ 8)) {
315 if ((HTotal
- 24) < SE
) {
328 if (SS
< (VDisp
+ 3)) {
333 if ((VTotal
- 4) < SE
) {
342 crtc
->HorizontalTotal
= HTotal
;
343 crtc
->HorizontalSyncStart
= HSS
;
344 crtc
->HorizontalSyncEnd
= HSE
;
345 crtc
->VerticalTotal
= VTotal
;
346 crtc
->VerticalSyncStart
= VSS
;
347 crtc
->VerticalSyncEnd
= VSE
;
348 crtc
->Flags
= HNEG
| VNEG
;
351 crtc
->Flags
|= DOUBLESCAN
;
356 /* Desc: Attempts to enter specified video mode.
358 * In : ptr to mode structure, refresh rate
364 vesa_entermode (vl_mode
*p
, int refresh
)
368 if (p
->mode
& 0x4000) {
369 VESA
.blit
= _can_mmx() ? vesa_l_dump_virtual_mmx
: vesa_l_dump_virtual
;
371 VESA
.blit
= vesa_b_dump_virtual
;
372 { int n
; for (vesa_gran_shift
=0, n
=p
->gran
; n
; vesa_gran_shift
++, n
>>=1) ; }
373 vesa_gran_mask
= (1 << (--vesa_gran_shift
)) - 1;
374 if ((unsigned)p
->gran
!= (vesa_gran_mask
+1)) {
381 __dpmi_int(0x10, &r
);
388 if (refresh
&& ((vesa_ver
>>8) >= 3)) {
389 /* VESA 3.0 stuff for controlling the refresh rate */
394 _crtc_timing(&crtc
, p
->xres
, p
->yres
, 0, 0);
396 vclk
= (double)crtc
.HorizontalTotal
* crtc
.VerticalTotal
* refresh
;
397 vclk
= _closest_pixclk(p
->mode
, vclk
);
400 f0
= (double)vclk
/ (crtc
.HorizontalTotal
* crtc
.VerticalTotal
);
401 /*_current_refresh_rate = (int)(f0 + 0.5);*/
403 crtc
.PixelClock
= vclk
;
404 crtc
.RefreshRate
= refresh
* 100;
406 movedata(_my_ds(), (unsigned)&crtc
, _stubinfo
->ds_selector
, 0, sizeof(crtc
));
409 r
.x
.es
= _stubinfo
->ds_segment
;
414 __dpmi_int(0x10, &r
);
415 if (r
.x
.ax
!= 0x004f) {
422 __dpmi_int(0x10, &r
);
423 if (r
.x
.ax
== 0x004f) {
426 __dpmi_int(0x10, &r
);
427 vesa_color_precision
= r
.h
.bh
;
435 /* Desc: Restores to the mode prior to first call to vesa_entermode.
450 __dpmi_int(0x10, &r
);
456 /* Desc: set one palette entry
458 * In : color index, R, G, B
461 * Note: uses integer values
464 vesa_setCI_i (int index
, int red
, int green
, int blue
)
468 movw $0x1010, %%ax \n\
472 "::"b"(index
), "m"(red
), "m"(green
), "c"(blue
):"%eax", "%edx");
474 outportb(0x03C8, index
);
475 outportb(0x03C9, red
);
476 outportb(0x03C9, green
);
477 outportb(0x03C9, blue
);
482 /* Desc: set one palette entry
484 * In : color index, R, G, B
487 * Note: uses normalized values
490 vesa_setCI_f (int index
, float red
, float green
, float blue
)
492 float max
= (1 << vesa_color_precision
) - 1;
494 vesa_setCI_i(index
, (int)(red
* max
), (int)(green
* max
), (int)(blue
* max
));
498 /* Desc: state retrieval
500 * In : parameter name, ptr to storage
501 * Out : 0 if request successfully processed
506 vesa_get (int pname
, int *params
)
510 params
[0] = vesa_color_precision
;