summaryrefslogtreecommitdiff
path: root/src/arch/amd64/drivers/bochs.c
blob: 1abb927f9c554b1f50160ec1abea8d5277cd7951 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <lib.h>
#include <memory.h>
#include <stdint.h>
#include <panic.h>
#include <pci.h>
#include <bochs.h>

#include "../bindings.h"

#define INDEX           0x1CE
#define DATA            0x1CF

#define INDEX_ID            0
#define INDEX_XRES          1
#define INDEX_YRES          2
#define INDEX_BPP           3
#define INDEX_ENABLE        4
#define INDEX_BANK          5
#define INDEX_VIRT_WIDTH    6
#define INDEX_VIRT_HEIGHT   7
#define INDEX_X_OFFSET      8
#define INDEX_Y_OFFSET      9

#define DATA_DISP_DISABLE   0x00
#define DATA_DISP_ENABLE    0x01
#define DATA_LFB_ENABLE     0x40
#define DATA_NO_CLEAR_MEM   0x80

#define BOCHS_PCI_VENDOR    0x1234
#define BOCHS_PCI_DEVICE    0x1111

static void write(uint16_t index, uint16_t data) {
    outw(INDEX, index);
    outw(DATA, data);
}

static uint16_t read(uint16_t value) {
    outw(INDEX, value);
    return inw(DATA);
}

static int is_available(void) {
    return (read(INDEX_ID) == 0xB0C5);
}

static void set_mode(uint16_t width, uint16_t height, uint16_t bit_depth, int lfb, int clear) {
    write(INDEX_ENABLE, DATA_DISP_DISABLE);
    write(INDEX_XRES, width);
    write(INDEX_YRES, height);
    write(INDEX_BPP, bit_depth);
    write(INDEX_ENABLE, DATA_DISP_ENABLE |
        (lfb ? DATA_LFB_ENABLE : 0) |
        (clear ? 0 : DATA_NO_CLEAR_MEM));
}

volatile uint32_t* bochs_init(uint16_t width, uint16_t height, uint8_t bit_depth) {

	set_mode(width, height, bit_depth, true, true);

	if (!is_available())
        return NULL;

    struct pci_device bochs = {0};
    bool found = pci_findby_id(&bochs, BOCHS_PCI_DEVICE, BOCHS_PCI_VENDOR, NULL);
    if (!found)
        return NULL;

    uint32_t bar0 = pci_rcfg_d(bochs, PCI_BAR0_D);
    uint32_t *addr = (uint32_t*) (uintptr_t) bar0;
    addr = mmap(addr, width * height * bit_depth);

    return addr;
}