]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/hpet.c
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / osfmk / i386 / hpet.c
index 5ae9621d52d8dbc20d304fdf936dde3921c17ccf..8b9f03b2e7f1a597098e21d6f0c904f99593db2d 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
 #include <vm/vm_page.h>
 #include <vm/pmap.h>
 #include <vm/vm_kern.h>
-#include <i386/pmap.h>
-#include <i386/misc_protos.h>
 #include <i386/cpuid.h>
-#include <i386/mp.h>
 #include <i386/machine_cpu.h>
+#include <i386/mp.h>
 #include <i386/machine_routines.h>
+#include <i386/pmap.h>
+#include <i386/misc_protos.h>
 #include <i386/io_map_entries.h>
 #include <architecture/i386/pio.h>
 #include <i386/cpuid.h>
 #include <i386/cpu_topology.h>
 #include <i386/cpu_threads.h>
 #include <pexpert/device_tree.h>
-#if    MACH_KDB
-#include <i386/db_machdep.h>
-#endif
-#if    MACH_KDB
-#include <ddb/db_aout.h>
-#include <ddb/db_access.h>
-#include <ddb/db_sym.h>
-#include <ddb/db_variables.h>
-#include <ddb/db_command.h>
-#include <ddb/db_output.h>
-#include <ddb/db_expr.h>
-#endif /* MACH_KDB */
-#include <ddb/tr.h>
 
 /* Decimal powers: */
 #define kilo (1000ULL)
 #define Tera (kilo * Giga)
 #define Peta (kilo * Tera)
 
-uint32_t hpetArea = 0;                 
-uint32_t hpetAreap = 0;                        
+vm_offset_t hpetArea = 0;
+uint32_t hpetAreap = 0;
 uint64_t hpetFemto = 0;
 uint64_t hpetFreq = 0;
-uint64_t hpetCvt = 0;                  /* (TAKE OUT LATER)  */
+uint64_t hpetCvt = 0;                   /* (TAKE OUT LATER)  */
 uint64_t hpetCvtt2n = 0;
 uint64_t hpetCvtn2t = 0;
 uint64_t tsc2hpet = 0;
@@ -91,27 +78,27 @@ uint64_t hpet2tsc = 0;
 uint64_t bus2hpet = 0;
 uint64_t hpet2bus = 0;
 
-uint32_t rcbaArea = 0;                 
-uint32_t rcbaAreap = 0;                        
+vm_offset_t rcbaArea = 0;
+uint32_t rcbaAreap = 0;
 
 static int (*hpet_req)(uint32_t apicid, void *arg, hpetRequest_t *hpet) = NULL;
 static void *hpet_arg = NULL;
 
 #if DEBUG
