~ubuntu-branches/ubuntu/oneiric/seabios/oneiric

« back to all changes in this revision

Viewing changes to src/acpi.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn, Serge Hallyn, Dustin Kirkland
  • Date: 2011-02-14 14:38:50 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110214143850-cmzexufi3dlrt7ga
Tags: 0.6.1.2-0ubuntu1
[ Serge Hallyn ]
* upstream merge
  - updated debian/watch
  - remove all patches as they are applied upstream
  - removed debian-changes-0.6.0-0ubuntu2 - I'm not certain about this one,
    so it may re-introduce a regression

[ Dustin Kirkland ]
* debian/rules: fix lintian warnings, install changelog, make binary build
  arch indep
* debian/control: update standards version

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// Support for generating ACPI tables (on emulators)
2
2
//
3
 
// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
 
3
// Copyright (C) 2008-2010  Kevin O'Connor <kevin@koconnor.net>
4
4
// Copyright (C) 2006 Fabrice Bellard
5
5
//
6
6
// This file may be distributed under the terms of the GNU LGPLv3 license.
12
12
#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
13
13
#include "pci_regs.h" // PCI_INTERRUPT_LINE
14
14
#include "paravirt.h"
 
15
#include "dev-i440fx.h" // piix4_fadt_init
15
16
 
16
17
/****************************************************/
17
18
/* ACPI tables init */
19
20
/* Table structure from Linux kernel (the ACPI tables are under the
20
21
   BSD license) */
21
22
 
22
 
#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
23
 
    u32 signature;          /* ACPI signature (4 ASCII characters) */ \
24
 
    u32 length;                 /* Length of table, in bytes, including header */ \
25
 
    u8  revision;               /* ACPI Specification minor version # */ \
26
 
    u8  checksum;               /* To make sum of entire table == 0 */ \
27
 
    u8  oem_id [6];             /* OEM identification */ \
28
 
    u8  oem_table_id [8];       /* OEM table identification */ \
29
 
    u32 oem_revision;           /* OEM revision number */ \
30
 
    u8  asl_compiler_id [4];    /* ASL compiler vendor ID */ \
31
 
    u32 asl_compiler_revision;  /* ASL compiler revision number */
