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
#include <string.h> /* needed for memmove */
25
static __inline__ uint32_t
30
memmove(&ret, p, sizeof(*p));
34
static __inline__ uint16_t
39
memmove(&ret, p, sizeof(*p));
43
static __inline__ void
44
stl_u(uint32_t val, uint32_t * p)
48
memmove(p, &tmp, sizeof(*p));
51
static __inline__ void
52
stw_u(uint16_t val, uint16_t * p)
56
memmove(p, &tmp, sizeof(*p));
59
static uint8_t read_b(xf86Int10InfoPtr pInt, int addr);
60
static uint16_t read_w(xf86Int10InfoPtr pInt, int addr);
61
static uint32_t read_l(xf86Int10InfoPtr pInt, int addr);
62
static void write_b(xf86Int10InfoPtr pInt, int addr, uint8_t val);
63
static void write_w(xf86Int10InfoPtr pInt, int addr, uint16_t val);
64
static void write_l(xf86Int10InfoPtr pInt, int addr, uint32_t val);
67
* the emulator cannot pass a pointer to the current xf86Int10InfoRec
68
* to the memory access functions therefore store it here.
81
#define INTPriv(x) ((genericInt10Priv*)x->private)
83
int10MemRec genericMem = {
92
static void MapVRam(xf86Int10InfoPtr pInt);
93
static void UnmapVRam(xf86Int10InfoPtr pInt);
96
#define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \
100
static void *sysMem = NULL;
103
readIntVec(struct pci_device *dev, unsigned char *buf, int len)
107
if (pci_device_map_legacy(dev, 0, len, 0, &map))
110
memcpy(buf, map, len);
111
pci_device_unmap_legacy(dev, map, len);
117
xf86ExtendedInitInt10(int entityIndex, int Flags)
119
xf86Int10InfoPtr pInt;
122
void *options = NULL;
126
pScrn = xf86FindScreenForEntity(entityIndex);
128
options = xf86HandleInt10Options(pScrn, entityIndex);
130
if (int10skip(options)) {
135
pInt = (xf86Int10InfoPtr) xnfcalloc(1, sizeof(xf86Int10InfoRec));
136
pInt->entityIndex = entityIndex;
137
if (!xf86Int10ExecSetup(pInt))
139
pInt->mem = &genericMem;
140
pInt->private = (void *) xnfcalloc(1, sizeof(genericInt10Priv));
141
INTPriv(pInt)->alloc = (void *) xnfcalloc(1, ALLOC_ENTRIES(getpagesize()));
143
base = INTPriv(pInt)->base = xnfalloc(SYS_BIOS);
145
/* FIXME: Shouldn't this be a failure case? Leaving dev as NULL seems like
148
pInt->dev = xf86GetPciInfoForEntity(entityIndex);
151
* we need to map video RAM MMIO as some chipsets map mmio
152
* registers into this range.
157
pci_device_map_legacy(pInt->dev, V_BIOS, BIOS_SIZE + SYS_BIOS - V_BIOS,
158
PCI_DEV_MAP_FLAG_WRITABLE, &sysMem);
159
INTPriv(pInt)->sysMem = sysMem;
161
if (!readIntVec(pInt->dev, base, LOW_PAGE_SIZE)) {
162
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read int vect\n");
167
* Retrieve everything between V_BIOS and SYS_BIOS as some system BIOSes
168
* have executable code there.
170
memset((char *) base + V_BIOS, 0, SYS_BIOS - V_BIOS);
171
INTPriv(pInt)->highMemory = V_BIOS;
173
if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) {
174
if (!xf86int10GetBiosSegment(pInt, (unsigned char *) sysMem - V_BIOS))
177
set_return_trap(pInt);
179
pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
180
if (!(pInt->Flags & SET_BIOS_SCRATCH))
181
pInt->Flags &= ~RESTORE_BIOS_SCRATCH;
182
xf86Int10SaveRestoreBIOSVars(pInt, TRUE);
186
const BusType location_type = xf86int10GetBiosLocationType(pInt);
187
int bios_location = V_BIOS;
189
reset_int_vect(pInt);
190
set_return_trap(pInt);
192
switch (location_type) {
195
struct pci_device *rom_device =
196
xf86GetPciInfoForEntity(pInt->entityIndex);
198
vbiosMem = (unsigned char *) base + bios_location;
199
err = pci_device_read_rom(rom_device, vbiosMem);
201
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (3) %s\n",
205
INTPriv(pInt)->highMemory = GET_HIGH_BASE(rom_device->rom_size);
211
pInt->BIOSseg = V_BIOS >> 4;
213
LockLegacyVGA(pInt, &vga);
214
xf86ExecX86int10(pInt);
215
UnlockLegacyVGA(pInt, &vga);
219
sysMem = xnfalloc(BIOS_SIZE);
220
setup_system_bios(sysMem);
222
INTPriv(pInt)->sysMem = sysMem;
223
setup_int_vect(pInt);
224
set_return_trap(pInt);
226
/* Retrieve the entire legacy video BIOS segment. This can be upto
229
vbiosMem = (char *) base + V_BIOS;
230
memset(vbiosMem, 0, 2 * V_BIOS_SIZE);
231
if (pci_device_read_rom(pInt->dev, vbiosMem) != 0
232
|| pInt->dev->rom_size < V_BIOS_SIZE) {
233
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
234
"Unable to retrieve all of segment 0x0C0000.\n");
238
* If this adapter is the primary, use its post-init BIOS (if we can find
242
int bios_location = V_BIOS;
245
vbiosMem = (unsigned char *) base + bios_location;
247
if (xf86IsEntityPrimary(entityIndex)) {
248
if (int10_check_bios(pScrn->scrnIndex, bios_location >> 4, vbiosMem))
251
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
252
"No legacy BIOS found -- trying PCI\n");
256
struct pci_device *rom_device =
257
xf86GetPciInfoForEntity(pInt->entityIndex);
259
err = pci_device_read_rom(rom_device, vbiosMem);
261
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (5) %s\n",
268
pInt->BIOSseg = V_BIOS >> 4;
270
LockLegacyVGA(pInt, &vga);
271
xf86ExecX86int10(pInt);
272
UnlockLegacyVGA(pInt, &vga);
280
free(INTPriv(pInt)->alloc);
290
MapVRam(xf86Int10InfoPtr pInt)
292
int pagesize = getpagesize();
293
int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
295
pci_device_map_legacy(pInt->dev, V_RAM, size, PCI_DEV_MAP_FLAG_WRITABLE,
296
&(INTPriv(pInt)->vRam));
297
pInt->io = pci_legacy_open_io(pInt->dev, 0, 64 * 1024);
301
UnmapVRam(xf86Int10InfoPtr pInt)
303
int pagesize = getpagesize();
304
int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
306
pci_device_unmap_legacy(pInt->dev, INTPriv(pInt)->vRam, size);
307
pci_device_close_io(pInt->dev, pInt->io);
312
MapCurrentInt10(xf86Int10InfoPtr pInt)
314
/* nothing to do here */
319
xf86FreeInt10(xf86Int10InfoPtr pInt)
324
xf86Int10SaveRestoreBIOSVars(pInt, FALSE);
326
if (Int10Current == pInt)
328
free(INTPriv(pInt)->base);
330
free(INTPriv(pInt)->alloc);
336
xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off)
338
int pagesize = getpagesize();
339
int num_pages = ALLOC_ENTRIES(pagesize);
342
for (i = 0; i < (num_pages - num); i++) {
343
if (INTPriv(pInt)->alloc[i] == 0) {
344
for (j = i; j < (num + i); j++)
345
if (INTPriv(pInt)->alloc[j] != 0)
352
if (i == (num_pages - num))
355
for (j = i; j < (i + num); j++)
356
INTPriv(pInt)->alloc[j] = 1;
358
*off = (i + 1) * pagesize;
360
return (char *) INTPriv(pInt)->base + *off;
364
xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
366
int pagesize = getpagesize();
368
(((char *) pbase - (char *) INTPriv(pInt)->base) / pagesize) - 1;
371
for (i = first; i < (first + num); i++)
372
INTPriv(pInt)->alloc[i] = 0;
375
#define OFF(addr) ((addr) & 0xffff)
377
#define HIGH_OFFSET (INTPriv(pInt)->highMemory)
378
#define HIGH_BASE V_BIOS
380
#define HIGH_OFFSET SYS_BIOS
381
#define HIGH_BASE SYS_BIOS
383
#define SYS(addr) ((addr) >= HIGH_OFFSET)
384
#define V_ADDR(addr) \
385
(SYS(addr) ? ((char*)INTPriv(pInt)->sysMem) + (addr - HIGH_BASE) \
386
: (((char*)(INTPriv(pInt)->base) + addr)))
387
#define VRAM_ADDR(addr) (addr - V_RAM)
388
#define VRAM_BASE (INTPriv(pInt)->vRam)
390
#define VRAM(addr) ((addr >= V_RAM) && (addr < (V_RAM + VRAM_SIZE)))
391
#define V_ADDR_RB(addr) \
392
(VRAM(addr)) ? MMIO_IN8((uint8_t*)VRAM_BASE,VRAM_ADDR(addr)) \
393
: *(uint8_t*) V_ADDR(addr)
394
#define V_ADDR_RW(addr) \
395
(VRAM(addr)) ? MMIO_IN16((uint16_t*)VRAM_BASE,VRAM_ADDR(addr)) \
396
: ldw_u((void *)V_ADDR(addr))
397
#define V_ADDR_RL(addr) \
398
(VRAM(addr)) ? MMIO_IN32((uint32_t*)VRAM_BASE,VRAM_ADDR(addr)) \
399
: ldl_u((void *)V_ADDR(addr))
401
#define V_ADDR_WB(addr,val) \
403
MMIO_OUT8((uint8_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
405
*(uint8_t*) V_ADDR(addr) = val;
406
#define V_ADDR_WW(addr,val) \
408
MMIO_OUT16((uint16_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
410
stw_u((val),(void *)(V_ADDR(addr)));
412
#define V_ADDR_WL(addr,val) \
414
MMIO_OUT32((uint32_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
416
stl_u(val,(void *)(V_ADDR(addr)));
419
read_b(xf86Int10InfoPtr pInt, int addr)
421
return V_ADDR_RB(addr);
425
read_w(xf86Int10InfoPtr pInt, int addr)
427
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
428
if (OFF(addr + 1) > 0)
429
return V_ADDR_RW(addr);
431
return V_ADDR_RB(addr) | (V_ADDR_RB(addr + 1) << 8);
435
read_l(xf86Int10InfoPtr pInt, int addr)
437
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
438
if (OFF(addr + 3) > 2)
439
return V_ADDR_RL(addr);
441
return V_ADDR_RB(addr) |
442
(V_ADDR_RB(addr + 1) << 8) |
443
(V_ADDR_RB(addr + 2) << 16) | (V_ADDR_RB(addr + 3) << 24);
447
write_b(xf86Int10InfoPtr pInt, int addr, uint8_t val)
449
V_ADDR_WB(addr, val);
453
write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val)
455
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
456
if (OFF(addr + 1) > 0) {
457
V_ADDR_WW(addr, val);
460
V_ADDR_WB(addr, val);
461
V_ADDR_WB(addr + 1, val >> 8);
465
write_l(xf86Int10InfoPtr pInt, int addr, uint32_t val)
467
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
468
if (OFF(addr + 3) > 2) {
469
V_ADDR_WL(addr, val);
472
V_ADDR_WB(addr, val);
473
V_ADDR_WB(addr + 1, val >> 8);
474
V_ADDR_WB(addr + 2, val >> 16);
475
V_ADDR_WB(addr + 3, val >> 24);
479
xf86int10Addr(xf86Int10InfoPtr pInt, uint32_t addr)