10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*4551Ssudheer * Common Development and Distribution License (the "License"). 6*4551Ssudheer * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*4551Ssudheer * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * tod driver module for Starfire 310Sstevel@tonic-gate * This module implements a soft tod since 320Sstevel@tonic-gate * starfire has no tod part. 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <sys/types.h> 360Sstevel@tonic-gate #include <sys/param.h> 370Sstevel@tonic-gate #include <sys/sysmacros.h> 380Sstevel@tonic-gate #include <sys/systm.h> 390Sstevel@tonic-gate #include <sys/errno.h> 400Sstevel@tonic-gate #include <sys/modctl.h> 410Sstevel@tonic-gate #include <sys/autoconf.h> 420Sstevel@tonic-gate #include <sys/debug.h> 430Sstevel@tonic-gate #include <sys/clock.h> 440Sstevel@tonic-gate #include <sys/cmn_err.h> 450Sstevel@tonic-gate #include <sys/promif.h> 460Sstevel@tonic-gate #include <sys/cpuvar.h> 470Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h> 480Sstevel@tonic-gate #include <starfire/sys/cpu_sgn.h> 490Sstevel@tonic-gate 500Sstevel@tonic-gate static timestruc_t todsf_get(void); 510Sstevel@tonic-gate static void todsf_set(timestruc_t); 520Sstevel@tonic-gate static uint_t todsf_set_watchdog_timer(uint_t); 530Sstevel@tonic-gate static uint_t todsf_clear_watchdog_timer(void); 540Sstevel@tonic-gate static void todsf_set_power_alarm(timestruc_t); 550Sstevel@tonic-gate static void todsf_clear_power_alarm(void); 560Sstevel@tonic-gate static uint64_t todsf_get_cpufrequency(void); 570Sstevel@tonic-gate 580Sstevel@tonic-gate /* 590Sstevel@tonic-gate * Module linkage information for the kernel. 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate static struct modlmisc modlmisc = { 620Sstevel@tonic-gate &mod_miscops, "Soft tod module for Starfire %I%" 630Sstevel@tonic-gate }; 640Sstevel@tonic-gate 650Sstevel@tonic-gate static struct modlinkage modlinkage = { 660Sstevel@tonic-gate MODREV_1, (void *)&modlmisc, NULL 670Sstevel@tonic-gate }; 680Sstevel@tonic-gate 690Sstevel@tonic-gate int 700Sstevel@tonic-gate _init(void) 710Sstevel@tonic-gate { 720Sstevel@tonic-gate if (strcmp(tod_module_name, "todstarfire") == 0) { 730Sstevel@tonic-gate int ssp_time32; 740Sstevel@tonic-gate char obp_string[40]; 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* Set the string to pass to OBP */ 770Sstevel@tonic-gate (void) sprintf(obp_string, "h# %p unix-gettod", 78*4551Ssudheer (void *)&ssp_time32); 790Sstevel@tonic-gate 800Sstevel@tonic-gate /* Get OBP to get TOD from ssp */ 810Sstevel@tonic-gate prom_interpret(obp_string, 0, 0, 0, 0, 0); 820Sstevel@tonic-gate 830Sstevel@tonic-gate hrestime.tv_sec = (time_t)ssp_time32; 840Sstevel@tonic-gate 850Sstevel@tonic-gate tod_ops.tod_get = todsf_get; 860Sstevel@tonic-gate tod_ops.tod_set = todsf_set; 870Sstevel@tonic-gate tod_ops.tod_set_watchdog_timer = todsf_set_watchdog_timer; 880Sstevel@tonic-gate tod_ops.tod_clear_watchdog_timer = todsf_clear_watchdog_timer; 890Sstevel@tonic-gate tod_ops.tod_set_power_alarm = todsf_set_power_alarm; 900Sstevel@tonic-gate tod_ops.tod_clear_power_alarm = todsf_clear_power_alarm; 910Sstevel@tonic-gate tod_ops.tod_get_cpufrequency = todsf_get_cpufrequency; 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 940Sstevel@tonic-gate * Flag warning if user tried to use hardware watchdog 950Sstevel@tonic-gate */ 960Sstevel@tonic-gate if (watchdog_enable) { 970Sstevel@tonic-gate cmn_err(CE_WARN, "Hardware watchdog unavailable"); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate } 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate return (mod_install(&modlinkage)); 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate int 1050Sstevel@tonic-gate _fini(void) 1060Sstevel@tonic-gate { 1070Sstevel@tonic-gate if (strcmp(tod_module_name, "todstarfire") == 0) 1080Sstevel@tonic-gate return (EBUSY); 1090Sstevel@tonic-gate else 1100Sstevel@tonic-gate return (mod_remove(&modlinkage)); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate int 1140Sstevel@tonic-gate _info(struct modinfo *modinfop) 1150Sstevel@tonic-gate { 1160Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate /* 1210Sstevel@tonic-gate * Simply return hrestime value 1220Sstevel@tonic-gate * Must be called with tod_lock held. 1230Sstevel@tonic-gate */ 1240Sstevel@tonic-gate static timestruc_t 1250Sstevel@tonic-gate todsf_get(void) 1260Sstevel@tonic-gate { 1270Sstevel@tonic-gate timestruc_t ts; 1280Sstevel@tonic-gate extern cpu_sgnblk_t *cpu_sgnblkp[]; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate ts = hrestime; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate /* Update the heartbeat */ 1350Sstevel@tonic-gate if (cpu_sgnblkp[CPU->cpu_id] != NULL) 1360Sstevel@tonic-gate cpu_sgnblkp[CPU->cpu_id]->sigb_heartbeat++; 1370Sstevel@tonic-gate return (ts); 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate /* 1410Sstevel@tonic-gate * Null function for now. 1420Sstevel@tonic-gate * Must be called with tod_lock held. 1430Sstevel@tonic-gate */ 1440Sstevel@tonic-gate /* ARGSUSED */ 1450Sstevel@tonic-gate static void 1460Sstevel@tonic-gate todsf_set(timestruc_t ts) 1470Sstevel@tonic-gate { 1480Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate /* 1530Sstevel@tonic-gate * No watchdog function. 1540Sstevel@tonic-gate */ 1550Sstevel@tonic-gate /* ARGSUSED */ 1560Sstevel@tonic-gate static uint_t 1570Sstevel@tonic-gate todsf_set_watchdog_timer(uint_t timeoutval) 1580Sstevel@tonic-gate { 1590Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 1600Sstevel@tonic-gate return (0); 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate /* 1640Sstevel@tonic-gate * No watchdog function 1650Sstevel@tonic-gate */ 1660Sstevel@tonic-gate static uint_t 1670Sstevel@tonic-gate todsf_clear_watchdog_timer(void) 1680Sstevel@tonic-gate { 1690Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 1700Sstevel@tonic-gate return (0); 1710Sstevel@tonic-gate } 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* 1740Sstevel@tonic-gate * Null function. 1750Sstevel@tonic-gate */ 1760Sstevel@tonic-gate /* ARGSUSED */ 1770Sstevel@tonic-gate static void 1780Sstevel@tonic-gate todsf_set_power_alarm(timestruc_t ts) 1790Sstevel@tonic-gate { 1800Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate /* 1840Sstevel@tonic-gate * Null function 1850Sstevel@tonic-gate */ 1860Sstevel@tonic-gate static void 1870Sstevel@tonic-gate todsf_clear_power_alarm() 1880Sstevel@tonic-gate { 1890Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tod_lock)); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* 1930Sstevel@tonic-gate * Get clock freq from the cpunode 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate uint64_t 1960Sstevel@tonic-gate todsf_get_cpufrequency(void) 1970Sstevel@tonic-gate { 1980Sstevel@tonic-gate return (cpunodes[CPU->cpu_id].clock_freq); 1990Sstevel@tonic-gate } 200