#author("2017-11-05T22:32:57+09:00","default:afuruta","afuruta")
#author("2017-11-05T22:37:44+09:00","default:afuruta","afuruta")
* HPET API [#be6692a3]
[[HPET API 日本語ページ>HPET API - 日本語版]]

Here shows HPET driver API. Using man page like format with some modifications. Following lines shows modifications, 
- "SYNOPSIS" shows with preferred, or fixed value argument.
- "PRECONDITION" shows conditions that application should satisfy before calling the API.
- "RETURN VALUE" and "ERROR" shows only HPET driver specification. To see basic system call specification, use man pages.
- "KERNEL CONFIGURATION and PARAMETER" shows some conditions at kernel building and kernel booting affected to API behavior. 
- "KERNEL SOURCE" shows related kernel source code. 

** Features [#w04c2733]
HPET driver provides following features.
- [[Allocate HPET timer.>#td026212]]
- [[Get timer information.>#pdce19e5]]
- [[Set interrupt frequency.>#bd9cfaa7]]
- [[Enable>#m7832c4e]]/[[disable>#y3465016]] hardware implemented periodic interrupt.&br;(Select hardware implemented, or software implemented periodic interrupt.)
- [[Enable>#ma83f3b9]]/[[disable>#rcb4bb60]] timer interrupt.
- Event to poll()/select() waiter at timer interrupt. See [[HPET_IE_ON>#ma83f3b9]].
- Send signal at timer interrupt.Using fcntl() features. See [[F_SETOWN>#u578f126]], [[F_SETFL>#g6b699cd]], and [[FSET_OWN>#ub0566d7]]
- [[Read and clear interrupted count.>#x52e9d21]]
- [[mmap HPET register on memory address space>#g68651f3]].&br;(Optional, kernel build configuration CONFIG_HPET_MMAP enables this feature.)

To know more details [[refer to HPET specification>https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf]].
** Example [#nd179a17]
To know HPET (High Precision Event Timer) driver &ogfileone(/drivers/char/hpet.c); API, here is example application &ref(hpet_example - HPET sample Application/hpet_example.tar.gz);. This application program is based on &ogfileone(/Documentation/timers/hpet_example.c); with some modifications and additions.
To know HPET driver &ogfileone(/drivers/char/hpet.c); API, here is example application &ref(hpet_example - HPET sample Application/hpet_example.tar.gz);. This application program is based on &ogfileone(/Documentation/timers/hpet_example.c); with some modifications and additions.
** Device path [#cc1eca9f]
Most linux distributions enable HPET driver and prepare access node /dev/hpet. /dev/hpet is the character device node associated to major=10, minor=228 one of "misc device".
** Open device [#cc1eca9f]
To use HPET device, open /dev/hpet with file mode O_RDONLY. If there is a unused(free) HPET timer, assign a timer to opened file descriptor. A timer is one of timer circuit block in HPET block. HPET driver's ioctl() calls manipulate the timer assigned to file descriptor.
** Header files [#g51b6a6f]
To use HPET device from user space (Linux Application), include header files as follows.
#pre(soft){{
&span(ConsoleOut){#define _GNU_SOURCE};
&span(ConsoleOut){#include <features.h>};
&span(ConsoleOut){#include <sys/types.h>};
&span(ConsoleOut){#include <sys/stat.h>};
&span(ConsoleOut){#include <sys/ioctl.h>};
&span(ConsoleOut){#include <unistd.h>};
&span(ConsoleOut){#include <fcntl.h>};
&span(ConsoleOut){#include <linux/hpet.h>};
}}
If you wish to use poll(), include optional header file as follows.
#pre(soft){{
&span(ConsoleOut){#include <poll.h>};
}}
If you wish to use select(), include optional header files as follows.
#pre(soft){{
&span(ConsoleOut){#include <sys/time.h>};
&span(ConsoleOut){#include <sys/select.h>};
}}
If you wish to use signal(), include optional header file as follows.
#pre(soft){{
&span(ConsoleOut){#include <signal.h>};
}}
If you wish to use mmap(), include optional header file as follows.
#pre(soft){{
&span(ConsoleOut){#include <sys/mman.h>};
}}
If you wish to handle error, include optional header files as follows.
#pre(soft){{
&span(ConsoleOut){#include <string.h>}; /* strerror() */
&span(ConsoleOut){#include <errno.h>};  /* errno, Exxx macros. */
}}
** HPET driver's ioctl API [#ycda765a]
In this section shows HPET driver ioctl() API. HPET driver provides following ioctl() API.
|ioctl request number|description|h
|HPET_INFO|Get Information&br;int ioctl(int fd, HPET_INFO, /* out */ struct hpet_info *info);|
|HPET_IRQFREQ|Set Interrupt Frequency in Hz&br;int ioctl(int fd, HPET_IRQFREQ, unsigned long frequency);|
|HPET_EPI|Enable hardware periodic interrupt&br;int ioctl(int fd, HPET_EPI);|
|HPET_DPI|Disable hardware periodic interrupt&br;int ioctl(int fd, HPET_DPI);|
|HPET_IE_ON|Interrupt On&br;int ioctl(int fd, HPET_IE_ON);|
|HPET_IE_OFF|Interrupt Off&br;int ioctl(int fd, HPET_IE_OFF);|
Here shows HPET driver specific behaviors. To see basic file system ioctl() behaviors refer to [[man 2 ioctl>https://www.google.co.jp/search?num=100&newwindow=1&q=man+2+ioctl&oq=man+2+ioctl]].

*** HPET_INFO - Get Information [#pdce19e5]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){struct hpet_info {};
&span(ConsoleOut){	unsigned long  hi_ireqfreq; /* Period or time in Hz */};
&span(ConsoleOut){	unsigned long  hi_flags;    /* Information: 0x0: Not supported periodic int., 0x10: Supported periodic int. */};
&span(ConsoleOut){	unsigned short hi_hpet;     /* HPET device number, [0..TheNumberOfHPETDevicesInPlatform-1] */};
&span(ConsoleOut){	unsigned short hi_timer;    /* Timer number in HPET device, [0..31] */};
&span(ConsoleOut){};};
&span(ConsoleOut){int ioctl(int fd, HPET_INFO, /* out */ struct hpet_info *info);};
}}
- ''DESCRIPTION''&br;
Get the timer information assigned to file descriptor fd. ioctl call with HPET_INFO stores timer information to *info. This ioctl call fills hpet_info members as follows.
|member|description|h
|hi_ireqfreq|Interrupt frequency in Hz.|
|hi_flags|Timer capability. The value will be as follows,&br;''0x00UL'' This timer doesn't have hardware implemented periodic interrupt.&br;''0x10UL'' This timer has hardware implemented periodic interrupt.|
|hi_hpet|HPET device number on platform. It satisfies (hi_hpet >= 0) && (hi_hpet < M), where M is the number of HPET devices (circuit blocks) on platform. |
|hi_timer|Timer number in HPET device. It satisfies (hi_timer >= 0) && (hi_timer < N), where N is the number of timers in HPET device and N <= 32.&br;''NOTE: ''You may see {hi_hpet, hi_timer} == {0, 2} at first opened HPET timer, because the timer 0 and timer 1 replaces PIT(programmable Interval Timer) and RTC(Real Time Clock).|
- ''RETURN VALUE''
-- ''0:'' Success
-- ''-1:'' Error
- ''ERRORS''
-- ''EBADF:'' Invalid file descriptor fd.
-- ''EFAULT:'' info points an inaccessible memory area.
- ''KERNEL SOURCE''&br;
&ogrefs(HPET_INFO,HPET_INFO,hpet.c);
*** HPET_IRQFREQ - Set Interrupt Frequency in Hz [#bd9cfaa7]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int ioctl(int fd, HPET_IRQFREQ, unsigned long frequency);};
}}
- ''PRECONDITION''&br;
-- Disabling timer interrupt, HPET_IE_OFF.
- ''DESCRIPTION''&br;
Set interrupt frequency to timer assigned to file descriptor fd. Specify frequency in Hz. If process hasn't CAP_SYS_RESOURCE capability, frequency is limited less or equal to the value read from /proc/sys/dev/hpet/max-user-freq. The default value read from max-user-freq is 64 (==&ogdefs(HPET_USER_FREQ);).&br;
Don't update frequency while enabling interrupt.
- ''RETURN''&br;
-- ''0:'' Success
-- ''-1:'' Error
- ''ERRORS''
-- ''EACCESS'' Process doesn't have capability &ogdefs(CAP_SYS_RESOURCE); and try to set frequency more than the value read from /proc/sys/dev/hpet/max-user-freq. The default value read from max-user-freq is 64 (==&ogdefs(HPET_USER_FREQ);).
-- ''EINVAL:'' Frequency is zero.
- ''FILES''&br;
-- /proc/sys/dev/hpet/max-user-freq
- ''KERNEL SOURCE''&br;
&ogrefs(HPET_IRQFREQ,HPET_IRQFREQ,hpet.c);, &ogdefs(hpet_max_freq);, &ogdefs(HPET_USER_FREQ);, &ogdefs(hpet_interrupt());
*** HPET_EPI - Enable hardware periodic interrupt [#m7832c4e]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int ioctl(int fd, HPET_EPI);};
}}
- ''PRECONDITION''&br;
-- Disabling timer interrupt, HPET_IE_OFF.
- ''DESCRIPTION''&br;
Enable hardware implemented periodic interrupt at the timer assigned to file descriptor fd, and disable software assisted periodic interrupt. Call HPET_EPI ioctl() before enabling timer interrupt HPET_IE_ON.
- ''RETURN VALUE''&br;
-- ''0:'' Success
-- ''-1:'' Error
- ''ERRORS''
-- ''EBADF:'' Invalid file descriptor fd.
-- ''ENXIO:'' The timer's hardware assigned to file descriptor fd doesn't support periodic interrupt.
- ''KERNEL SOURCE''&br;
&ogrefs(HPET_EPI,HPET_EPI,hpet.c);
*** HPET_DPI - Disable hardware periodic interrupt [#y3465016]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int ioctl(int fd, HPET_DPI);};
}}
- ''PRECONDITION''&br;
-- Disabling timer interrupt, HPET_IE_OFF.
- ''DESCRIPTION''&br;
Disable hardware implemented periodic interrupt at the timer assigned to file descriptor fd, and enable software assisted periodic interrupt. Call HPET_DPI ioctl() before enabling timer interrupt HPET_IE_ON. &br;
When using HPET timer with HPET_DPI (disabling hardware periodic interrupt), HPET driver updates interrupt time in interrupt handler. So timer interrupts periodically and interrupt period includes software response time delay.
- ''RETURN VALUE''&br;
-- ''0:'' Success
-- ''-1:'' Error
- ''ERRORS''
-- ''EBADF:'' Invalid file descriptor fd.
-- ''ENXIO:'' The timer's hardware assigned to file descriptor fd doesn't support periodic interrupt.
- ''KERNEL SOURCE''&br;
&ogrefs(HPET_DPI,HPET_DPI,hpet.c);, &ogdefs(hpet_interrupt());
***  HPET_IE_ON - Interrupt On [#ma83f3b9]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int ioctl(int fd, HPET_IE_ON);};
}}
- ''PRECONDITION''&br;
-- Set interrupt frequency by HPET_IRQFREQ.
-- Enable or disable hardware implemented periodic interrupt by HPET_EPI or HPET_DPI.
- ''DESCRIPTION''&br;
Enable timer interrupt assigned to file descriptor fd. When the timer interrupts a processor, file descriptor fd becomes ready with event (POLLIN | POLLRDNORM) and also sends signal if a process sets file status flag O_ASYNC, valid owner, and signal number to fd.
- ''RETURN VALUE''
-- ''0:'' Success
-- ''-1:'' Error
- ''ERRORS''
-- ''EBADF:'' Invalid file descriptor fd.
-- ''EIO:'' It occurs one of following conditions.
--- Invalid interrupt frequency.
--- Interrupt frequency has not been set.
--- Can't request IRQ handler. It may chipset or BIOS bug.
-- ''EBUSY''
--- Already enabled interrupt.
- ''KERNEL SOURCE''&br;
&ogrefs(HPET_IE_ON,HPET_IE_ON,hpet.c);, &ogdefs(hpet_interrupt());
*** HPET_IE_OFF - Interrupt Off[#rcb4bb60]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int ioctl(int fd, HPET_IE_OFF);};
}}
- ''DESCRIPTION''&br;
Disable timer interrupt assigned to file descriptor fd.
- ''RETURN VALUE''
-- ''0:'' Success
-- ''-1:'' Error
- ''ERRORS''
-- ''EBADF:'' Invalid file descriptor fd.
- ''KERNEL SOURCE''&br;
&ogrefs(HPET_IE_OFF,HPET_IE_OFF,hpet.c);
** File System and Memory Mapping API related to HPET [#xcd77816]
In this section shows File System and Memory Mapping API related to HPET driver. When using open(), close(), read(), mmap(), munmap(), fcntl(), and these alternate functions to access HPET, these API have HPET specific behaviour. Here shows 
HPET specific behavior. To see file system specific basic behavior and details, refer to system call man pages. [[man 2 fcntl>https://www.google.co.jp/search?num=100&newwindow=1&q=man+2+fcntl&oq=man+2+fcntl]] shows about sending signal from file descriptor in detail.
*** open HPET timer [#td026212]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int open(const char *hpet_path, /* open mode */ O_RDONLY);};
}}
- ''DESCRIPTION''&br;
Open a unused HPET timer. On most linux distributions, hpet_path may be "/dev/hpet". It is the character device node major = 10, minor = 228. If there is no unused HPET timer, open fails with the error EBUSY. Use O_RDONLY as open mode.
- ''RETURN VALUE''
-- ''return_value >= 0:'' File descriptor assigned HPET timer.
-- ''-1:'' Error.
- ''ERROR (HPET device specific)''
-- ''EINVAL:'' Open mode contains write mode.
-- ''EBUSY:'' There is no unised HPET timer, or all HPET timer in use.
- ''FILES''
-- /dev/hpet
- ''KERNEL SOURCE''
-- &ogdefs(hpet_open());
*** close HPET timer [#q45d3eac]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int close(int fd);};
}}
- ''DESCRIPTION''&br;
Close the HPET timer assigned to file descriptor fd. Release the timer from fd, the timer will be unused. Strictly speaking, the timer will be released at no one refers to fd. Duplicating fd, and mapping fd to memory add reference to fd. At releasing the timer from fd, do the following procedures. 
-- Disable interrupt from the timer.
-- Disable hardware implemented periodic interrupt.
-- Free IRQ handler.
- ''KERNEL SOURCE''
-- &ogdefs(hpet_release());
*** read and clear interrupted count [#x52e9d21]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int read(int fd, unsigned long *buf, /* size */ sizeof(unsigned long));};
}}
- ''DESCRIPTION''&br;
Read and clear interrupt count. The count value is stored to *buf. Use sizeof(unsigned long) as size argument. size may be grater or equal to sizeof(unsigned long). But return value (the number of read bytes) is always equal to sizeof(unsigned long) on success.
-- If open HPET timer with O_NONBLOCK file status flag, read() does as follows.
--- If interrupt has been occurred during from previous read() call to now, store interrupt count to *buf and return.
--- If interrupt has not been occurred during  from previous read() call to now, read() fails with EAGAIN error.
-- If open HPET timer without O_NONBLOCK file status flag, read() does as follows.
--- If interrupt has been occurred during from previous read() call to now, store interrupt count to *buf and return.
--- If interrupt has not been occurred during  from previous read() call to now, read() blocks until interrupt occurs. 
- ''RETURN VALUE''
-- ''sizeof(unsigned long):'' Success read.
-- ''-1:'' Error.
- ''ERROR (HPET device specific)''
-- ''EIO:'' Interrupt frequency has not been set.
-- ''EFAULT:'' buf doesn't points accessible address space.
-- ''EINVAL:'' size is less than sizeof(unsigned long).
-- ''EAGAIN:'' Interrupt hasn't been occurred during form previous read() call to now.
-- ''EINTR:'' Caught signal.
- ''KERNEL SOURCE''&br;
&ogdefs(hpet_read());
*** mmap HPET register on memory address space [#g68651f3]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){void *mmap(void *addr, size_t length, int prot, int flags, int fd, /* offset */ 0);};
&span(ConsoleOut){int munmap(void *addr, size_t length);};
}}
- ''DESCRIPTION''&br;
mmap() and munmap() HPET registers which has the timer assigned to file descriptor fd. This call maps/unmaps whole HPET block not only the timer to memory address space. When mmap() returns valid pointer, the pointer points HPET "General Capabilities and ID Register".&br;
Valid length range is [ 0x1 .. page size (equal to sysconf(_SC_PAGESIZE)) ], but it maps HPET registers (and may containing other device(s) registers) ranged page size or more to memory address space.&br;
offset should be zero.
- ''RETURN VALUE ''
-- ''return_value != MAP_FAILED:'' Returned pointer points HPET "General Capabilities and ID Register"
-- ''MAP_FAILED:'' Can't map HPET register.
- ''ERROR (HPET device specific)''
-- ''EACCESS:'' Not enabled mmap feature. Kernel was built without CONFIG_HPET_MMAP_DEFAULT, or kernel booted with "hpet_mmap=0". To enable HPET mmap feature, Add kernel parameter "hpet_mmap=1".
-- ''ENOSYS:''
--- Kernel doesn't have HPET mmap function. Kernel was built without CONFIG_HPET_MMAP. This error also means that the kernel boot parameter "hpet_mmap=1" can't enable HPET mmap feature.
--- HPET hardware implementation issue, HPET registers is not aligned to page boundary.
- ''KERNEL CONFIGURATION and PARAMETER''&br;
To use HPET mmap feature, satisfy following two conditions.
-- Build kernel with CONFIG_HPET_MMAP=y.
-- Add "hpet_mmap=1" to kernel parameter, if distributor or you built kernel without CONFIG_HPET_MMAP_DEFAULT=y.
- ''SEE ALSO''
-- [[HPET specification>https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf]].
- ''KERNEL SOURCE''&br;
&ogdefs(hpet_mmap());

*** F_GETOWN - Get file descriptor owner[#sb3baf92]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int fcntl(int fd, F_GETOWN);};
}}
- ''DESCRIPTION''&br;
Get owner assigned to file descriptor fd.
- ''RETURN VALUE''&br;
-- ''0:'' no owner, it doesn't send signal.
-- ''return_value > 0:'' process id number.
-- ''return_value < 0:'' Negative process group number. Be careful, it may treated as an error. It is better to use F_GETOWN_EX.
- ''KERNEL SOURCE''&br;
&ogrefs(F_GETOWN,F_GETOWN,fcntl.c);
*** F_GETOWN_EX - Get file descriptor owner with extended feature [#fff26c5c]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){struct f_owner_ex {};
&span(ConsoleOut){  int    type; /* F_OWNER_PID, F_OWNER_PGRP, or     F_OWNER_TID */};
&span(ConsoleOut){  pid_t  pid;  /* process id,  process group id, or thread id. */};
&span(ConsoleOut){&#125;};
&span(ConsoleOut){int fcntl(int fd, F_GETOWN_EX, /* out */ struct f_owner_ex *owner_ex);};
}}
- ''DESCRIPTION''&br;
Get owner assigned to file descriptor fd. fcntl() F_GETOWN_EX call stores result in *owner_ex. See more details in  F_SETOWN_EX.
- ''KERNEL SOURCE''&br;
&ogrefs(F_GETOWN_EX,F_GETOWN_EX,fcntl.c);
*** F_SETOWN - Set file descriptor owner [#u578f126]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int fcntl(int fd, F_SETOWN, int owner);};
}}
- ''DESCRIPTION''&br;
Set owner to file descriptor fd. owner is process id, or negative process group id. When the timer assigned to fd interrupts a processor and the fd's file status flags has been ORed with O_ASYNC, a signal is sent to owner.
- ''KERNEL SOURCE''&br;
&ogrefs(F_SETOWN,F_SETOWN,fcntl.c);
*** F_SETOWN_EX - Set file descriptor owner with extended feature [#rf3b6390]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){struct f_owner_ex {};
&span(ConsoleOut){  int    type; /* F_OWNER_PID, F_OWNER_PGRP, or     F_OWNER_TID */};
&span(ConsoleOut){  pid_t  pid;  /* process id,  process group id, or thread id. */};
&span(ConsoleOut){&#125;};
&span(ConsoleOut){int fcntl(int fd, F_GETOWN_EX, /* in */ struct f_owner_ex *owner_ex);};
}}
- ''DESCRIPTION''&br;
Set one of process id, process group id, or thread id to file descriptor fd. type specifies pid containing which id. type should be one of F_OWNER_PID (process id), F_OWNER_PGRP (process group id), or F_OWNER_TID (thread id), and set process, process group, or thread id to pid.&br;
When the timer assigned to fd interrupts a processor and the fd's file status flags has been ORed with O_ASYNC, a signal is sent to pid.
- ''KERNEL SOURCE''&br;
&ogrefs(F_SETOWN_EX,F_SETOWN_EX,fcntl.c);
*** F_GETFL - Get file status flags [#yc1882fd]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int fcntl(int fd, F_GETFL);};
}}
- ''DESCRIPTION''&br;
Use this function to set or clear O_ASYNC flag to file descriptor fd. See the description of F_SETFL.
- ''KERNEL SOURCE''&br;
&ogrefs(F_GETFL,F_GETFL,fcntl.c);
*** F_SETFL - Set file status flags [#g6b699cd]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int fcntl(int fd, F_SETFL, int flags);};
}}
- ''DESCRIPTION''&br;
To send signal on timer interrupt, let flags be ORed with O_ASYNC, see following pseudo code piece.
#code(c){{
{	int	flags;
	flags = fcntl(fd, F_GETFL);
	if (flags < 0) {
		/* error handling. */
	}
	flags |= O_ASYNC;
	if (fcntl(fd, F_SETFL, flags) != 0) {
		/* error handling. */
	}
}
}}
- ''KERNEL SOURCE''&br;
&ogrefs(F_SETFL,F_SETFL,fcntl.c);, &ogdefs(setfl());, #define O_ASYNC &ogdefs(FASYNC);
*** F_GETSIG - Get signal number will be sent[#zfddc3a9]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int fcntl(int fd, F_GETSIG);};
}}
- ''DESCRIPTION''&br;
Get the signal number will be sent on timer interrupt.
- ''KERNEL SOURCE''&br;
&ogrefs(F_GETSIG,F_GETSIG,fcntl.c);
*** F_SETSIG - Set signal number will be sent[#ub0566d7]
- ''SYNOPSIS''
#pre(soft){{
&span(ConsoleOut){int fcntl(int fd, F_SETSIG, int signal);};
}}
- ''DESCRIPTION''&br;
Set the signal number will be sent on timer interrupt.
- ''KERNEL SOURCE''&br;
&ogrefs(F_SETSIG,F_SETSIG,fcntl.c);, &ogdefs(send_sigio());

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS