Two hda_verb.h files: Add more comments.
[coreboot.git] / src / arch / i386 / boot / acpigen.c
index 777ec742531efd3d2fbc06ceefe1e1dc1d5b1e63..e8cd724e23a5d88d3a761d6d1251ef190c6a89f9 100644 (file)
@@ -4,8 +4,8 @@
  * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
  *
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License v2 as published by
- * the Free Software Foundation.
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <arch/acpigen.h>
 #include <console/console.h>
+#include <device/device.h>
 
 static char *gencurrent;
 
@@ -147,8 +148,8 @@ int acpigen_emit_stream(const char *data, int size)
        return size;
 }
 
-/* The NameString are bit tricky, each element can be 4 chars, if 
-   less its padded with underscore. Check 18.2.2 and 18.4 
+/* The NameString are bit tricky, each element can be 4 chars, if
+   less its padded with underscore. Check 18.2.2 and 18.4
    and 5.3 of ACPI specs 3.0 for details
 */
 
@@ -160,14 +161,14 @@ static int acpigen_emit_simple_namestring(const char *name) {
                        len += acpigen_emit_stream(ud, 4 - i);
                        break;
                } else {
-                       len += acpigen_emit_byte(name[i]);                              
+                       len += acpigen_emit_byte(name[i]);
                }
        }
        return len;
 }
 
 static int acpigen_emit_double_namestring(const char *name, int dotpos) {
-       int len = 0; 
+       int len = 0;
        /* mark dual name prefix */
        len += acpigen_emit_byte(0x2e);
        len += acpigen_emit_simple_namestring(name);
@@ -177,7 +178,7 @@ static int acpigen_emit_double_namestring(const char *name, int dotpos) {
 
 static int acpigen_emit_multi_namestring(const char *name) {
        int len = 0, count = 0;
-       unsigned char *pathlen; 
+       unsigned char *pathlen;
        /* mark multi name prefix */
        len += acpigen_emit_byte(0x2f);
        len += acpigen_emit_byte(0x0);
@@ -229,7 +230,7 @@ int acpigen_emit_namestring(const char *namepath) {
 
        if (dotcount == 0) {
                len += acpigen_emit_simple_namestring(namepath);
-       } else if (dotcount == 1) { 
+       } else if (dotcount == 1) {
                len += acpigen_emit_double_namestring(namepath, dotpos);
        } else {
                len += acpigen_emit_multi_namestring(namepath);
@@ -372,3 +373,145 @@ int acpigen_write_PSD_package(u32 domain, u32 numprocs, PSD_coord coordtype)
        acpigen_patch_len(len - 1);
        return len + lenh;
 }
+
+int acpigen_write_mem32fixed(int readwrite, u32 base, u32 size)
+{
+       /*
+        * acpi 4.0 section 6.4.3.4: 32-Bit Fixed Memory Range Descriptor
+        * Byte 0:
+        *   Bit7  : 1 => big item
+        *   Bit6-0: 0000110 (0x6) => 32-bit fixed memory
+        */
+       acpigen_emit_byte(0x86);
+       /* Byte 1+2: length (0x0009) */
+       acpigen_emit_byte(0x09);
+       acpigen_emit_byte(0x00);
+       /* bit1-7 are ignored */
+       acpigen_emit_byte(readwrite ? 0x01 : 0x00);
+       acpigen_emit_byte(base & 0xff);
+       acpigen_emit_byte((base >> 8) & 0xff);
+       acpigen_emit_byte((base >> 16) & 0xff);
+       acpigen_emit_byte((base >> 24) & 0xff);
+       acpigen_emit_byte(size & 0xff);
+       acpigen_emit_byte((size >> 8) & 0xff);
+       acpigen_emit_byte((size >> 16) & 0xff);
+       acpigen_emit_byte((size >> 24) & 0xff);
+       return 12;
+}
+
+int acpigen_write_io16(u16 min, u16 max, u8 align, u8 len, u8 decode16)
+{
+       /*
+        * acpi 4.0 section 6.4.2.6: I/O Port Descriptor
+        * Byte 0:
+        *   Bit7  : 0 => small item
+        *   Bit6-3: 1000 (0x8) => I/O port descriptor
+        *   Bit2-0: 111 (0x7) => 7 Bytes long
+        */
+       acpigen_emit_byte(0x47);
+       /* does the device decode all 16 or just 10 bits? */
+       /* bit1-7 are ignored */
+       acpigen_emit_byte(decode16 ? 0x01 : 0x00);
+       /* minimum base address the device may be configured for */
+       acpigen_emit_byte(min & 0xff);
+       acpigen_emit_byte((min >> 8) & 0xff);
+       /* maximum base address the device may be configured for */
+       acpigen_emit_byte(max & 0xff);
+       acpigen_emit_byte((max >> 8) & 0xff);
+       /* alignment for min base */
+       acpigen_emit_byte(align & 0xff);
+       acpigen_emit_byte(len & 0xff);
+       return 8;
+}
+
+int acpigen_write_resourcetemplate_header(void)
+{
+       int len;
+       /*
+        * A ResourceTemplate() is a Buffer() with a
+        * (Byte|Word|DWord) containing the length, followed by one or more
+        * resource items, terminated by the end tag
+        * (small item 0xf, len 1)
+        */
+       len = acpigen_emit_byte(0x11); /* Buffer opcode */
+       len += acpigen_write_len_f();
+       len += acpigen_emit_byte(0x0b); /* Word opcode */
+       len_stack[ltop++] = acpigen_get_current();
+       len += acpigen_emit_byte(0x00);
+       len += acpigen_emit_byte(0x00);
+       return len;
+}
+
+int acpigen_write_resourcetemplate_footer(int len)
+{
+       char *p = len_stack[--ltop];
+       /*
+        * end tag (acpi 4.0 Section 6.4.2.8)
+        * 0x79 <checksum>
+        * 0x00 is treated as a good checksum according to the spec
+        * and is what iasl generates.
+        */
+       len += acpigen_emit_byte(0x79);
+       len += acpigen_emit_byte(0x00);
+       /* patch len word */
+       p[0] = (len-6) & 0xff;
+       p[1] = ((len-6) >> 8) & 0xff;
+       /* patch len field */
+       acpigen_patch_len(len-1);
+       return 2;
+}
+
+static void acpigen_add_mainboard_rsvd_mem32(void *gp, struct device *dev,
+                                               struct resource *res)
+{
+       acpigen_write_mem32fixed(0, res->base, res->size);
+}
+
+static void acpigen_add_mainboard_rsvd_io(void *gp, struct device *dev,
+                                               struct resource *res)
+{
+       resource_t base = res->base;
+       resource_t size = res->size;
+       while (size > 0) {
+               resource_t sz = size > 255 ? 255 : size;
+               acpigen_write_io16(base, base, 0, sz, 1);
+               size -= sz;
+               base += sz;
+       }
+}
+
+int acpigen_write_mainboard_resource_template(void)
+{
+       int len;
+       char *start;
+       char *end;
+       len = acpigen_write_resourcetemplate_header();
+       start = acpigen_get_current();
+
+       /* Add reserved memory ranges */
+       search_global_resources(
+               IORESOURCE_MEM | IORESOURCE_RESERVE,
+                IORESOURCE_MEM | IORESOURCE_RESERVE,
+               acpigen_add_mainboard_rsvd_mem32, 0);
+
+       /* Add reserved io ranges */
+       search_global_resources(
+               IORESOURCE_IO | IORESOURCE_RESERVE,
+                IORESOURCE_IO | IORESOURCE_RESERVE,
+               acpigen_add_mainboard_rsvd_io, 0);
+
+       end = acpigen_get_current();
+       len += end-start;
+       len += acpigen_write_resourcetemplate_footer(len);
+       return len;
+}
+
+int acpigen_write_mainboard_resources(const char *scope, const char *name)
+{
+       int len;
+       len = acpigen_write_scope(scope);
+       len += acpigen_write_name(name);
+       len += acpigen_write_mainboard_resource_template();
+       acpigen_patch_len(len - 1);
+       return len;
+}