/* Get frequency of the system processor. sparc64 version. Copyright (C) 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include #include #include #include #include #include static hp_timing_t __get_clockfreq_via_cpuinfo (void) { hp_timing_t result; int fd; result = 0; fd = open ("/proc/cpuinfo", O_RDONLY); if (fd != -1) { char buf[8192]; ssize_t n; n = read (fd, buf, sizeof buf); if (n > 0) { char *mhz = memmem (buf, n, "Cpu0ClkTck", 7); if (mhz != NULL) { char *endp = buf + n; /* Search for the beginning of the string. */ while (mhz < endp && (*mhz < '0' || *mhz > '9') && (*mhz < 'a' || *mhz > 'f') && *mhz != '\n') ++mhz; while (mhz < endp && *mhz != '\n') { if ((*mhz >= '0' && *mhz <= '9') || (*mhz >= 'a' && *mhz <= 'f')) { result <<= 4; if (*mhz >= '0' && *mhz <= '9') result += *mhz - '0'; else result += (*mhz - 'a') + 10; } ++mhz; } } } close (fd); } return result; } static hp_timing_t __get_clockfreq_via_proc_openprom (void) { hp_timing_t result; int obp_fd; result = 0; obp_fd = open ("/proc/openprom", O_RDONLY); if (obp_fd != -1) { unsigned long int buf[4096 / sizeof (unsigned long int)]; struct dirent *dirp = (struct dirent *) buf; off_t dbase = (off_t) 0; ssize_t len; while ((len = getdirentries (obp_fd, (char *) dirp, sizeof (buf), &dbase)) > 0) { struct dirent *this_dirp = dirp; while (len > 0) { char node[strlen ("/proc/openprom/") + _D_ALLOC_NAMLEN (this_dirp) + strlen ("/clock-frequency")]; char *prop; int fd; /* Note that strlen("/clock-frequency") > strlen("/device_type") */ __stpcpy (prop = __stpcpy (__stpcpy (node, "/proc/openprom/"), this_dirp->d_name), "/device_type"); fd = open (node, O_RDONLY); if (fd != -1) { char type_string[128]; int ret; ret = read (fd, type_string, sizeof (type_string)); if (ret > 0 && strncmp (type_string, "'cpu'", 5) == 0) { int clkfreq_fd; __stpcpy (prop, "/clock-frequency"); clkfreq_fd = open (node, O_RDONLY); if (fd != -1) { if (read (clkfreq_fd, type_string, sizeof (type_string)) > 0) result = (hp_timing_t) strtoull (type_string, NULL, 16); close (clkfreq_fd); } } close (fd); } if (result != 0) break; len -= this_dirp->d_reclen; this_dirp = (struct dirent *) ((char *) this_dirp + this_dirp->d_reclen); } if (result != 0) break; } close (obp_fd); } return result; } static hp_timing_t __get_clockfreq_via_dev_openprom (void) { hp_timing_t result; int obp_dev_fd; result = 0; obp_dev_fd = open ("/dev/openprom", O_RDONLY); if (obp_dev_fd != -1) { char obp_buf[8192]; struct openpromio *obp_cmd = (struct openpromio *)obp_buf; int ret; obp_cmd->oprom_size = sizeof (obp_buf) - sizeof (unsigned int); *(int *) obp_cmd->oprom_array = 0; ret = ioctl (obp_dev_fd, OPROMCHILD, (char *) obp_cmd); if (ret == 0) { int cur_node = *(int *) obp_cmd->oprom_array; while (cur_node != 0 && cur_node != -1) { obp_cmd->oprom_size = sizeof (obp_buf) - sizeof (unsigned int); strcpy (obp_cmd->oprom_array, "device_type"); ret = ioctl (obp_dev_fd, OPROMGETPROP, (char *) obp_cmd); if (ret == 0 && strncmp (obp_cmd->oprom_array, "cpu", 3) == 0) { obp_cmd->oprom_size = (sizeof (obp_buf) - sizeof (unsigned int)); strcpy (obp_cmd->oprom_array, "clock-frequency"); ret = ioctl (obp_dev_fd, OPROMGETPROP, (char *) obp_cmd); if (ret == 0) result = (hp_timing_t) *(unsigned int *) obp_cmd->oprom_array; } obp_cmd->oprom_size = sizeof (obp_buf) - sizeof (unsigned int); *(int *) obp_cmd->oprom_array = cur_node; ret = ioctl (obp_dev_fd, OPROMNEXT, (char *) obp_cmd); if (ret < 0) break; cur_node = *(int *)obp_cmd->oprom_array; } } } return result; } hp_timing_t __get_clockfreq (void) { static hp_timing_t result; /* If this function was called before, we know the result. */ if (result != 0) return result; /* We first read the information from the /proc/cpuinfo file. It contains at least one line like Cpu0ClkTick : 000000002cb41780 We search for this line and convert the number in an integer. */ result = __get_clockfreq_via_cpuinfo (); if (result != 0) return result; /* If that did not work, try to find an OpenPROM node with device_type equal to 'cpu' using /dev/openprom and fetch the clock-frequency property from there. */ result = __get_clockfreq_via_dev_openprom (); if (result != 0) return result; /* Finally, try the same lookup as above but using /proc/openprom. */ result = __get_clockfreq_via_proc_openprom (); return result; }