32
 
 
33
 
 
34
23
struct acpi_table_header         /* ACPI common table header */
35
24
{
36
25
    ACPI_TABLE_HEADER_DEF
65
54
 
66
55
 
67
56
/*
68
 
 * ACPI 1.0 Fixed ACPI Description Table (FADT)
69
 
 */
70
 
#define FACP_SIGNATURE 0x50434146 // FACP
71
 
struct fadt_descriptor_rev1
72
 
{
73
 
    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
74
 
    u32 firmware_ctrl;          /* Physical address of FACS */
75
 
    u32 dsdt;                   /* Physical address of DSDT */
76
 
    u8  model;                  /* System Interrupt Model */
77
 
    u8  reserved1;              /* Reserved */
78
 
    u16 sci_int;                /* System vector of SCI interrupt */
79
 
    u32 smi_cmd;                /* Port address of SMI command port */
80
 
    u8  acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
81
 
    u8  acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
82
 
    u8  S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
83
 
    u8  reserved2;              /* Reserved - must be zero */
84
 
    u32 pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
85
 
    u32 pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
86
 
    u32 pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
87
 
    u32 pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
88
 
    u32 pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
89
 
    u32 pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
90
 
    u32 gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
91
 
    u32 gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
92
 
    u8  pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
93
 
    u8  pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
94
 
    u8  pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
95
 
    u8  pm_tmr_len;             /* Byte Length of ports at pm_tm_blk */
96
 
    u8  gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
97
 
    u8  gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
98
 
    u8  gpe1_base;              /* Offset in gpe model where gpe1 events start */
99
 
    u8  reserved3;              /* Reserved */
100
 
    u16 plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
101
 
    u16 plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
102
 
    u16 flush_size;             /* Size of area read to flush caches */
103
 
    u16 flush_stride;           /* Stride used in flushing caches */
104
 
    u8  duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
105
 
    u8  duty_width;             /* Bit width of duty cycle field in p_cnt reg */
106
 
    u8  day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
107
 
    u8  mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
108
 
    u8  century;                /* Index to century in RTC CMOS RAM */
109
 
    u8  reserved4;              /* Reserved */
110
 
    u8  reserved4a;             /* Reserved */
111
 
    u8  reserved4b;             /* Reserved */
112
 
#if 0
113
 
    u32 wb_invd         : 1;    /* The wbinvd instruction works properly */
114
 
    u32 wb_invd_flush   : 1;    /* The wbinvd flushes but does not invalidate */
115
 
    u32 proc_c1         : 1;    /* All processors support C1 state */
116
 
    u32 plvl2_up        : 1;    /* C2 state works on MP system */
117
 
    u32 pwr_button      : 1;    /* Power button is handled as a generic feature */
118
 
    u32 sleep_button    : 1;    /* Sleep button is handled as a generic feature, or not present */
119
 
    u32 fixed_rTC       : 1;    /* RTC wakeup stat not in fixed register space */
120
 
    u32 rtcs4           : 1;    /* RTC wakeup stat not possible from S4 */
121
 
    u32 tmr_val_ext     : 1;    /* The tmr_val width is 32 bits (0 = 24 bits) */
122
 
    u32 reserved5       : 23;   /* Reserved - must be zero */
123
 
#else
124
 
    u32 flags;
125
 
#endif
126
 
} PACKED;
127
 
 
128
 
/*
129
57
 * MADT values and structures
130
58
 */
131
59
 
270
198
 
271
199
#include "acpi-dsdt.hex"
272
200
 
273
 
static inline u16 cpu_to_le16(u16 x)
274
 
{
275
 
    return x;
276
 
}
277
 
 
278
 
static inline u32 cpu_to_le32(u32 x)
279
 
{
280
 
    return x;
281
 
}
282
 
 
283
201
static void
284
202
build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
285
203
{
295
213
    h->checksum -= checksum(h, len);
296
214
}
297
215
 
 
216
static const struct pci_device_id fadt_init_tbl[] = {
 
217
    /* PIIX4 Power Management device (for ACPI) */
 
218
    PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
 
219
               piix4_fadt_init),
 
220
 
 
221
    PCI_DEVICE_END
 
222
};
 
223
 
298
224
static void*
299
225
build_fadt(int bdf)
300
226
{
324
250
    int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
325
251
    fadt->sci_int = cpu_to_le16(pm_sci_int);
326
252
    fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
327
 
    fadt->acpi_enable = 0xf1;
328
 
    fadt->acpi_disable = 0xf0;
329
253
    fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
330
254
    fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
331
255
    fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
334
258
    fadt->pm_tmr_len = 4;
335
259
    fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
336
260
    fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
337
 
    fadt->gpe0_blk = cpu_to_le32(0xafe0);
338
 
    fadt->gpe0_blk_len = 4;
 
261
    pci_init_device(fadt_init_tbl, bdf, fadt);
339
262
    /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
340
263
    fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
341
264
 
406
329
    return madt;
407
330
}
408
331
 
 
332
// Encode a hex value
 
333
static inline char getHex(u32 val) {
 
334
    val &= 0x0f;
 
335
    return (val <= 9) ? ('0' + val) : ('A' + val - 10);
 
336
}
 
337
 
 
338
// Encode a length in an SSDT.
 
339
static u8 *
 
340
encodeLen(u8 *ssdt_ptr, int length, int bytes)
 
341
{
 
342
    switch (bytes) {
 
343
    default:
 
344
    case 4: ssdt_ptr[3] = ((length >> 20) & 0xff);
 
345
    case 3: ssdt_ptr[2] = ((length >> 12) & 0xff);
 
346
    case 2: ssdt_ptr[1] = ((length >> 4) & 0xff);
 
347
            ssdt_ptr[0] = (((bytes-1) & 0x3) << 6) | (length & 0x0f);
 
348
            break;
 
349
    case 1: ssdt_ptr[0] = length & 0x3f;
 
350
    }
 
351
    return ssdt_ptr + bytes;
 
352
}
 
353
 
 
354
// AML Processor() object.  See src/ssdt-proc.dsl for info.
 
