~gerchanovsky/xorg-server/trusty

« back to all changes in this revision

Viewing changes to hw/xfree86/int10/generic.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2016-01-13 00:01:28 UTC
  • Revision ID: package-import@ubuntu.com-20160113000128-oc1wb1mr1zfjqlm5
Tags: upstream-1.17.2
ImportĀ upstreamĀ versionĀ 1.17.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *                   XFree86 int10 module
 
3
 *   execute BIOS int 10h calls in x86 real mode environment
 
4
 *                 Copyright 1999 Egbert Eich
 
5
 */
 
6
#ifdef HAVE_XORG_CONFIG_H
 
7
#include <xorg-config.h>
 
8
#endif
 
9
 
 
10
#include <string.h>
 
11
#include <unistd.h>
 
12
 
 
13
#include "xf86.h"
 
14
#include "xf86_OSproc.h"
 
15
#include "compiler.h"
 
16
#define _INT10_PRIVATE
 
17
#include "xf86int10.h"
 
18
#include "int10Defines.h"
 
19
#include "Pci.h"
 
20
 
 
21
#define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
 
22
 
 
23
#include <string.h>             /* needed for memmove */
 
24
 
 
25
static __inline__ uint32_t
 
26
ldl_u(uint32_t * p)
 
27
{
 
28
    uint32_t ret;
 
29
 
 
30
    memmove(&ret, p, sizeof(*p));
 
31
    return ret;
 
32
}
 
33
 
 
34
static __inline__ uint16_t
 
35
ldw_u(uint16_t * p)
 
36
{
 
37
    uint16_t ret;
 
38
 
 
39
    memmove(&ret, p, sizeof(*p));
 
40
    return ret;
 
41
}
 
42
 
 
43
static __inline__ void
 
44
stl_u(uint32_t val, uint32_t * p)
 
45
{
 
46
    uint32_t tmp = val;
 
47
 
 
48
    memmove(p, &tmp, sizeof(*p));
 
49
}
 
50
 
 
51
static __inline__ void
 
52
stw_u(uint16_t val, uint16_t * p)
 
53
{
 
54
    uint16_t tmp = val;
 
55
 
 
56
    memmove(p, &tmp, sizeof(*p));
 
57
}
 
58
 
 
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);
 
65
 
 
66
/*
 
67
 * the emulator cannot pass a pointer to the current xf86Int10InfoRec
 
68
 * to the memory access functions therefore store it here.
 
69
 */
 
70
 
 
71
typedef struct {
 
72
    int shift;
 
73
    int entries;
 
74
    void *base;
 
75
    void *vRam;
 
76
    int highMemory;
 
77
    void *sysMem;
 
78
    char *alloc;
 
79
} genericInt10Priv;
 
80
 
 
81
#define INTPriv(x) ((genericInt10Priv*)x->private)
 
82
 
 
83
int10MemRec genericMem = {
 
84
    read_b,
 
85
    read_w,
 
86
    read_l,
 
87
    write_b,
 
88
    write_w,
 
89
    write_l
 
90
};
 
91
 
 
92
static void MapVRam(xf86Int10InfoPtr pInt);
 
93
static void UnmapVRam(xf86Int10InfoPtr pInt);
 
94
 
 
95
#ifdef _PC
 
96
#define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \
 
97
                              * getpagesize())
 
98
#endif
 
99
 
 
100
static void *sysMem = NULL;
 
101
 
 
102
static Bool
 
103
readIntVec(struct pci_device *dev, unsigned char *buf, int len)
 
104
{
 
105
    void *map;
 
106
 
 
107
    if (pci_device_map_legacy(dev, 0, len, 0, &map))
 
108
        return FALSE;
 
109
 
 
110
    memcpy(buf, map, len);
 
111
    pci_device_unmap_legacy(dev, map, len);
 
112
 
 
113
    return TRUE;
 
114
}
 
115
 
 
116
xf86Int10InfoPtr
 
117
xf86ExtendedInitInt10(int entityIndex, int Flags)
 
