* 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,
* 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;
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;
}
/*
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;
}
/*
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);
}
/*
void
hpet_init(void)
{
- unsigned int *xmod;
+ unsigned int *xmod;
map_rcbaArea();
* 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;
*/
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.
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)
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
}
/*
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;
}
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);
}
/*
* 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;
int
HPETInterrupt(void)
{
-
/* All we do here is to bump the count */
x86_package()->HpetInt++;
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;
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?
*/
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;
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);
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