bd33b8856cf94852a033d6d2d7bab569775f60fb
[profile/ivi/mesa.git] / src / mesa / drivers / dos / dpmi.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  4.0
4  * 
5  * Copyright (C) 1999  Brian Paul   All Rights Reserved.
6  * 
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:
13  * 
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  * 
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.
23  */
24
25 /*
26  * DOS/DJGPP device driver for Mesa
27  *
28  *  Author: Daniel Borca
29  *  Email : dborca@yahoo.com
30  *  Web   : http://www.geocities.com/dborca
31  */
32
33
34 #include <dpmi.h>
35
36 #include "internal.h"
37
38
39 #ifndef MAX
40 #define MAX(x, y) (((x) < (y)) ? (y) : (x))
41 #endif
42
43
44 /* _create_linear_mapping:
45  *  Maps a physical address range into linear memory.
46  */
47 int
48 _create_linear_mapping (unsigned long *linear, unsigned long physaddr, int size)
49 {
50    __dpmi_meminfo meminfo;
51
52    if (physaddr >= 0x100000) {
53       /* map into linear memory */
54       meminfo.address = physaddr;
55       meminfo.size = size;
56       if (__dpmi_physical_address_mapping(&meminfo) != 0) {
57          return -1;
58       }
59
60       *linear = meminfo.address;
61    } else {
62       /* exploit 1 -> 1 physical to linear mapping in low megabyte */
63       *linear = physaddr;
64    }
65
66    return 0;
67 }
68
69
70 /* _remove_linear_mapping:
71  *  Frees the DPMI resources being used to map a linear address range.
72  */
73 void
74 _remove_linear_mapping (unsigned long *linear)
75 {
76    __dpmi_meminfo meminfo;
77
78    if (*linear) {
79       if (*linear >= 0x100000) {
80          meminfo.address = *linear;
81          __dpmi_free_physical_address_mapping(&meminfo);
82       }
83
84       *linear = 0;
85    }
86 }
87
88
89 /* _create_selector:
90  *  Allocates a selector to access a region of linear memory.
91  */
92 int
93 _create_selector (int *segment, unsigned long base, int size)
94 {
95    /* allocate an ldt descriptor */
96    if ((*segment=__dpmi_allocate_ldt_descriptors(1)) < 0) {
97       *segment = 0;
98       return -1;
99    }
100
101    /* create the linear mapping */
102    if (_create_linear_mapping(&base, base, size)) {
103       __dpmi_free_ldt_descriptor(*segment);
104       *segment = 0;
105       return -1;
106    }
107
108    /* set the descriptor base and limit */
109    __dpmi_set_segment_base_address(*segment, base);
110    __dpmi_set_segment_limit(*segment, MAX(size-1, 0xFFFF));
111
112    return 0;
113 }
114
115
116 /* _remove_selector:
117  *  Frees a DPMI segment selector.
118  */
119 void
120 _remove_selector (int *segment)
121 {
122    if (*segment) {
123       unsigned long base;
124       __dpmi_get_segment_base_address(*segment, &base);
125       _remove_linear_mapping(&base);
126       __dpmi_free_ldt_descriptor(*segment);
127       *segment = 0;
128    }
129 }
130
131
132 /* Desc: retrieve CPU MMX capability
133  *
134  * In  : -
135  * Out : FALSE if CPU cannot do MMX
136  *
137  * Note: -
138  */
139 int
140 _can_mmx (void)
141 {
142 #ifdef USE_MMX_ASM
143    int x86_cpu_features = 0;
144    __asm("\n\
145                 pushfl                  \n\
146                 popl    %%eax           \n\
147                 movl    %%eax, %%ecx    \n\
148                 xorl    $0x200000, %%eax\n\
149                 pushl   %%eax           \n\
150                 popfl                   \n\
151                 pushfl                  \n\
152                 popl    %%eax           \n\
153                 pushl   %%ecx           \n\
154                 popfl                   \n\
155                 xorl    %%ecx, %%eax    \n\
156                 jz 0f                   \n\
157                 movl    $1, %%eax       \n\
158                 cpuid                   \n\
159                 movl    %%edx, %0       \n\
160         0:                              \n\
161    ":"=g"(x86_cpu_features)::"%eax", "%ebx", "%ecx", "%edx");
162    return (x86_cpu_features & 0x00800000);
163 #else
164    return 0;
165 #endif
166 }