118
{
 
119
    xf86Int10InfoPtr pInt;
 
120
    void *base = 0;
 
121
    void *vbiosMem = 0;
 
122
    void *options = NULL;
 
123
    legacyVGARec vga;
 
124
    ScrnInfoPtr pScrn;
 
125
 
 
126
    pScrn = xf86FindScreenForEntity(entityIndex);
 
127
 
 
128
    options = xf86HandleInt10Options(pScrn, entityIndex);
 
129
 
 
130
    if (int10skip(options)) {
 
131
        free(options);
 
132
        return NULL;
 
133
    }
 
134
 
 
135
    pInt = (xf86Int10InfoPtr) xnfcalloc(1, sizeof(xf86Int10InfoRec));
 
136
    pInt->entityIndex = entityIndex;
 
137
    if (!xf86Int10ExecSetup(pInt))
 
138
        goto error0;
 
139
    pInt->mem = &genericMem;
 
140
    pInt->private = (void *) xnfcalloc(1, sizeof(genericInt10Priv));
 
141
    INTPriv(pInt)->alloc = (void *) xnfcalloc(1, ALLOC_ENTRIES(getpagesize()));
 
142
    pInt->pScrn = pScrn;
 
143
    base = INTPriv(pInt)->base = xnfalloc(SYS_BIOS);
 
144
 
 
145
    /* FIXME: Shouldn't this be a failure case?  Leaving dev as NULL seems like
 
146
     * FIXME: an error
 
147
     */
 
148
    pInt->dev = xf86GetPciInfoForEntity(entityIndex);
 
149
 
 
150
    /*
 
151
     * we need to map video RAM MMIO as some chipsets map mmio
 
152
     * registers into this range.
 
153
     */
 
154
    MapVRam(pInt);
 
155
#ifdef _PC
 
156
    if (!sysMem)
 
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;
 
160
 
 
161
    if (!readIntVec(pInt->dev, base, LOW_PAGE_SIZE)) {
 
162
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read int vect\n");
 
163
        goto error1;
 
164
    }
 
165
 
 
166
    /*
 
167
     * Retrieve everything between V_BIOS and SYS_BIOS as some system BIOSes
 
168
     * have executable code there.
 
169
     */
 
170
    memset((char *) base + V_BIOS, 0, SYS_BIOS - V_BIOS);
 
171
    INTPriv(pInt)->highMemory = V_BIOS;
 
172
 
 
173
    if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) {
 
174
        if (!xf86int10GetBiosSegment(pInt, (unsigned char *) sysMem - V_BIOS))
 
175
            goto error1;
 
176
 
 
177
        set_return_trap(pInt);
 
178
 
 
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);
 
183
 
 
184
    }
 
185
    else {
 
186
        const BusType location_type = xf86int10GetBiosLocationType(pInt);
 
187
        int bios_location = V_BIOS;
 
188
 
 
189
        reset_int_vect(pInt);
 
190
        set_return_trap(pInt);
 
191
 
 
192
        switch (location_type) {
 
193
        case BUS_PCI:{
 
194
            int err;
 
195
            struct pci_device *rom_device =
 
196
                xf86GetPciInfoForEntity(pInt->entityIndex);
 
197
 
 
198
            vbiosMem = (unsigned char *) base + bios_location;
 
199
            err = pci_device_read_rom(rom_device, vbiosMem);
 
200
            if (err) {
 
201
                xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (3) %s\n",
 
202
                           strerror(err));
 
203
                goto error1;
 
204
            }
 
205
            INTPriv(pInt)->highMemory = GET_HIGH_BASE(rom_device->rom_size);
 
206
            break;
 
207
        }
 
208
        default:
 
209
            goto error1;
 
210
        }
 
211
        pInt->BIOSseg = V_BIOS >> 4;
 
212
        pInt->num = 0xe6;
 
213
        LockLegacyVGA(pInt, &vga);
 
214
        xf86ExecX86int10(pInt);
 
215
        UnlockLegacyVGA(pInt, &vga);
 
216
    }
 
217
#else
 
218
    if (!sysMem) {
 
219
        sysMem = xnfalloc(BIOS_SIZE);
 
220
        setup_system_bios(sysMem);
 
221
    }
 