355
static unsigned char ssdt_proc[] = {
 
356
    0x5b,0x83,0x42,0x05,0x43,0x50,0x41,0x41,
 
357
    0xaa,0x10,0xb0,0x00,0x00,0x06,0x08,0x49,
 
358
    0x44,0x5f,0x5f,0x0a,0xaa,0x08,0x5f,0x48,
 
359
    0x49,0x44,0x0d,0x41,0x43,0x50,0x49,0x30,
 
360
    0x30,0x30,0x37,0x00,0x14,0x0f,0x5f,0x4d,
 
361
    0x41,0x54,0x00,0xa4,0x43,0x50,0x4d,0x41,
 
362
    0x49,0x44,0x5f,0x5f,0x14,0x0f,0x5f,0x53,
 
363
    0x54,0x41,0x00,0xa4,0x43,0x50,0x53,0x54,
 
364
    0x49,0x44,0x5f,0x5f,0x14,0x0f,0x5f,0x45,
 
365
    0x4a,0x30,0x01,0x43,0x50,0x45,0x4a,0x49,
 
366
    0x44,0x5f,0x5f,0x68
 
367
};
 
368
#define SD_OFFSET_CPUHEX 6
 
369
#define SD_OFFSET_CPUID1 8
 
370
#define SD_OFFSET_CPUID2 20
 
371
 
409
372
#define SSDT_SIGNATURE 0x54445353 // SSDT
410
373
static void*
411
374
build_ssdt(void)
412
375
{
413
376
    int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
414
 
    // calculate the length of processor block and scope block
415
 
    // excluding PkgLength
416
 
    int cpu_length = 13 * acpi_cpus + 4;
417
 
 
418
 
    int length = sizeof(struct acpi_table_header) + 3 + cpu_length;
419
 
    u8 *ssdt = malloc_high(length);
 
377
    // length = ScopeOp + procs + NTYF method + CPON package
 
378
    int length = ((1+3+4)
 
379
                  + (acpi_cpus * sizeof(ssdt_proc))
 
380
                  + (1+2+5+(12*acpi_cpus))
 
381
                  + (6+2+1+(1*acpi_cpus)));
 
382
    u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length);
420
383
    if (! ssdt) {
421
384
        warn_noalloc();
422
385
        return NULL;
423
386
    }
424
 
 
425
 
    u8 *ssdt_ptr = ssdt;
426
 
    ssdt_ptr[9] = 0; // checksum;
427
 
    ssdt_ptr += sizeof(struct acpi_table_header);
428
 
 
429
 
    // build processor scope header
 
387
    u8 *ssdt_ptr = ssdt + sizeof(struct acpi_table_header);
 
388
 
 
389
    // build Scope(_SB_) header
430
390
    *(ssdt_ptr++) = 0x10; // ScopeOp
431
 
    if (cpu_length <= 0x3e) {
432
 
        /* Handle 1-4 CPUs with one byte encoding */
433
 
        *(ssdt_ptr++) = cpu_length + 1;
434
 
    } else {
435
 
        /* Handle 5-314 CPUs with two byte encoding */
436
 
        *(ssdt_ptr++) = 0x40 | ((cpu_length + 2) & 0xf);
437
 
        *(ssdt_ptr++) = (cpu_length + 2) >> 4;
438
 
    }
439
 
    *(ssdt_ptr++) = '_'; // Name
 
391
    ssdt_ptr = encodeLen(ssdt_ptr, length-1, 3);
 
392
    *(ssdt_ptr++) = '_';
 
393
    *(ssdt_ptr++) = 'S';
 
394
    *(ssdt_ptr++) = 'B';
 
395
    *(ssdt_ptr++) = '_';
 
396
 
 
397
    // build Processor object for each processor
 
398
    int i;
 
399
    for (i=0; i<acpi_cpus; i++) {
 
400
        memcpy(ssdt_ptr, ssdt_proc, sizeof(ssdt_proc));
 
401
        ssdt_ptr[SD_OFFSET_CPUHEX] = getHex(i >> 4);
 
402
        ssdt_ptr[SD_OFFSET_CPUHEX+1] = getHex(i);
 
403
        ssdt_ptr[SD_OFFSET_CPUID1] = i;
 
404
        ssdt_ptr[SD_OFFSET_CPUID2] = i;
 
405
        ssdt_ptr += sizeof(ssdt_proc);
 
406
    }
 
407
 
 
408
    // build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}"
 
