Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include <syscall.h>
  2. #include <linux/ktime.h>
  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.  
  320.  
  321.