222
    INTPriv(pInt)->sysMem = sysMem;
 
223
    setup_int_vect(pInt);
 
224
    set_return_trap(pInt);
 
225
 
 
226
    /* Retrieve the entire legacy video BIOS segment.  This can be upto
 
227
     * 128KiB.
 
228
     */
 
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");
 
235
    }
 
236
 
 
237
    /*
 
238
     * If this adapter is the primary, use its post-init BIOS (if we can find
 
239
     * it).
 
240
     */
 
241
    {
 
242
        int bios_location = V_BIOS;
 
243
        Bool done = FALSE;
 
244
 
 
245
        vbiosMem = (unsigned char *) base + bios_location;
 
246
 
 
247
        if (xf86IsEntityPrimary(entityIndex)) {
 
248
            if (int10_check_bios(pScrn->scrnIndex, bios_location >> 4, vbiosMem))
 
249
                done = TRUE;
 
250
            else
 
251
                xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 
252
                           "No legacy BIOS found -- trying PCI\n");
 
253
        }
 
254
        if (!done) {
 
255
            int err;
 
256
            struct pci_device *rom_device =
 
257
                xf86GetPciInfoForEntity(pInt->entityIndex);
 
258
 
 
259
            err = pci_device_read_rom(rom_device, vbiosMem);
 
260
            if (err) {
 
261
                xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (5) %s\n",
 
262
                           strerror(err));
 
263
                goto error1;
 
264
            }
 
265
        }
 
266
    }
 
267
 
 
268
    pInt->BIOSseg = V_BIOS >> 4;
 
269
    pInt->num = 0xe6;
 
270
    LockLegacyVGA(pInt, &vga);
 
271
    xf86ExecX86int10(pInt);
 
272
    UnlockLegacyVGA(pInt, &vga);
 
273
#endif
 
274
    free(options);
 
275
    return pInt;
 
276
 
 
277
 error1:
 
278
    free(base);
 
279
    UnmapVRam(pInt);
 
280
    free(INTPriv(pInt)->alloc);
 
281
    free(pInt->private);
 
282
 error0:
 
283
    free(pInt);
 
284
    free(options);
 
285
 
 
286
    return NULL;
 
287
}
 
288
 
 
289
static void
 
290
MapVRam(xf86Int10InfoPtr pInt)
 
291
{
 
292
    int pagesize = getpagesize();
 
293
    int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
 
294
 
 
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);
 
298
}
 
299
 
 
300
static void
 
301
UnmapVRam(xf86Int10InfoPtr pInt)
 
302
{
 
303
    int pagesize = getpagesize();
 
304
    int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
 
305
 
 
306
    pci_device_unmap_legacy(pInt->dev, INTPriv(pInt)->vRam, size);
 
307
    pci_device_close_io(pInt->dev, pInt->io);
 
308
    pInt->io = NULL;
 
309
}
 
310
 
 
311
Bool
 
312
MapCurrentInt10(xf86Int10InfoPtr pInt)
 
313
{
 
314
    /* nothing to do here */
 
315
    return TRUE;
 
316
}
 
317
 
 
318
void
 
319
xf86FreeInt10(xf86Int10InfoPtr pInt)
 
320
{
 
321
    if (!pInt)
 
322
        return;
 
323
#if defined (_PC)
 
324
    xf86Int10SaveRestoreBIOSVars(pInt, FALSE);
 
325
#endif
 
326
    if (Int10Current == pInt)
 
327
        Int10Current = NULL;
 
328
    free(INTPriv(pInt)->base);
 
329
    UnmapVRam(pInt);
 
330
    free(INTPriv(pInt)->alloc);
 
331
    free(pInt->private);
 
332
    free(pInt);
 
333
}
 
334
 
 
335
void *
 
336
xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off)
 
337
{
 
338
    int pagesize = getpagesize();
 
339
    int num_pages = ALLOC_ENTRIES(pagesize);
 
340
    int i, j;
 
341
 
 
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)
 
346
                    break;
 
347
            if (j == (num + i))
 