-#define DBG(x...)      kprintf("DBG: " x)
+#define DBG(x...)       kprintf("DBG: " x)
 #else
 #define DBG(x...)
 #endif
 
 int
 hpet_register_callback(int (*hpet_reqst)(uint32_t apicid,
-                                        void *arg,
-                                        hpetRequest_t *hpet),
-                      void *arg)
+    void *arg,
+    hpetRequest_t *hpet),
+    void *arg)
 {
-    hpet_req = hpet_reqst;
-    hpet_arg = arg;
-    return(0);
+       hpet_req = hpet_reqst;
+       hpet_arg = arg;
+       return 0;
 }
 
 /*
@@ -122,58 +109,78 @@ hpet_register_callback(int (*hpet_reqst)(uint32_t apicid,
 int
 hpet_request(uint32_t cpu)
 {
-    hpetRequest_t      hpetReq;
-    int                        rc;
-    x86_lcpu_t         *lcpu;
-    x86_core_t         *core;
-    x86_pkg_t          *pkg;
-    boolean_t          enabled;
-
-    if (hpet_req == NULL) {
-       return(-1);
-    }
-
-    rc = (*hpet_req)(ml_get_apicid(cpu), hpet_arg, &hpetReq);
-    if (rc != 0) {
-       return(rc);
-    }
-
-    enabled = ml_set_interrupts_enabled(FALSE);
-    lcpu = cpu_to_lcpu(cpu);
-    core = lcpu->core;
-    pkg  = core->package;
-
-    /*
-     * Compute the address of the HPET.
-     */
-    core->Hpet = (hpetTimer_t *)((uint8_t *)hpetArea + hpetReq.hpetOffset);
-    core->HpetVec = hpetReq.hpetVector;
-
-    /*
-     * Enable interrupts
-     */
-    core->Hpet->Config |= Tn_INT_ENB_CNF;
-
-    /*
-     * Save the configuration
-     */
-    core->HpetCfg = core->Hpet->Config;
-    core->HpetCmp = 0;
-
-    /*
-     * If the CPU is the "primary" for the package, then
-     * add the HPET to the package too.
-     */
-    if (lcpu->primary) {
-       pkg->Hpet = core->Hpet;
-       pkg->HpetCfg = core->HpetCfg;
-       pkg->HpetCmp = core->HpetCmp;
-       pkg->flags |= X86PKG_FL_HAS_HPET;
-    }
+       hpetRequest_t       hpetReq;
+       int                 rc;
+       x86_lcpu_t          *lcpu;
+       x86_core_t          *core;
+       x86_pkg_t           *pkg;
+       boolean_t           enabled;
+
+       if (hpet_req == NULL) {
+               return -1;
+       }
+
+       /*
+        * Deal with the case where the CPU # passed in is past the
+        * value specified in cpus=n in boot-args.
+        */
+       if (cpu >= real_ncpus) {
+               enabled = ml_set_interrupts_enabled(FALSE);
+               lcpu = cpu_to_lcpu(cpu);
+               if (lcpu != NULL) {
+                       core = lcpu->core;
+                       pkg  = core->package;
+
+                       if (lcpu->primary) {
+                               pkg->flags |= X86PKG_FL_HAS_HPET;
+                       }
+               }
+
+               ml_set_interrupts_enabled(enabled);
+               return 0;
+       }
+
+       rc = (*hpet_req)(ml_get_apicid(cpu), hpet_arg, &hpetReq);
+       if (rc != 0) {
+               return rc;
+       }
+
+       enabled = ml_set_interrupts_enabled(FALSE);
+       lcpu = cpu_to_lcpu(cpu);
+       core = lcpu->core;
+       pkg  = core->package;
+
+       /*
+        * Compute the address of the HPET.
+        */
+       core->Hpet = (hpetTimer_t *)((uint8_t *)hpetArea + hpetReq.hpetOffset);
+       core->HpetVec = hpetReq.hpetVector;
+
+       /*
+        * Enable interrupts
+        */
+       core->Hpet->Config |= Tn_INT_ENB_CNF;
+
+       /*
+        * Save the configuration
+        */
+       core->HpetCfg = core->Hpet->Config;
+       core->HpetCmp = 0;
 
-    ml_set_interrupts_enabled(enabled);
+       /*
+        * If the CPU is the "primary" for the package, then
+        * add the HPET to the package too.
+        */
+       if (lcpu->primary) {
+               pkg->Hpet = core->Hpet;
+               pkg->HpetCfg = core->HpetCfg;
+               pkg->HpetCmp = core->HpetCmp;
+               pkg->flags |= X86PKG_FL_HAS_HPET;
+       }
+
+       ml_set_interrupts_enabled(enabled);
 
-    return(0);
+       return 0;
 }
 
 /*
@@ -188,7 +195,7 @@ map_rcbaArea(void)
        outl(cfgAdr, lpcCfg | (0xF0 & 0xFC));
        rcbaAreap = inl(cfgDat | (0xF0 & 0x03));
        rcbaArea = io_map_spec(rcbaAreap & -4096, PAGE_SIZE * 4, VM_WIMG_IO);
-       kprintf("RCBA: vaddr = %08X, paddr = %08X\n", rcbaArea, rcbaAreap);
+       kprintf("RCBA: vaddr = %lX, paddr = %08X\n", (unsigned long)rcbaArea, rcbaAreap);
 }
 
 /*
@@ -197,7 +204,7 @@ map_rcbaArea(void)
 void
 hpet_init(void)
 {
-       unsigned int    *xmod;
+       unsigned int    *xmod;
 
        map_rcbaArea();
 
@@ -205,10 +212,10 @@ hpet_init(void)
         * Is the HPET memory already enabled?
         * If not, set address and enable.
         */
-       xmod = (uint32_t *)(rcbaArea + 0x3404); /* Point to the HPTC */
-       uint32_t hptc = *xmod;                  /* Get HPET config */
+       xmod = (uint32_t *)(rcbaArea + 0x3404); /* Point to the HPTC */
+       uint32_t hptc = *xmod;                  /* Get HPET config */
        DBG("    current RCBA.HPTC:  %08X\n", *xmod);
-       if(!(hptc & hptcAE)) {
+       if (!(hptc & hptcAE)) {
                DBG("HPET memory is not enabled, "
                    "enabling and assigning to 0xFED00000 (hope that's ok)\n");
                *xmod = (hptc & ~3) | hptcAE;
@@ -219,7 +226,7 @@ hpet_init(void)
         */
        hpetAreap = hpetAddr | ((hptc & 3) << 12);
        hpetArea = io_map_spec(hpetAreap & -4096, PAGE_SIZE * 4, VM_WIMG_IO);
-       kprintf("HPET: vaddr = %08X, paddr = %08X\n", hpetArea, hpetAreap);
+       kprintf("HPET: vaddr = %lX, paddr = %08X\n", (unsigned long)hpetArea, hpetAreap);
 
        /*
         * Extract the HPET tick rate.
@@ -247,10 +254,10 @@ hpet_init(void)
        hpetCvtt2n = hpetCvtt2n / 1000000ULL;
        hpetCvtn2t = 0xFFFFFFFFFFFFFFFFULL / hpetCvtt2n;
        kprintf("HPET: Frequency = %6d.%04dMHz, "
-               "cvtt2n = %08X.%08X, cvtn2t = %08X.%08X\n",
-               (uint32_t)(hpetFreq / Mega), (uint32_t)(hpetFreq % Mega), 
-               (uint32_t)(hpetCvtt2n >> 32), (uint32_t)hpetCvtt2n,
-               (uint32_t)(hpetCvtn2t >> 32), (uint32_t)hpetCvtn2t);
+           "cvtt2n = %08X.%08X, cvtn2t = %08X.%08X\n",
+           (uint32_t)(hpetFreq / Mega), (uint32_t)(hpetFreq % Mega),
+           (uint32_t)(hpetCvtt2n >> 32), (uint32_t)hpetCvtt2n,
+           (uint32_t)(hpetCvtn2t >> 32), (uint32_t)hpetCvtn2t);
 
 
        /* (TAKE OUT LATER)
@@ -279,10 +286,6 @@ hpet_init(void)
        hpet2bus = tmrCvt(hpetCvtt2n, busFCvtn2t);
        DBG(" CVT: HPET to BUS = %08X.%08X\n",
            (uint32_t)(hpet2bus >> 32), (uint32_t)hpet2bus);
-
-#if MACH_KDB
-       db_display_hpet((hpetReg_t *)hpetArea); /* (BRINGUP) */
-#endif
 }
 
 /*
@@ -293,19 +296,19 @@ hpet_init(void)
 void
 hpet_get_info(hpetInfo_t *info)
 {
-    info->hpetCvtt2n = hpetCvtt2n;
-    info->hpetCvtn2t = hpetCvtn2t;
-    info->tsc2hpet   = tsc2hpet;
-    info->hpet2tsc   = hpet2tsc;
-    info->bus2hpet   = bus2hpet;
-    info->hpet2bus   = hpet2bus;
-    /*
-     * XXX
-     * We're repurposing the rcbaArea so we can use the HPET.
-     * Eventually we'll rename this correctly.
-     */
-    info->rcbaArea   = hpetArea;
-    info->rcbaAreap  = hpetAreap;
+       info->hpetCvtt2n = hpetCvtt2n;
+       info->hpetCvtn2t = hpetCvtn2t;
+       info->tsc2hpet   = tsc2hpet;
+       info->hpet2tsc   = hpet2tsc;
+       info->bus2hpet   = bus2hpet;
+       info->hpet2bus   = hpet2bus;
+       /*
+        * XXX
+        * We're repurposing the rcbaArea so we can use the HPET.
+        * Eventually we'll rename this correctly.
+        */
+       info->rcbaArea   = hpetArea;
+       info->rcbaAreap  = hpetAreap;
 }
 
 