409
    *(ssdt_ptr++) = 0x14; // MethodOp
 
410
    ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*acpi_cpus), 2);
 
411
    *(ssdt_ptr++) = 'N';
 
412
    *(ssdt_ptr++) = 'T';
 
413
    *(ssdt_ptr++) = 'F';
 
414
    *(ssdt_ptr++) = 'Y';
 
415
    *(ssdt_ptr++) = 0x02;
 
416
    for (i=0; i<acpi_cpus; i++) {
 
417
        *(ssdt_ptr++) = 0xA0; // IfOp
 
418
        ssdt_ptr = encodeLen(ssdt_ptr, 11, 1);
 
419
        *(ssdt_ptr++) = 0x93; // LEqualOp
 
420
        *(ssdt_ptr++) = 0x68; // Arg0Op
 
421
        *(ssdt_ptr++) = 0x0A; // BytePrefix
 
422
        *(ssdt_ptr++) = i;
 
423
        *(ssdt_ptr++) = 0x86; // NotifyOp
 
424
        *(ssdt_ptr++) = 'C';
 
425
        *(ssdt_ptr++) = 'P';
 
426
        *(ssdt_ptr++) = getHex(i >> 4);
 
427
        *(ssdt_ptr++) = getHex(i);
 
428
        *(ssdt_ptr++) = 0x69; // Arg1Op
 
429
    }
 
430
 
 
431
    // build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
 
432
    *(ssdt_ptr++) = 0x08; // NameOp
 
433
    *(ssdt_ptr++) = 'C';
440
434
    *(ssdt_ptr++) = 'P';
441
 
    *(ssdt_ptr++) = 'R';
442
 
    *(ssdt_ptr++) = '_';
443
 
 
444
 
    // build object for each processor
445
 
    int i;
446
 
    for (i=0; i<acpi_cpus; i++) {
447
 
        *(ssdt_ptr++) = 0x5B; // ProcessorOp
448
 
        *(ssdt_ptr++) = 0x83;
449
 
        *(ssdt_ptr++) = 0x0B; // Length
450
 
        *(ssdt_ptr++) = 'C';  // Name (CPUxx)
451
 
        *(ssdt_ptr++) = 'P';
452
 
        if ((i & 0xf0) != 0)
453
 
            *(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
454
 
        else
455
 
            *(ssdt_ptr++) = 'U';
456
 
        *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
457
 
        *(ssdt_ptr++) = i;
458
 
        *(ssdt_ptr++) = 0x10; // Processor block address
459
 
        *(ssdt_ptr++) = 0xb0;
460
 
        *(ssdt_ptr++) = 0;
461
 
        *(ssdt_ptr++) = 0;
462
 
        *(ssdt_ptr++) = 6;    // Processor block length
463
 
    }
 
435
    *(ssdt_ptr++) = 'O';
 
436
    *(ssdt_ptr++) = 'N';
 
437
    *(ssdt_ptr++) = 0x12; // PackageOp
 
438
    ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*acpi_cpus), 2);
 
439
    *(ssdt_ptr++) = acpi_cpus;
 
440
    for (i=0; i<acpi_cpus; i++)
 
441
        *(ssdt_ptr++) = (i < CountCPUs) ? 0x01 : 0x00;
464
442
 
465
443
    build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
466
444
 
 
445
    //hexdump(ssdt, ssdt_ptr - ssdt);
 
446
 
467
447
    return ssdt;
468
448
}
469
449
 
599
579
    return srat;
600
580
}
601
581
 
 
582
static const struct pci_device_id acpi_find_tbl[] = {
 
583
    /* PIIX4 Power Management device. */
 
584
    PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL),
 
585
 
 
586
    PCI_DEVICE_END,
 
587
};
 
588
 
602
589
struct rsdp_descriptor *RsdpAddr;
603
590
 
604
591
#define MAX_ACPI_TABLES 20
611
598
    dprintf(3, "init ACPI tables\n");
612
599
 
613
600
    // This code is hardcoded for PIIX4 Power Management device.
614
 
    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL
615
 
                              , PCI_DEVICE_ID_INTEL_82371AB_3);
 
601
    int bdf = pci_find_init_device(acpi_find_tbl, NULL);
616
602
    if (bdf < 0)
617
603
        // Device not found
618
604
        return;