348
                break;
 
349
            i += num;
 
350
        }
 
351
    }
 
352
    if (i == (num_pages - num))
 
353
        return NULL;
 
354
 
 
355
    for (j = i; j < (i + num); j++)
 
356
        INTPriv(pInt)->alloc[j] = 1;
 
357
 
 
358
    *off = (i + 1) * pagesize;
 
359
 
 
360
    return (char *) INTPriv(pInt)->base + *off;
 
361
}
 
362
 
 
363
void
 
364
xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
 
365
{
 
366
    int pagesize = getpagesize();
 
367
    int first =
 
368
        (((char *) pbase - (char *) INTPriv(pInt)->base) / pagesize) - 1;
 
369
    int i;
 
370
 
 
371
    for (i = first; i < (first + num); i++)
 
372
        INTPriv(pInt)->alloc[i] = 0;
 
373
}
 
374
 
 
375
#define OFF(addr) ((addr) & 0xffff)
 
376
#if defined _PC
 
377
#define HIGH_OFFSET (INTPriv(pInt)->highMemory)
 
378
#define HIGH_BASE   V_BIOS
 
379
#else
 
380
#define HIGH_OFFSET SYS_BIOS
 
381
#define HIGH_BASE   SYS_BIOS
 
382
#endif
 
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)
 
389
 
 
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))
 
400
 
 
401
#define V_ADDR_WB(addr,val) \
 
402
        if(VRAM(addr)) \
 
403
            MMIO_OUT8((uint8_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
 
404
        else \
 
405
            *(uint8_t*) V_ADDR(addr) = val;
 
406
#define V_ADDR_WW(addr,val) \
 
407
        if(VRAM(addr)) \
 
408
            MMIO_OUT16((uint16_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
 
409
        else \
 
410
            stw_u((val),(void *)(V_ADDR(addr)));
 
411
 
 
412
#define V_ADDR_WL(addr,val) \
 
413
        if (VRAM(addr)) \
 
414
            MMIO_OUT32((uint32_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
 
415
        else \
 
416
            stl_u(val,(void *)(V_ADDR(addr)));
 
417
 
 
418
static uint8_t
 
419
read_b(xf86Int10InfoPtr pInt, int addr)
 
420
{
 
421
    return V_ADDR_RB(addr);
 
422
}
 
423
 
 
424
static uint16_t
 
425
read_w(xf86Int10InfoPtr pInt, int addr)
 
426
{
 
427
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
 
428
    if (OFF(addr + 1) > 0)
 
429
        return V_ADDR_RW(addr);
 
430
#endif
 
431
    return V_ADDR_RB(addr) | (V_ADDR_RB(addr + 1) << 8);
 
432
}
 
433
 
 
434
static uint32_t
 
435
read_l(xf86Int10InfoPtr pInt, int addr)
 
436
{
 
437
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
 
438
    if (OFF(addr + 3) > 2)
 
439
        return V_ADDR_RL(addr);
 
440
#endif
 
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);
 
444
}
 
445
 
 
446
static void
 
447
write_b(xf86Int10InfoPtr pInt, int addr, uint8_t val)
 
448
{
 
449
    V_ADDR_WB(addr, val);
 
450
}
 
451
 
 
452
static void
 
453
write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val)
 
454
{
 
455
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
 
456
    if (OFF(addr + 1) > 0) {
 
457
        V_ADDR_WW(addr, val);
 
458
    }
 
459
#endif
 
460
    V_ADDR_WB(addr, val);
 
461
    V_ADDR_WB(addr + 1, val >> 8);
 
462
}
 
463
 
 
464
static void
 
465
write_l(xf86Int10InfoPtr pInt, int addr, uint32_t val)
 
466
{
 
467
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
 
468
    if (OFF(addr + 3) > 2) {
 
469
        V_ADDR_WL(addr, val);
 
470
    }
 
471
#endif
 
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);
 
476
}
 
477
 
 
478
void *
 
479
xf86int10Addr(xf86Int10InfoPtr pInt, uint32_t addr)
 
480
{
 
481
    return V_ADDR(addr);
 
482
}