2 * linux specific part of the int10 module
3 * Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2008 Egbert Eich
5 #ifdef HAVE_XORG_CONFIG_H
6 #include <xorg-config.h>
10 #include "xf86_OSproc.h"
13 #define _INT10_PRIVATE
14 #include "xf86int10.h"
16 #define DEV_MEM "/dev/fb"
18 #define DEV_MEM "/dev/mem"
20 #define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
21 #define SHMERRORPTR (pointer)(-1)
31 static int counter
= 0;
32 static unsigned long int10Generation
= 0;
34 static CARD8
read_b(xf86Int10InfoPtr pInt
, int addr
);
35 static CARD16
read_w(xf86Int10InfoPtr pInt
, int addr
);
36 static CARD32
read_l(xf86Int10InfoPtr pInt
, int addr
);
37 static void write_b(xf86Int10InfoPtr pInt
, int addr
, CARD8 val
);
38 static void write_w(xf86Int10InfoPtr pInt
, int addr
, CARD16 val
);
39 static void write_l(xf86Int10InfoPtr pInt
, int addr
, CARD32 val
);
41 int10MemRec linuxMem
= {
58 #if defined DoSubModules
65 } Int10LinuxSubModuleState
;
67 static Int10LinuxSubModuleState loadedSubModule
= INT10_NOT_LOADED
;
69 static Int10LinuxSubModuleState
int10LinuxLoadSubModule(ScrnInfoPtr pScrn
);
71 #endif /* DoSubModules */
74 xf86ExtendedInitInt10(int entityIndex
, int Flags
)
76 xf86Int10InfoPtr pInt
= NULL
;
79 static void *vidMem
= NULL
;
80 static void *sysMem
= NULL
;
85 char *base
= SHMERRORPTR
;
86 char *base_high
= SHMERRORPTR
;
90 Bool videoBiosMapped
= FALSE
;
92 if (int10Generation
!= serverGeneration
) {
94 int10Generation
= serverGeneration
;
97 pScrn
= xf86FindScreenForEntity(entityIndex
);
98 screen
= pScrn
->scrnIndex
;
100 options
= xf86HandleInt10Options(pScrn
, entityIndex
);
102 if (int10skip(options
)) {
107 #if defined DoSubModules
108 if (loadedSubModule
== INT10_NOT_LOADED
)
109 loadedSubModule
= int10LinuxLoadSubModule(pScrn
);
111 if (loadedSubModule
== INT10_LOAD_FAILED
)
115 if ((!vidMem
) || (!sysMem
)) {
116 if ((fd
= open(DEV_MEM
, O_RDWR
, 0)) >= 0) {
118 DebugF("Mapping sys bios area\n");
119 if ((sysMem
= mmap((void *) (SYS_BIOS
), BIOS_SIZE
,
120 PROT_READ
| PROT_EXEC
,
121 MAP_SHARED
| MAP_FIXED
, fd
, SYS_BIOS
))
123 xf86DrvMsg(screen
, X_ERROR
, "Cannot map SYS BIOS\n");
129 DebugF("Mapping VRAM area\n");
130 if ((vidMem
= mmap((void *) (V_RAM
), VRAM_SIZE
,
131 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
132 MAP_SHARED
| MAP_FIXED
, fd
, V_RAM
))
134 xf86DrvMsg(screen
, X_ERROR
, "Cannot map V_RAM\n");
142 xf86DrvMsg(screen
, X_ERROR
, "Cannot open %s\n", DEV_MEM
);
147 pInt
= (xf86Int10InfoPtr
) xnfcalloc(1, sizeof(xf86Int10InfoRec
));
149 pInt
->entityIndex
= entityIndex
;
150 pInt
->dev
= xf86GetPciInfoForEntity(entityIndex
);
152 if (!xf86Int10ExecSetup(pInt
))
154 pInt
->mem
= &linuxMem
;
155 pagesize
= getpagesize();
156 pInt
->private = (pointer
) xnfcalloc(1, sizeof(linuxInt10Priv
));
157 ((linuxInt10Priv
*) pInt
->private)->alloc
=
158 (pointer
) xnfcalloc(1, ALLOC_ENTRIES(pagesize
));
160 if (!xf86IsEntityPrimary(entityIndex
)) {
161 DebugF("Mapping high memory area\n");
162 if ((high_mem
= shmget(counter
++, HIGH_MEM_SIZE
,
163 IPC_CREAT
| SHM_R
| SHM_W
)) == -1) {
165 xf86DrvMsg(screen
, X_ERROR
, "shmget error\n Please reconfigure"
166 " your kernel to include System V IPC support\n");
168 xf86DrvMsg(screen
, X_ERROR
,
169 "shmget(highmem) error: %s\n", strerror(errno
));
174 DebugF("Mapping Video BIOS\n");
175 videoBiosMapped
= TRUE
;
176 if ((fd
= open(DEV_MEM
, O_RDWR
, 0)) >= 0) {
177 if ((vMem
= mmap((void *) (V_BIOS
), SYS_BIOS
- V_BIOS
,
178 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
179 MAP_SHARED
| MAP_FIXED
, fd
, V_BIOS
))
181 xf86DrvMsg(screen
, X_ERROR
, "Cannot map V_BIOS\n");
190 ((linuxInt10Priv
*) pInt
->private)->highMem
= high_mem
;
192 DebugF("Mapping 640kB area\n");
193 if ((low_mem
= shmget(counter
++, V_RAM
, IPC_CREAT
| SHM_R
| SHM_W
)) == -1) {
194 xf86DrvMsg(screen
, X_ERROR
,
195 "shmget(lowmem) error: %s\n", strerror(errno
));
199 ((linuxInt10Priv
*) pInt
->private)->lowMem
= low_mem
;
200 base
= shmat(low_mem
, 0, 0);
201 if (base
== SHMERRORPTR
) {
202 xf86DrvMsg(screen
, X_ERROR
,
203 "shmat(low_mem) error: %s\n", strerror(errno
));
206 ((linuxInt10Priv
*) pInt
->private)->base
= base
;
208 base_high
= shmat(high_mem
, 0, 0);
209 if (base_high
== SHMERRORPTR
) {
210 xf86DrvMsg(screen
, X_ERROR
,
211 "shmat(high_mem) error: %s\n", strerror(errno
));
214 ((linuxInt10Priv
*) pInt
->private)->base_high
= base_high
;
217 ((linuxInt10Priv
*) pInt
->private)->base_high
= NULL
;
219 if (!MapCurrentInt10(pInt
))
224 DebugF("Mapping int area\n");
225 if (xf86ReadBIOS(0, 0, (unsigned char *) 0, LOW_PAGE_SIZE
) < 0) {
226 xf86DrvMsg(screen
, X_ERROR
, "Cannot read int vect\n");
231 * Read in everything between V_BIOS and SYS_BIOS as some system BIOSes
232 * have executable code there. Note that xf86ReadBIOS() can only bring in
233 * 64K bytes at a time.
235 if (!videoBiosMapped
) {
236 memset((pointer
) V_BIOS
, 0, SYS_BIOS
- V_BIOS
);
237 DebugF("Reading BIOS\n");
238 for (cs
= V_BIOS
; cs
< SYS_BIOS
; cs
+= V_BIOS_SIZE
)
239 if (xf86ReadBIOS(cs
, 0, (pointer
) cs
, V_BIOS_SIZE
) < V_BIOS_SIZE
)
240 xf86DrvMsg(screen
, X_WARNING
,
241 "Unable to retrieve all of segment 0x%06lX.\n",
246 if (xf86IsEntityPrimary(entityIndex
) && !(initPrimary(options
))) {
247 if (!xf86int10GetBiosSegment(pInt
, NULL
))
250 set_return_trap(pInt
);
252 pInt
->Flags
= Flags
& (SET_BIOS_SCRATCH
| RESTORE_BIOS_SCRATCH
);
253 if (!(pInt
->Flags
& SET_BIOS_SCRATCH
))
254 pInt
->Flags
&= ~RESTORE_BIOS_SCRATCH
;
255 xf86Int10SaveRestoreBIOSVars(pInt
, TRUE
);
259 const BusType location_type
= xf86int10GetBiosLocationType(pInt
);
261 switch (location_type
) {
264 struct pci_device
*rom_device
=
265 xf86GetPciInfoForEntity(pInt
->entityIndex
);
267 pci_device_enable(rom_device
);
268 err
= pci_device_read_rom(rom_device
, (unsigned char *) (V_BIOS
));
270 xf86DrvMsg(screen
, X_ERROR
, "Cannot read V_BIOS (%s)\n",
275 pInt
->BIOSseg
= V_BIOS
>> 4;
283 reset_int_vect(pInt
);
284 set_return_trap(pInt
);
285 LockLegacyVGA(pInt
, &vga
);
286 xf86ExecX86int10(pInt
);
287 UnlockLegacyVGA(pInt
, &vga
);
290 dprint(0xc0000, 0x20);
302 shmdt((char *) HIGH_MEM
);
303 shmctl(low_mem
, IPC_RMID
, NULL
);
307 shmctl(high_mem
, IPC_RMID
, NULL
);
310 munmap(vMem
, SYS_BIOS
- V_BIOS
);
311 free(((linuxInt10Priv
*) pInt
->private)->alloc
);
320 MapCurrentInt10(xf86Int10InfoPtr pInt
)
327 if (((linuxInt10Priv
*) Int10Current
->private)->highMem
>= 0)
328 shmdt((char *) HIGH_MEM
);
330 munmap((pointer
) V_BIOS
, (SYS_BIOS
- V_BIOS
));
333 shmat(((linuxInt10Priv
*) pInt
->private)->lowMem
, (char *) 1, SHM_RND
);
334 if (addr
== SHMERRORPTR
) {
335 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
, "Cannot shmat() low memory\n");
336 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
,
337 "shmat(low_mem) error: %s\n", strerror(errno
));
340 if (mprotect((void *) 0, V_RAM
, PROT_READ
| PROT_WRITE
| PROT_EXEC
) != 0)
341 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
,
342 "Cannot set EXEC bit on low memory: %s\n", strerror(errno
));
344 if (((linuxInt10Priv
*) pInt
->private)->highMem
>= 0) {
345 addr
= shmat(((linuxInt10Priv
*) pInt
->private)->highMem
,
346 (char *) HIGH_MEM
, 0);
347 if (addr
== SHMERRORPTR
) {
348 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
,
349 "Cannot shmat() high memory\n");
350 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
,
351 "shmget error: %s\n", strerror(errno
));
354 if (mprotect((void *) HIGH_MEM
, HIGH_MEM_SIZE
,
355 PROT_READ
| PROT_WRITE
| PROT_EXEC
) != 0)
356 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
,
357 "Cannot set EXEC bit on high memory: %s\n",
361 if ((fd
= open(DEV_MEM
, O_RDWR
, 0)) >= 0) {
362 if (mmap((void *) (V_BIOS
), SYS_BIOS
- V_BIOS
,
363 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
364 MAP_SHARED
| MAP_FIXED
, fd
, V_BIOS
)
366 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
, "Cannot map V_BIOS\n");
372 xf86DrvMsg(pInt
->pScrn
->scrnIndex
, X_ERROR
, "Cannot open %s\n", DEV_MEM
);
382 xf86FreeInt10(xf86Int10InfoPtr pInt
)
388 xf86Int10SaveRestoreBIOSVars(pInt
, FALSE
);
390 if (Int10Current
== pInt
) {
392 if (((linuxInt10Priv
*) pInt
->private)->highMem
>= 0)
393 shmdt((char *) HIGH_MEM
);
395 munmap((pointer
) V_BIOS
, (SYS_BIOS
- V_BIOS
));
399 if (((linuxInt10Priv
*) pInt
->private)->base_high
)
400 shmdt(((linuxInt10Priv
*) pInt
->private)->base_high
);
401 shmdt(((linuxInt10Priv
*) pInt
->private)->base
);
402 shmctl(((linuxInt10Priv
*) pInt
->private)->lowMem
, IPC_RMID
, NULL
);
403 if (((linuxInt10Priv
*) pInt
->private)->highMem
>= 0)
404 shmctl(((linuxInt10Priv
*) pInt
->private)->highMem
, IPC_RMID
, NULL
);
405 free(((linuxInt10Priv
*) pInt
->private)->alloc
);
411 xf86Int10AllocPages(xf86Int10InfoPtr pInt
, int num
, int *off
)
413 int pagesize
= getpagesize();
414 int num_pages
= ALLOC_ENTRIES(pagesize
);
417 for (i
= 0; i
< (num_pages
- num
); i
++) {
418 if (((linuxInt10Priv
*) pInt
->private)->alloc
[i
] == 0) {
419 for (j
= i
; j
< (num
+ i
); j
++)
420 if ((((linuxInt10Priv
*) pInt
->private)->alloc
[j
] != 0))
428 if (i
== (num_pages
- num
))
431 for (j
= i
; j
< (i
+ num
); j
++)
432 ((linuxInt10Priv
*) pInt
->private)->alloc
[j
] = 1;
434 *off
= (i
+ 1) * pagesize
;
436 return ((linuxInt10Priv
*) pInt
->private)->base
+ ((i
+ 1) * pagesize
);
440 xf86Int10FreePages(xf86Int10InfoPtr pInt
, void *pbase
, int num
)
442 int pagesize
= getpagesize();
443 int first
= (((unsigned long) pbase
444 - (unsigned long) ((linuxInt10Priv
*) pInt
->private)->base
)
448 for (i
= first
; i
< (first
+ num
); i
++)
449 ((linuxInt10Priv
*) pInt
->private)->alloc
[i
] = 0;
453 read_b(xf86Int10InfoPtr pInt
, int addr
)
455 return *((CARD8
*) (memType
) addr
);
459 read_w(xf86Int10InfoPtr pInt
, int addr
)
461 return *((CARD16
*) (memType
) addr
);
465 read_l(xf86Int10InfoPtr pInt
, int addr
)
467 return *((CARD32
*) (memType
) addr
);
471 write_b(xf86Int10InfoPtr pInt
, int addr
, CARD8 val
)
473 *((CARD8
*) (memType
) addr
) = val
;
477 write_w(xf86Int10InfoPtr pInt
, int addr
, CARD16 val
)
479 *((CARD16
*) (memType
) addr
) = val
;
484 write_l(xf86Int10InfoPtr pInt
, int addr
, CARD32 val
)
486 *((CARD32
*) (memType
) addr
) = val
;
490 xf86int10Addr(xf86Int10InfoPtr pInt
, CARD32 addr
)
493 return ((linuxInt10Priv
*) pInt
->private)->base
+ addr
;
494 else if (addr
< V_BIOS
)
495 return (pointer
) (memType
) addr
;
496 else if (addr
< SYS_BIOS
) {
497 if (((linuxInt10Priv
*) pInt
->private)->base_high
)
498 return (pointer
) (((linuxInt10Priv
*) pInt
->private)->base_high
501 return (pointer
) (memType
) addr
;
504 return (pointer
) (memType
) addr
;
507 #if defined DoSubModules
515 /* When compiling with -fPIC, we can't use asm constraint "b" because
516 %ebx is already taken by gcc. */
517 __asm__
__volatile__("pushl %%ebx\n\t"
520 "int $0x80\n\t" "popl %%ebx":"=a"(__res
)
521 :"n"((int) 113), "r"(NULL
));
523 __asm__
__volatile__("int $0x80\n\t":"=a"(__res
):"a"((int) 113),
524 "b"((struct vm86_struct
*) NULL
));
527 if (__res
< 0 && __res
== -ENOSYS
)
533 static Int10LinuxSubModuleState
534 int10LinuxLoadSubModule(ScrnInfoPtr pScrn
)
537 if (xf86LoadSubModule(pScrn
, "vm86"))
538 return INT10_LOADED_VM86
;
540 if (xf86LoadSubModule(pScrn
, "x86emu"))
541 return INT10_LOADED_X86EMU
;
543 return INT10_LOAD_FAILED
;
546 #endif /* DoSubModules */