Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6084 serge 1
#include 
2
#include 
3
 
4
typedef unsigned int addr_t;
5
 
6
#define ACPI_NAME_SIZE                  4
7
#define ACPI_OEM_ID_SIZE                6
8
#define ACPI_OEM_TABLE_ID_SIZE          8
9
 
10
#define ACPI_RSDP_CHECKSUM_LENGTH       20
11
#define ACPI_RSDP_XCHECKSUM_LENGTH      36
12
 
13
typedef struct __attribute__((packed))
14
{
15
    u32           sig;
16
    u32           len;
17
    u8            rev;
18
    u8            csum;
19
    char          oem_id[ACPI_OEM_ID_SIZE];
20
    char          oem_tid[ACPI_OEM_TABLE_ID_SIZE];
21
    u32           oem_rev;
22
    u32           creator_id;
23
    u32           creator_rev;
24
}acpi_thead_t;
25
 
26
typedef struct __attribute__((packed))
27
{
28
    u8 space_id;            /* Address space where struct or register exists */
29
    u8 bit_width;           /* Size in bits of given register */
30
    u8 bit_offset;          /* Bit offset within the register */
31
    u8 access_width;        /* Minimum Access size (ACPI 3.0) */
32
    u64 address;            /* 64-bit address of struct or register */
33
}acpi_address_t;
34
 
35
 
36
typedef struct __attribute__((packed))
37
{
38
        acpi_thead_t header;        /* Common ACPI table header */
39
        u32 id;                     /* Hardware ID of event timer block */
40
        acpi_address_t address;     /* Address of event timer block */
41
        u8 sequence;                /* HPET sequence number */
42
        u16 minimum_tick;           /* Main counter min tick, periodic mode */
43
        u8 flags;
44
}acpi_hpet_t;
45
 
46
typedef struct  __attribute__((packed))
47
{
48
    acpi_thead_t  header;
49
    u32           ptrs[0];
50
}acpi_rsdt_t;
51
 
52
typedef struct  __attribute__((packed))
53
{
54
    acpi_thead_t  header;
55
    u64           ptrs[0];
56
}acpi_xsdt_t;
57
 
58
typedef struct __attribute__((packed))
59
{
60
    u64           sig;
61
    u8            csum;
62
    char          oemid[6];
63
    u8            rev;
64
    u32           rsdt_ptr;
65
    u32           rsdt_len;
66
    u64           xsdt_ptr;
67
    u8            xcsum;
68
    u8            _rsvd_33[3];
69
}acpi_rsdp_t;
70
 
71
#define OS_BASE                 0x80000000
72
#define ACPI20_PC99_RSDP_START  (OS_BASE + 0x0e0000)
73
#define ACPI20_PC99_RSDP_END    (OS_BASE + 0x100000)
74
#define ACPI20_PC99_RSDP_SIZE   (ACPI20_PC99_RSDP_END - ACPI20_PC99_RSDP_START)
75
 
76
static acpi_thead_t* (*sdt_find)(void *sdt, u32 sig);
77
 
78
static u8 acpi_tb_checksum (u8 *buffer, u32 len)
79
{
80
    u8    sum = 0;
81
    u8    *end = buffer + len;
82
 
83
    while (buffer < end)
84
    {
85
        sum = (u8)(sum + *(buffer++));
86
    }
87
 
88
    return sum;
89
}
90
 