@@ -319,14 +322,14 @@ hpet_get_info(hpetInfo_t *info)
 void
 ml_hpet_cfg(uint32_t cpu, uint32_t hpetVect)
 {
-       uint64_t        *hpetVaddr;
-       hpetTimer_t     *hpet;
-       x86_lcpu_t      *lcpu;
-       x86_core_t      *core;
-       x86_pkg_t       *pkg;
-       boolean_t       enabled;
-       
-       if(cpu > 1) {
+       uint64_t        *hpetVaddr;
+       hpetTimer_t     *hpet;
+       x86_lcpu_t      *lcpu;
+       x86_core_t      *core;
+       x86_pkg_t       *pkg;
+       boolean_t       enabled;
+
+       if (cpu > 1) {
                panic("ml_hpet_cfg: invalid cpu = %d\n", cpu);
        }
 
@@ -337,17 +340,18 @@ ml_hpet_cfg(uint32_t cpu, uint32_t hpetVect)
        /*
         * Only deal with the primary CPU for the package.
         */
-       if (!lcpu->primary)
-           return;
+       if (!lcpu->primary) {
+               return;
+       }
 
        enabled = ml_set_interrupts_enabled(FALSE);
 
        /* Calculate address of the HPET for this processor */
-       hpetVaddr = (uint64_t *)(((uint32_t)&(((hpetReg_t *)hpetArea)->TIM1_CONF)) + (cpu << 5));
+       hpetVaddr = (uint64_t *)(((uintptr_t)&(((hpetReg_t *)hpetArea)->TIM1_CONF)) + (cpu << 5));
        hpet = (hpetTimer_t *)hpetVaddr;
 
        DBG("ml_hpet_cfg: HPET for cpu %d at %p, vector = %d\n",
-            cpu, hpetVaddr, hpetVect);
+           cpu, hpetVaddr, hpetVect);
 
        /* Save the address and vector of the HPET for this processor */
        core->Hpet = hpet;
@@ -384,7 +388,6 @@ ml_hpet_cfg(uint32_t cpu, uint32_t hpetVect)
 int
 HPETInterrupt(void)
 {
-
        /* All we do here is to bump the count */
        x86_package()->HpetInt++;
 
@@ -403,8 +406,8 @@ static hpetReg_t saved_hpet;
 void
 hpet_save(void)
 {
-       hpetReg_t       *from = (hpetReg_t *) hpetArea;
-       hpetReg_t       *to = &saved_hpet;
+       hpetReg_t       *from = (hpetReg_t *) hpetArea;
+       hpetReg_t       *to = &saved_hpet;
 
        to->GEN_CONF  = from->GEN_CONF;
        to->TIM0_CONF = from->TIM0_CONF;
@@ -419,8 +422,8 @@ hpet_save(void)
 void
 hpet_restore(void)
 {
-       hpetReg_t       *from = &saved_hpet;
-       hpetReg_t       *to = (hpetReg_t *) hpetArea;
+       hpetReg_t       *from = &saved_hpet;
+       hpetReg_t       *to = (hpetReg_t *) hpetArea;
 
        /*
         * Is the HPET memory already enabled?
@@ -428,7 +431,7 @@ hpet_restore(void)
         */
        uint32_t *hptcp = (uint32_t *)(rcbaArea + 0x3404);
        uint32_t hptc = *hptcp;
-       if(!(hptc & hptcAE)) {
+       if (!(hptc & hptcAE)) {
                DBG("HPET memory is not enabled, "
                    "enabling and assigning to 0xFED00000 (hope that's ok)\n");
                *hptcp = (hptc & ~3) | hptcAE;
@@ -455,10 +458,10 @@ hpet_restore(void)
 uint64_t
 rdHPET(void)
 {
-       hpetReg_t               *hpetp = (hpetReg_t *) hpetArea;
-       volatile uint32_t       *regp = (uint32_t *) &hpetp->MAIN_CNT;
-       uint32_t                high;
-       uint32_t                low;
+       hpetReg_t               *hpetp = (hpetReg_t *) hpetArea;
+       volatile uint32_t       *regp = (uint32_t *) &hpetp->MAIN_CNT;
+       uint32_t                high;
+       uint32_t                low;
 
        do {
                high = *(regp + 1);
@@ -467,64 +470,3 @@ rdHPET(void)
 
        return (((uint64_t) high) << 32) | low;
 }
-
-#if MACH_KDB
-
-#define HI32(x)        ((uint32_t)(((x) >> 32) & 0xFFFFFFFF))
-#define LO32(x)        ((uint32_t)((x) & 0xFFFFFFFF))
-
-/*
- *     Displays HPET memory mapped area
- *     hp
- */
-void 
-db_hpet(__unused db_expr_t addr, __unused int have_addr, __unused db_expr_t count, __unused char *modif)
-{
-
-       db_display_hpet((hpetReg_t *) hpetArea);        /* Dump out the HPET
-                                                        * stuff */
-       return;
-}
-
-void
-db_display_hpet(hpetReg_t *hpt)
-{
-       uint64_t        cmain;
-
-       cmain = hpt->MAIN_CNT;  /* Get the main timer */
-
-       /* General capabilities */
-       db_printf("  GCAP_ID = %08X.%08X\n",
-                 HI32(hpt->GCAP_ID), LO32(hpt->GCAP_ID));
-       /* General configuration */
-       db_printf(" GEN_CONF = %08X.%08X\n",
-                 HI32(hpt->GEN_CONF), LO32(hpt->GEN_CONF));
-       /* General Interrupt status */
-       db_printf("GINTR_STA = %08X.%08X\n",
-                 HI32(hpt->GINTR_STA), LO32(hpt->GINTR_STA));
-       /* Main counter */
-       db_printf(" MAIN_CNT = %08X.%08X\n",
-                 HI32(cmain), LO32(cmain));
-       /* Timer 0 config and cap */
-       db_printf("TIM0_CONF = %08X.%08X\n",
-                 HI32(hpt->TIM0_CONF), LO32(hpt->TIM0_CONF));
-       /* Timer 0 comparator */
-       db_printf("TIM0_COMP = %08X.%08X\n",
-                 HI32(hpt->TIM0_COMP), LO32(hpt->TIM0_COMP));
-       /* Timer 1 config and cap */
-       db_printf("TIM0_CONF = %08X.%08X\n",
-                 HI32(hpt->TIM1_CONF), LO32(hpt->TIM1_CONF));
-       /* Timer 1 comparator */
-       db_printf("TIM1_COMP = %08X.%08X\n",
-                 HI32(hpt->TIM1_COMP), LO32(hpt->TIM1_COMP));
-       /* Timer 2 config and cap */
-       db_printf("TIM2_CONF = %08X.%08X\n",
-                 HI32(hpt->TIM2_CONF), LO32(hpt->TIM2_CONF));
-       /* Timer 2 comparator */
-       db_printf("TIM2_COMP = %08X.%08X\n",
-                 HI32(hpt->TIM2_COMP), LO32(hpt->TIM2_COMP));
-
-       db_printf("\nHPET Frequency = %d.%05dMHz\n",
-         (uint32_t) (hpetFreq / 1000000), (uint32_t) (hpetFreq % 1000000));
-}
-#endif