3 * execute BIOS int 10h calls in x86 real mode environment
4 * Copyright 1999 Egbert Eich
6 #ifdef HAVE_XORG_CONFIG_H
7 #include <xorg-config.h>
14 #include "xf86_OSproc.h"
16 #define _INT10_PRIVATE
17 #include "xf86int10.h"
18 #include "int10Defines.h"
21 #define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
23 static CARD8
read_b(xf86Int10InfoPtr pInt
, int addr
);
24 static CARD16
read_w(xf86Int10InfoPtr pInt
, int addr
);
25 static CARD32
read_l(xf86Int10InfoPtr pInt
, int addr
);
26 static void write_b(xf86Int10InfoPtr pInt
, int addr
, CARD8 val
);
27 static void write_w(xf86Int10InfoPtr pInt
, int addr
, CARD16 val
);
28 static void write_l(xf86Int10InfoPtr pInt
, int addr
, CARD32 val
);
31 * the emulator cannot pass a pointer to the current xf86Int10InfoRec
32 * to the memory access functions therefore store it here.
45 #define INTPriv(x) ((genericInt10Priv*)x->private)
47 int10MemRec genericMem
= {
56 static void MapVRam(xf86Int10InfoPtr pInt
);
57 static void UnmapVRam(xf86Int10InfoPtr pInt
);
60 #define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \
64 static void *sysMem
= NULL
;
67 xf86ExtendedInitInt10(int entityIndex
, int Flags
)
69 xf86Int10InfoPtr pInt
;
76 pScrn
= xf86FindScreenForEntity(entityIndex
);
78 options
= xf86HandleInt10Options(pScrn
, entityIndex
);
80 if (int10skip(options
)) {
85 pInt
= (xf86Int10InfoPtr
) xnfcalloc(1, sizeof(xf86Int10InfoRec
));
86 pInt
->entityIndex
= entityIndex
;
87 if (!xf86Int10ExecSetup(pInt
))
89 pInt
->mem
= &genericMem
;
90 pInt
->private = (pointer
) xnfcalloc(1, sizeof(genericInt10Priv
));
91 INTPriv(pInt
)->alloc
= (pointer
) xnfcalloc(1, ALLOC_ENTRIES(getpagesize()));
93 base
= INTPriv(pInt
)->base
= xnfalloc(SYS_BIOS
);
95 /* FIXME: Shouldn't this be a failure case? Leaving dev as NULL seems like
98 pInt
->dev
= xf86GetPciInfoForEntity(entityIndex
);
101 * we need to map video RAM MMIO as some chipsets map mmio
102 * registers into this range.
107 pci_device_map_legacy(pInt
->dev
, V_BIOS
, BIOS_SIZE
+ SYS_BIOS
- V_BIOS
,
108 PCI_DEV_MAP_FLAG_WRITABLE
, &sysMem
);
109 INTPriv(pInt
)->sysMem
= sysMem
;
111 if (xf86ReadBIOS(0, 0, base
, LOW_PAGE_SIZE
) < 0) {
112 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "Cannot read int vect\n");
117 * Retrieve everything between V_BIOS and SYS_BIOS as some system BIOSes
118 * have executable code there.
120 memset((char *) base
+ V_BIOS
, 0, SYS_BIOS
- V_BIOS
);
121 INTPriv(pInt
)->highMemory
= V_BIOS
;
123 if (xf86IsEntityPrimary(entityIndex
) && !(initPrimary(options
))) {
124 if (!xf86int10GetBiosSegment(pInt
, (unsigned char *) sysMem
- V_BIOS
))
127 set_return_trap(pInt
);
129 pInt
->Flags
= Flags
& (SET_BIOS_SCRATCH
| RESTORE_BIOS_SCRATCH
);
130 if (!(pInt
->Flags
& SET_BIOS_SCRATCH
))
131 pInt
->Flags
&= ~RESTORE_BIOS_SCRATCH
;
132 xf86Int10SaveRestoreBIOSVars(pInt
, TRUE
);
136 const BusType location_type
= xf86int10GetBiosLocationType(pInt
);
137 int bios_location
= V_BIOS
;
139 reset_int_vect(pInt
);
140 set_return_trap(pInt
);
142 switch (location_type
) {
145 struct pci_device
*rom_device
=
146 xf86GetPciInfoForEntity(pInt
->entityIndex
);
148 vbiosMem
= (unsigned char *) base
+ bios_location
;
149 err
= pci_device_read_rom(rom_device
, vbiosMem
);
151 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "Cannot read V_BIOS (3) %s\n",
155 INTPriv(pInt
)->highMemory
= GET_HIGH_BASE(rom_device
->rom_size
);
161 pInt
->BIOSseg
= V_BIOS
>> 4;
163 LockLegacyVGA(pInt
, &vga
);
164 xf86ExecX86int10(pInt
);
165 UnlockLegacyVGA(pInt
, &vga
);
169 sysMem
= xnfalloc(BIOS_SIZE
);
170 setup_system_bios(sysMem
);
172 INTPriv(pInt
)->sysMem
= sysMem
;
173 setup_int_vect(pInt
);
174 set_return_trap(pInt
);
176 /* Retrieve the entire legacy video BIOS segment. This can be upto
179 vbiosMem
= (char *) base
+ V_BIOS
;
180 memset(vbiosMem
, 0, 2 * V_BIOS_SIZE
);
181 if (pci_device_read_rom(pInt
->dev
, vbiosMem
) != 0
182 || pInt
->dev
->rom_size
< V_BIOS_SIZE
) {
183 xf86DrvMsg(pScrn
->scrnIndex
, X_WARNING
,
184 "Unable to retrieve all of segment 0x0C0000.\n");
188 * If this adapter is the primary, use its post-init BIOS (if we can find
192 int bios_location
= V_BIOS
;
195 vbiosMem
= (unsigned char *) base
+ bios_location
;
197 if (xf86IsEntityPrimary(entityIndex
)) {
198 if (int10_check_bios(pScrn
->scrnIndex
, bios_location
>> 4, vbiosMem
))
201 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
202 "No legacy BIOS found -- trying PCI\n");
206 struct pci_device
*rom_device
=
207 xf86GetPciInfoForEntity(pInt
->entityIndex
);
209 err
= pci_device_read_rom(rom_device
, vbiosMem
);
211 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
, "Cannot read V_BIOS (5) %s\n",
218 pInt
->BIOSseg
= V_BIOS
>> 4;
220 LockLegacyVGA(pInt
, &vga
);
221 xf86ExecX86int10(pInt
);
222 UnlockLegacyVGA(pInt
, &vga
);
230 free(INTPriv(pInt
)->alloc
);
240 MapVRam(xf86Int10InfoPtr pInt
)
242 int pagesize
= getpagesize();
243 int size
= ((VRAM_SIZE
+ pagesize
- 1) / pagesize
) * pagesize
;
245 pci_device_map_legacy(pInt
->dev
, V_RAM
, size
, PCI_DEV_MAP_FLAG_WRITABLE
,
246 &(INTPriv(pInt
)->vRam
));
247 pInt
->io
= pci_legacy_open_io(pInt
->dev
, 0, 64 * 1024);
251 UnmapVRam(xf86Int10InfoPtr pInt
)
253 int pagesize
= getpagesize();
254 int size
= ((VRAM_SIZE
+ pagesize
- 1) / pagesize
) * pagesize
;
256 pci_device_unmap_legacy(pInt
->dev
, INTPriv(pInt
)->vRam
, size
);
257 pci_device_close_io(pInt
->dev
, pInt
->io
);
262 MapCurrentInt10(xf86Int10InfoPtr pInt
)
264 /* nothing to do here */
269 xf86FreeInt10(xf86Int10InfoPtr pInt
)
274 xf86Int10SaveRestoreBIOSVars(pInt
, FALSE
);
276 if (Int10Current
== pInt
)
278 free(INTPriv(pInt
)->base
);
280 free(INTPriv(pInt
)->alloc
);
286 xf86Int10AllocPages(xf86Int10InfoPtr pInt
, int num
, int *off
)
288 int pagesize
= getpagesize();
289 int num_pages
= ALLOC_ENTRIES(pagesize
);
292 for (i
= 0; i
< (num_pages
- num
); i
++) {
293 if (INTPriv(pInt
)->alloc
[i
] == 0) {
294 for (j
= i
; j
< (num
+ i
); j
++)
295 if (INTPriv(pInt
)->alloc
[j
] != 0)
302 if (i
== (num_pages
- num
))
305 for (j
= i
; j
< (i
+ num
); j
++)
306 INTPriv(pInt
)->alloc
[j
] = 1;
308 *off
= (i
+ 1) * pagesize
;
310 return (char *) INTPriv(pInt
)->base
+ *off
;
314 xf86Int10FreePages(xf86Int10InfoPtr pInt
, void *pbase
, int num
)
316 int pagesize
= getpagesize();
318 (((char *) pbase
- (char *) INTPriv(pInt
)->base
) / pagesize
) - 1;
321 for (i
= first
; i
< (first
+ num
); i
++)
322 INTPriv(pInt
)->alloc
[i
] = 0;
325 #define OFF(addr) ((addr) & 0xffff)
327 #define HIGH_OFFSET (INTPriv(pInt)->highMemory)
328 #define HIGH_BASE V_BIOS
330 #define HIGH_OFFSET SYS_BIOS
331 #define HIGH_BASE SYS_BIOS
333 #define SYS(addr) ((addr) >= HIGH_OFFSET)
334 #define V_ADDR(addr) \
335 (SYS(addr) ? ((char*)INTPriv(pInt)->sysMem) + (addr - HIGH_BASE) \
336 : (((char*)(INTPriv(pInt)->base) + addr)))
337 #define VRAM_ADDR(addr) (addr - V_RAM)
338 #define VRAM_BASE (INTPriv(pInt)->vRam)
340 #define VRAM(addr) ((addr >= V_RAM) && (addr < (V_RAM + VRAM_SIZE)))
341 #define V_ADDR_RB(addr) \
342 (VRAM(addr)) ? MMIO_IN8((CARD8*)VRAM_BASE,VRAM_ADDR(addr)) \
343 : *(CARD8*) V_ADDR(addr)
344 #define V_ADDR_RW(addr) \
345 (VRAM(addr)) ? MMIO_IN16((CARD16*)VRAM_BASE,VRAM_ADDR(addr)) \
346 : ldw_u((pointer)V_ADDR(addr))
347 #define V_ADDR_RL(addr) \
348 (VRAM(addr)) ? MMIO_IN32((CARD32*)VRAM_BASE,VRAM_ADDR(addr)) \
349 : ldl_u((pointer)V_ADDR(addr))
351 #define V_ADDR_WB(addr,val) \
353 MMIO_OUT8((CARD8*)VRAM_BASE,VRAM_ADDR(addr),val); \
355 *(CARD8*) V_ADDR(addr) = val;
356 #define V_ADDR_WW(addr,val) \
358 MMIO_OUT16((CARD16*)VRAM_BASE,VRAM_ADDR(addr),val); \
360 stw_u((val),(pointer)(V_ADDR(addr)));
362 #define V_ADDR_WL(addr,val) \
364 MMIO_OUT32((CARD32*)VRAM_BASE,VRAM_ADDR(addr),val); \
366 stl_u(val,(pointer)(V_ADDR(addr)));
369 read_b(xf86Int10InfoPtr pInt
, int addr
)
371 return V_ADDR_RB(addr
);
375 read_w(xf86Int10InfoPtr pInt
, int addr
)
377 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
378 if (OFF(addr
+ 1) > 0)
379 return V_ADDR_RW(addr
);
381 return V_ADDR_RB(addr
) | (V_ADDR_RB(addr
+ 1) << 8);
385 read_l(xf86Int10InfoPtr pInt
, int addr
)
387 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
388 if (OFF(addr
+ 3) > 2)
389 return V_ADDR_RL(addr
);
391 return V_ADDR_RB(addr
) |
392 (V_ADDR_RB(addr
+ 1) << 8) |
393 (V_ADDR_RB(addr
+ 2) << 16) | (V_ADDR_RB(addr
+ 3) << 24);
397 write_b(xf86Int10InfoPtr pInt
, int addr
, CARD8 val
)
399 V_ADDR_WB(addr
, val
);
403 write_w(xf86Int10InfoPtr pInt
, int addr
, CARD16 val
)
405 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
406 if (OFF(addr
+ 1) > 0) {
407 V_ADDR_WW(addr
, val
);
410 V_ADDR_WB(addr
, val
);
411 V_ADDR_WB(addr
+ 1, val
>> 8);
415 write_l(xf86Int10InfoPtr pInt
, int addr
, CARD32 val
)
417 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
418 if (OFF(addr
+ 3) > 2) {
419 V_ADDR_WL(addr
, val
);
422 V_ADDR_WB(addr
, val
);
423 V_ADDR_WB(addr
+ 1, val
>> 8);
424 V_ADDR_WB(addr
+ 2, val
>> 16);
425 V_ADDR_WB(addr
+ 3, val
>> 24);
429 xf86int10Addr(xf86Int10InfoPtr pInt
, CARD32 addr
)