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 for Mesa
28 * Author: Daniel Borca
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
;
184 if (_create_selector(&banked_selector
, 0xa0000, modes
[0].gran
)) {
188 maxsize
= ((maxsize
+ 0xfffUL
) & ~0xfffUL
);
189 if (_create_selector(&linear_selector
, linearfb
, maxsize
)) {
190 linear_selector
= banked_selector
;
194 for (q
= modes
; q
->mode
!= 0xffff; q
++) {
195 q
->sel
= banked_selector
;
196 if (q
->mode
& 0x4000) {
197 if (linear_selector
!= banked_selector
) {
198 q
->sel
= linear_selector
;
205 if (vesa_info
[V_MAJOR
] >= 2) {
208 __dpmi_int(0x10, &r
);
209 if (r
.x
.ax
== 0x004f) {
210 vesa_pmcode
= (word16
*)malloc(r
.x
.cx
);
211 if (vesa_pmcode
!= NULL
) {
212 movedata(__djgpp_dos_sel
, (r
.x
.es
<< 4) + r
.x
.di
, _my_ds(), (unsigned)vesa_pmcode
, r
.x
.cx
);
213 if (vesa_pmcode
[3]) {
214 p
= (word16
*)((long)vesa_pmcode
+ vesa_pmcode
[3]);
215 while (*p
++ != 0xffff) {
220 if (p
&& (*p
!= 0xffff)) {
224 vesa_swbank
= (void *)((long)vesa_pmcode
+ vesa_pmcode
[0]);
230 vesa_ver
= _16_ vesa_info
[V_MINOR
];
235 /* Desc: Frees all resources allocated by VESA init code.
246 _remove_selector(&linear_selector
);
247 _remove_selector(&banked_selector
);
248 if (vesa_pmcode
!= NULL
) {
256 /* Desc: Uses VESA 3.0 function 0x4F0B to find the closest pixel clock to the requested value.
259 * Out : desired clock
264 _closest_pixclk (int mode_no
, unsigned long vclk
)
272 __dpmi_int(0x10, &r
);
274 return (r
.x
.ax
== 0x004f) ? r
.d
.ecx
: 0;
278 /* Desc: Calculates CRTC mode timings.
280 * In : crtc block, geometry, adjust
286 _crtc_timing (CRTCInfoBlock
*crtc
, int xres
, int yres
, int xadjust
, int yadjust
)
292 int HSWidth
, VSWidth
;
294 int doublescan
= FALSE
;
302 HTotal
= (int)(HDisp
* 1.27) & ~0x7;
303 HSWidth
= (int)((HTotal
- HDisp
) / 5) & ~0x7;
307 VTotal
= VDisp
* 1.07;
308 VSWidth
= (VTotal
/ 100) + 1;
309 VSS
= VDisp
+ ((int)(VTotal
- VDisp
) / 5) + 1;
316 if (SS
< (HDisp
+ 8)) {
321 if ((HTotal
- 24) < SE
) {
334 if (SS
< (VDisp
+ 3)) {
339 if ((VTotal
- 4) < SE
) {
348 crtc
->HorizontalTotal
= HTotal
;
349 crtc
->HorizontalSyncStart
= HSS
;
350 crtc
->HorizontalSyncEnd
= HSE
;
351 crtc
->VerticalTotal
= VTotal
;
352 crtc
->VerticalSyncStart
= VSS
;
353 crtc
->VerticalSyncEnd
= VSE
;
354 crtc
->Flags
= HNEG
| VNEG
;
357 crtc
->Flags
|= DOUBLESCAN
;
362 /* Desc: Attempts to choose a suitable blitter.
364 * In : ptr to mode structure, software framebuffer bits
365 * Out : blitter funciton, or NULL
370 _choose_blitter (vl_mode
*p
, int fbbits
)
374 if (p
->mode
& 0x4000) {
375 blitter
= _can_mmx() ? vesa_l_dump_virtual_mmx
: vesa_l_dump_virtual
;
382 blitter
= vesa_l_dump_16_to_8
;
385 blitter
= vesa_l_dump_24_to_8
;
388 blitter
= vesa_l_dump_32_to_8
;
398 blitter
= vesa_l_dump_16_to_15
;
401 blitter
= vesa_l_dump_32_to_15
;
415 blitter
= vesa_l_dump_32_to_16
;
429 blitter
= vesa_l_dump_32_to_24
;
441 blitter
= vesa_l_dump_24_to_32
;
454 blitter
= vesa_b_dump_virtual
;
461 blitter
= vesa_b_dump_16_to_8
;
464 blitter
= vesa_b_dump_24_to_8
;
467 blitter
= vesa_b_dump_32_to_8
;
477 blitter
= vesa_b_dump_16_to_15
;
480 blitter
= vesa_b_dump_32_to_15
;
494 blitter
= vesa_b_dump_32_to_16
;
508 blitter
= vesa_b_dump_32_to_24
;
520 blitter
= vesa_b_dump_24_to_32
;
538 /* Desc: Attempts to enter specified video mode.
540 * In : ptr to mode structure, refresh rate
546 vesa_entermode (vl_mode
*p
, int refresh
, int fbbits
)
550 if (!(p
->mode
& 0x4000)) {
551 { int n
; for (vesa_gran_shift
= 0, n
= p
->gran
; n
; vesa_gran_shift
++, n
>>= 1); }
552 vesa_gran_mask
= (1 << (--vesa_gran_shift
)) - 1;
553 if ((unsigned)p
->gran
!= (vesa_gran_mask
+ 1)) {
558 VESA
.blit
= _choose_blitter(p
, fbbits
);
559 if (VESA
.blit
== NULL
) {
565 __dpmi_int(0x10, &r
);
572 if (refresh
&& ((vesa_ver
>> 8) >= 3)) {
573 /* VESA 3.0 stuff for controlling the refresh rate */
578 _crtc_timing(&crtc
, p
->xres
, p
->yres
, 0, 0);
580 vclk
= (double)crtc
.HorizontalTotal
* crtc
.VerticalTotal
* refresh
;
581 vclk
= _closest_pixclk(p
->mode
, vclk
);
584 f0
= (double)vclk
/ (crtc
.HorizontalTotal
* crtc
.VerticalTotal
);
585 /*_current_refresh_rate = (int)(f0 + 0.5);*/
587 crtc
.PixelClock
= vclk
;
588 crtc
.RefreshRate
= refresh
* 100;
590 movedata(_my_ds(), (unsigned)&crtc
, _stubinfo
->ds_selector
, 0, sizeof(crtc
));
593 r
.x
.es
= _stubinfo
->ds_segment
;
598 __dpmi_int(0x10, &r
);
599 if (r
.x
.ax
!= 0x004f) {
606 __dpmi_int(0x10, &r
);
607 if (r
.x
.ax
== 0x004f) {
610 __dpmi_int(0x10, &r
);
611 vesa_color_precision
= r
.h
.bh
;
619 /* Desc: Restores to the mode prior to first call to vesa_entermode.
632 if (oldmode
< 0x100) {
633 __asm("int $0x10"::"a"(oldmode
));
637 __dpmi_int(0x10, &r
);
644 /* Desc: set one palette entry
646 * In : color index, R, G, B
649 * Note: uses integer values
652 vesa_setCI_i (int index
, int red
, int green
, int blue
)
656 movw $0x1010, %%ax \n\
660 "::"b"(index
), "m"(red
), "m"(green
), "c"(blue
):"%eax", "%edx");
662 outportb(0x03C8, index
);
663 outportb(0x03C9, red
);
664 outportb(0x03C9, green
);
665 outportb(0x03C9, blue
);
670 /* Desc: set one palette entry
672 * In : color index, R, G, B
675 * Note: uses normalized values
678 vesa_setCI_f (int index
, float red
, float green
, float blue
)
680 float max
= (1 << vesa_color_precision
) - 1;
682 vesa_setCI_i(index
, (int)(red
* max
), (int)(green
* max
), (int)(blue
* max
));
686 /* Desc: state retrieval
688 * In : parameter name, ptr to storage
689 * Out : 0 if request successfully processed
694 vesa_get (int pname
, int *params
)
698 params
[0] = vesa_color_precision
;