91
static acpi_rsdp_t* acpi_locate()
92
{
93
    addr_t p;
94
 
95
    for (p = ACPI20_PC99_RSDP_START; p < ACPI20_PC99_RSDP_END; p+=16)
96
    {
97
        acpi_rsdp_t* r = (acpi_rsdp_t*) p;
98
        if (r->sig != 0x2052545020445352 )
99
            continue;
100
 
101
        if (acpi_tb_checksum ((u8*)r, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
102
            continue;
103
 
104
        if ((r->rev >= 2) &&
105
        (acpi_tb_checksum ((u8*)r, ACPI_RSDP_XCHECKSUM_LENGTH) != 0))
106
            continue;
107
 
108
        return r;
109
    };
110
 
111
    return NULL;
112
};
113
 
114
acpi_thead_t* rsdt_find(acpi_rsdt_t *rsdt, u32 sig)
115
{
116
    acpi_thead_t *head = NULL;
117
    u32 i;
118
 
119
    for (i = 0; i < ((rsdt->header.len-sizeof(acpi_thead_t))/
120
                sizeof(rsdt->ptrs[0])); i++)
121
    {
122
        u32 ptr = rsdt->ptrs[i];
123
 
124
        acpi_thead_t* t = (acpi_thead_t*)MapIoMem(ptr, 8192, PG_SW);
125
 
126
        if (t->sig == sig)
127
        {
128
           head = t;
129
           break;
130
        };
131
        FreeKernelSpace(t);
132
    }
133
    return head;
134
};
135
 
136
acpi_thead_t* xsdt_find(acpi_xsdt_t *xsdt, u32 sig)
137
{
138
    acpi_thead_t *head = NULL;
139
    u32 i;
140
 
141
    for (i = 0; i < ((xsdt->header.len-sizeof(acpi_thead_t))/
142
                sizeof(xsdt->ptrs[0])); i++)
143
    {
144
        u32 ptr = xsdt->ptrs[i];
145
 
146
        acpi_thead_t* t = (acpi_thead_t*)MapIoMem(ptr, 8192, PG_SW);
147
 
148
        if (t->sig == sig)
149
        {
150
           head = t;
151
           break;
152
        };
153
        FreeKernelSpace(t);
154
    }
155
    return head;
156
};
157
 
158
static void dump_rsdt(acpi_rsdt_t *rsdt)
159
{
160
    int i;
161
 
162
    for (i = 0; i < ((rsdt->header.len-sizeof(acpi_thead_t))/
163
                sizeof(rsdt->ptrs[0])); i++)
164
    {
165
        u32 ptr = rsdt->ptrs[i];
166
        dbgprintf("%s ptr= %p\n", __FUNCTION__, ptr);
167
 
168
        acpi_thead_t* t = (acpi_thead_t*)MapIoMem(ptr, 8192, PG_SW);
169
        dbgprintf("%s t= %x\n", __FUNCTION__, t);
170
 
171
        char *p = (char*)&t->sig;
172
        printf("sig %d: %x %c%c%c%c  base %p\n", i, t->sig,
173
        p[0],p[1],p[2],p[3],rsdt->ptrs[i]);
174
        FreeKernelSpace(t);
175
    };
176
};
177
 
178
typedef struct
179
{
180
    u64 hpet_cap;                       /* capabilities */
181
    u64 res0;                           /* reserved */
182
    u64 hpet_config;                    /* configuration */
183
    u64 res1;                           /* reserved */
184
    u64 hpet_isr;                       /* interrupt status reg */
185
    u64 res2[25];                       /* reserved */
186
    union {                             /* main counter */
187
            volatile u64 _hpet_mc64;
188
            u32 _hpet_mc32;
189
            unsigned long _hpet_mc;
190
    } _u0;
191
    u64 res3;                           /* reserved */
192
    struct hpet_timer {
193
            u64 hpet_config;            /* configuration/cap */
194
            union {                     /* timer compare register */
195
                    u64 _hpet_hc64;
196
                    u32 _hpet_hc32;
197
                    unsigned long _hpet_compare;
198
            } _u1;
199
            u64 hpet_fsb[2];            /* FSB route */
200
    } hpet_timers[1];
201
}hpet_t;
202
 
203
#define HPET_ID                 0x000
204
#define HPET_PERIOD             0x004
205
#define HPET_CFG                0x010
206
#define HPET_STATUS             0x020
207
#define HPET_COUNTER            0x0f0
208
 
209
#define HPET_ID_NUMBER          0x00001f00
210
#define HPET_ID_NUMBER_SHIFT    8
211
 
212
#define HPET_CFG_ENABLE         0x001
213
 
214
static void *hpet_virt_address;
215
 
216
inline unsigned int hpet_readl(unsigned int a)
217
{
218
    return readl(hpet_virt_address + a);
219
}
220
 
221
static inline void hpet_writel(unsigned int d, unsigned int a)
222
{
223
    writel(d, hpet_virt_address + a);
224
}
225
 
226
static void hpet_start_counter(void)
227
{
228
    unsigned int cfg = hpet_readl(HPET_CFG);
229
    cfg |= HPET_CFG_ENABLE;
230
    hpet_writel(cfg, HPET_CFG);
231
}
232
 
233
 
234
u64 read_htime()
235
{
236
    u32 eflags;
237
    u64 val;
238
 
239
    eflags = safe_cli();
240
    asm volatile(
241
    "1:\n"
242
    "mov 0xf4(%%ebx), %%edx\n"
243
    "mov 0xf0(%%ebx), %%eax\n"
244
    "mov 0xf4(%%ebx), %%ecx\n"
245
    "cmpl %%edx, %%ecx\n"
246
    "jnz 1b\n"
247
    :"=A"(val)
248
    :"b" (hpet_virt_address)
249
    :"ecx");
250
    safe_sti(eflags);
251
    return val;
252
}
253
 
254
static u32 period;
255
 
256
void init_hpet()
257
{
258
    void        *sdt  = NULL;
259
 
260
    acpi_rsdp_t *rsdp = acpi_locate();
261
 
262
    if (unlikely(rsdp == NULL))
263
    {
264
        printf("No ACPI RSD table\n");
265
        return ;
266
    };
267
 
268
    printf("rsd base address %p\n", rsdp);
269
 
270
    if(rsdp->rev > 1)
271
    {
272
        sdt = (void*)(u32)rsdp->xsdt_ptr;
273
        sdt_find = xsdt_find;
274
    }
275
    else
276
    {
277
        sdt = (void*)rsdp->rsdt_ptr;
278
        sdt_find = rsdt_find;
279
    };
280
 
281
    printf("sdt address %p\n", sdt);
282
 
283
    if (sdt == NULL)
284
    {
285
        printf("Invalid ACPI RSD table\n");
286
        return ;
287
    };
288
 
289
    sdt = MapIoMem(sdt, 128*1024, PG_SW);
290
 
291
    printf("sdt mapped address %x\n", sdt);
292
 
293
    acpi_hpet_t *tbl = (acpi_hpet_t*)sdt_find(sdt, 0x54455048);
294
 
295
    u32 hpet_address = tbl->address.address;
296
 
297
    hpet_virt_address = (void*)MapIoMem(hpet_address,1024, PG_SW|0x18);
298
 
299
    printf("hpet address %x mapped at %x\n", hpet_address, hpet_virt_address);
300
 
301
    u32 timers, l, h;
302
 
303
    l = hpet_readl(HPET_ID);
304
    h = hpet_readl(HPET_PERIOD);
305
    period = h / 1000000;
306
 
307
    timers = ((l & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
308
    printk(KERN_INFO "hpet: ID: 0x%x, PERIOD: 0x%x\n", l, h);
309
    l = hpet_readl(HPET_CFG);
310
    h = hpet_readl(HPET_STATUS);
311
    printk(KERN_INFO "hpet: CFG: 0x%x, STATUS: 0x%x\n", l, h);
312
    l = hpet_readl(HPET_COUNTER);
313
    h = hpet_readl(HPET_COUNTER+4);
314
    printk(KERN_INFO "hpet: COUNTER_l: 0x%x, COUNTER_h: 0x%x\n", l, h);
315
 
316
    hpet_start_counter();
317
 
318
}
319