From owner-acpi-jp@jp.freebsd.org  Tue Jul 31 13:48:04 2001
Received: (from daemon@localhost)
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) id NAA25620;
	Tue, 31 Jul 2001 13:48:04 +0900 (JST)
	(envelope-from owner-acpi-jp@jp.FreeBSD.org)
Received: from shidahara1.planet.sci.kobe-u.ac.jp (shidahara1.planet.sci.kobe-u.ac.jp [133.30.50.200])
	by castle.jp.freebsd.org (8.9.3+3.2W/8.7.3) with ESMTP id NAA25615
	for <acpi-jp@jp.freebsd.org>; Tue, 31 Jul 2001 13:48:03 +0900 (JST)
	(envelope-from takawata@shidahara1.planet.sci.kobe-u.ac.jp)
Received: from shidahara1.planet.sci.kobe-u.ac.jp (localhost [127.0.0.1])
	by shidahara1.planet.sci.kobe-u.ac.jp (8.9.3/8.9.3) with ESMTP id NAA16589
	for <acpi-jp@jp.freebsd.org>; Tue, 31 Jul 2001 13:55:59 +0900 (JST)
	(envelope-from takawata@shidahara1.planet.sci.kobe-u.ac.jp)
Message-Id: <200107310455.NAA16589@shidahara1.planet.sci.kobe-u.ac.jp>
To: acpi-jp@jp.freebsd.org
Date: Tue, 31 Jul 2001 13:55:59 +0900
From: Takanori Watanabe <takawata@shidahara1.planet.sci.kobe-u.ac.jp>
Reply-To: acpi-jp@jp.freebsd.org
Precedence: list
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+010328
X-Sequence: acpi-jp 1202
Subject: [acpi-jp 1202] kqueue stuff(revised)
Errors-To: owner-acpi-jp@jp.freebsd.org
Sender: owner-acpi-jp@jp.freebsd.org
X-Originator: takawata@shidahara1.planet.sci.kobe-u.ac.jp

This is revised version of kqueue stuff as I mentioned before.

In this patch event source is distinguished by kevent.fflags member.
(kevent.fflags&ACPI_KNMASK_DEV) means event source and
(kevent.fflags&ACPI_KNMASK_EVENT) means the event that occurs.
Kevent will come when (kevent.fflags&ACPI_KNMASK_DEV) and the 
(event&ACPI_KNMASK_DEV) is completely match and 
kevent.fflags&event&ACPI_KNMASK_EVENT is not 0 .
ACPI_KNDEV_SYSTEM is used for system event.
This can wait 
ACPI_KNOTE_ACAD (AC adapter event),
ACPI_KNOTE_LID (LID event),
ACPI_KNOTE_POWERBUTTON (power button event),
ACPI_KNOTE_SLEEPBUTTON (sleep button event),
and ACPI_KNOTE_WAKEUP (wake up event).

ACPI_KNDEV_BATTERY|<unit no(up to ACPI_KNDEV_UNIT)> is used for wait battery 
<unit no> event.
This can wait ACPI_KNOTE_BATTSTAT(battery status change) and 
ACPI_KNOTE_BATTINFO(battery infomation change).

ACPI_KNDEV_THRM|<unit no(up to ACPI_KNDEV_UNIT)> is used for wait thermal zone
<unit no> event.
This can wait ACPI_KNOTE_THRM (thermal tripping point reached) and
ACPI_KNOTE_THRMINFO(thermal tripping point setting is changed).

note that different ACPI_KNDEV requires different file discriptor.

Comment?

$BEOJUB:5*(B
$B?@8MBg3XBg3X1!<+A32J3X8&5f2J(BD3$B>pJs%a%G%#%"2J3X@l96(B
<a href="http://www.planet.sci.kobe-u.ac.jp/~takawata/key.html">
Public Key</a>
Key fingerprint =  2C 51 E2 78 2C E1 C5 2D  0F F1 20 A3 11 3A 62 2A 


sample code

#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <fcntl.h>
#include <dev/acpica/acpiio.h>

main()
{
	int kq,fd[3];
	struct kevent ev[3];
	int data,udata;
	int res,i;
	kq = kqueue();
	for(i=0;i<3;i++){
	  fd[i] = open("/dev/acpi",O_RDONLY);
	}
	/*
	 * You must use different file descriptor as identifier to wait event
	 * belong to different ACPI_KNDEV.
	 */	
	EV_SET(&ev[0], fd[0], EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR,
	       ACPI_KNDEV_SYSTEM|ACPI_KNMASK_EVENT,0,NULL);
	EV_SET(&ev[1], fd[1], EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR,
	       ACPI_KNDEV_BATT|0|ACPI_KNMASK_EVENT,0,NULL);
	EV_SET(&ev[2], fd[2], EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR,
	       ACPI_KNDEV_THRM|0|ACPI_KNMASK_EVENT,0,NULL);
	kevent(kq,ev,3,NULL,0,NULL);
	for(;;){ 
		res = kevent(kq,NULL,0,ev,3,NULL);
		for(i=0;i<res;i++){
		  printf("%x\n",ev[i].fflags);
		}
	}  
}



Index: acpi.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi.c,v
retrieving revision 1.28
diff -u -r1.28 acpi.c
--- acpi.c	2001/07/30 08:59:43	1.28
+++ acpi.c	2001/07/31 03:09:51
@@ -67,6 +67,9 @@
 static d_open_t		acpiopen;
 static d_close_t	acpiclose;
 static d_ioctl_t	acpiioctl;
+static int acpikqfilter (dev_t, struct knote *);
+static int  filt_acpi(struct knote *, long );
+static void filt_acpidetach(struct knote *);
 
 #define CDEV_MAJOR 152
 static struct cdevsw acpi_cdevsw = {
@@ -82,7 +85,8 @@
     CDEV_MAJOR,
     nodump,
     nopsize,
-    0
+    D_KQFILTER,
+    acpikqfilter,
 };
 
 static const char* sleep_state_names[] = {
@@ -1223,6 +1227,7 @@
 	}
 	acpi_wakeup((UINT8)state);
 	DEVICE_RESUME(root_bus);
+	acpi_knote(ACPI_KNDEV_SYSTEM|ACPI_KNOTE_WAKEUP);
 	sc->acpi_sstate = ACPI_STATE_S0;
 	acpi_enable_fixed_events(sc);
 	break;
@@ -1325,6 +1330,7 @@
 
     FUNCTION_TRACE(__func__);
 
+    acpi_knote(ACPI_KNDEV_SYSTEM|ACPI_KNOTE_POWERBUTTON);
     EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
 
     return_VALUE(INTERRUPT_HANDLED);
@@ -1349,6 +1355,7 @@
 
     FUNCTION_TRACE(__func__);
 
+    acpi_knote( ACPI_KNDEV_SYSTEM | ACPI_KNOTE_SLEEPBUTTON);
     EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
 
     return_VALUE(INTERRUPT_HANDLED);
@@ -1586,6 +1593,57 @@
 out:
     ACPI_UNLOCK;
     return(error);
+}
+static struct filterops acpi_filtops = 
+{ 1, NULL, filt_acpidetach, filt_acpi };
+static int acpikqfilter(dev_t dev, struct knote * kn)
+{
+	struct acpi_softc *sc = dev->si_drv1;
+	struct klist *kl = &sc->acpi_klist;
+	switch(kn->kn_filter){
+	case EVFILT_READ:
+		kn->kn_fop = & acpi_filtops;
+		break;
+	default:
+		return 1;
+	}
+	kn->kn_hook = (caddr_t) sc;
+	mtx_lock(&acpi_mutex);
+	SLIST_INSERT_HEAD(kl, kn, kn_selnext);
+	mtx_unlock(&acpi_mutex);
+	return 0;
+}
+static void filt_acpidetach(struct knote *kn)
+{
+	struct acpi_softc *sc = (struct acpi_softc *)kn->kn_hook;
+	mtx_lock(&acpi_mutex);
+	SLIST_REMOVE(&sc->acpi_klist, kn, knote, kn_selnext);
+	mtx_unlock(&acpi_mutex);
+}
+ 
+static int filt_acpi(struct knote *kn, long hint)
+{
+	/*This assumes with acpi_mutex acquired*/
+	long df1,df2,ev1,ev2;
+	df1 = kn->kn_sfflags&ACPI_KNMASK_DEV;
+	ev1 = kn->kn_sfflags&ACPI_KNMASK_EVENT;
+	df2 = hint & ACPI_KNMASK_DEV;
+	ev2 = hint & ACPI_KNMASK_EVENT;
+	if(hint==0&&kn->kn_fflags){
+	  return 1;
+	}
+	if((df1== df2)&&(ev1|ev2)){
+		kn->kn_fflags |= hint;
+		return 1;
+	}
+	return 0;
+}
+
+void acpi_knote(int filter){
+	struct acpi_softc *sc = devclass_get_softc(acpi_devclass,0);
+	mtx_lock(&acpi_mutex);
+	KNOTE(&sc->acpi_klist, filter);
+	mtx_unlock(&acpi_mutex);
 }
 
 static int
Index: acpi_acad.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_acad.c,v
retrieving revision 1.7
diff -u -r1.7 acpi_acad.c
--- acpi_acad.c	2001/07/25 16:08:58	1.7
+++ acpi_acad.c	2001/07/31 02:54:12
@@ -100,6 +100,7 @@
 	case ACPI_DEVICE_CHECK_PNP:
 	case ACPI_DEVICE_CHECK_EXISTENCE:
 	case ACPI_POWERSOURCE_STAT_CHANGE:
+		acpi_knote(ACPI_KNDEV_SYSTEM|ACPI_KNOTE_ACAD);
 		/*Temporally. It is better to notify policy manager*/
 		AcpiOsQueueForExecution(OSD_PRIORITY_LO,
 		    acpi_acad_get_status,context);
Index: acpi_cmbat.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_cmbat.c,v
retrieving revision 1.7
diff -u -r1.7 acpi_cmbat.c
--- acpi_cmbat.c	2001/06/24 02:39:08	1.7
+++ acpi_cmbat.c	2001/07/31 02:54:38
@@ -122,7 +122,7 @@
 	dest[sizeof(dest)-1] = '\0';					\
 } while(0)
 
-#define	BATTERY_INFO_EXPIRE	5
+#define	BATTERY_INFO_EXPIRE	60
 static __inline int
 acpi_cmbat_info_expired(struct timespec *lastupdated)
 {
@@ -292,9 +292,11 @@
 	switch (notify) {
 	case ACPI_BATTERY_BST_CHANGE:
 		timespecclear(&sc->bst_lastupdated);
+ 	        acpi_knote(ACPI_KNDEV_BATT|(device_get_unit(dev)&0xf)|ACPI_KNOTE_BATTSTAT);
 		break;
 	case ACPI_BATTERY_BIF_CHANGE:
 		timespecclear(&sc->bif_lastupdated);
+ 	        acpi_knote(ACPI_KNDEV_BATT|device_get_unit(dev)|ACPI_KNOTE_BATTINFO);
 		break;
 	default:
 		break;
@@ -331,7 +333,6 @@
 	bzero(&sc->bif_buffer, sizeof(sc->bif_buffer));
 	bzero(&sc->bst_buffer, sizeof(sc->bst_buffer));
 	sc->dev = dev;
-
 	timespecclear(&sc->bif_lastupdated);
 	timespecclear(&sc->bst_lastupdated);
 
@@ -385,6 +386,7 @@
 	struct acpi_bst	*bstp;
 
 	ioctl_arg = (union acpi_battery_ioctl_arg *)addr;
+
 	if ((dev = devclass_get_device(acpi_cmbat_devclass,
 			ioctl_arg->unit)) == NULL) {
 		return(ENXIO);
@@ -393,7 +395,6 @@
 	if ((sc = device_get_softc(dev)) == NULL) {
 		return(ENXIO);
 	}
-
 	switch (cmd) {
 	case ACPIIO_CMBAT_GET_BIF:
 		acpi_cmbat_get_bif(dev);
Index: acpi_lid.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_lid.c,v
retrieving revision 1.6
diff -u -r1.6 acpi_lid.c
--- acpi_lid.c	2001/05/29 20:13:34	1.6
+++ acpi_lid.c	2001/07/31 02:55:33
@@ -40,7 +40,7 @@
 #include "acpi.h"
 
 #include <dev/acpica/acpivar.h>
-
+#include <dev/acpica/acpiio.h>
 /*
  * Hooks for the ACPI CA debugging infrastructure
  */
@@ -123,7 +123,7 @@
     if (acpi_EvaluateInteger(sc->lid_handle, "_LID", &sc->lid_status) != AE_OK)
 	return_VOID;
     device_printf(sc->lid_dev, "Lid %s\n", sc->lid_status ? "opened" : "closed");
-
+    acpi_knote(ACPI_KNDEV_SYSTEM|ACPI_KNOTE_LID);
     acpi_sc = acpi_device_get_parent_softc(sc->lid_dev);
     if (acpi_sc == NULL) {
         return_VOID;
Index: acpi_thermal.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpi_thermal.c,v
retrieving revision 1.13
diff -u -r1.13 acpi_thermal.c
--- acpi_thermal.c	2001/07/21 10:24:32	1.13
+++ acpi_thermal.c	2001/07/31 02:55:06
@@ -37,7 +37,7 @@
 #include "acpi.h"
 
 #include <dev/acpica/acpivar.h>
-
+#include <dev/acpica/acpiio.h>
 /*
  * Hooks for the ACPI CA debugging infrastructure
  */
@@ -612,12 +612,14 @@
     switch(notify) {
     case TZ_NOTIFY_TEMPERATURE:
 	/* temperature change occurred */
+	acpi_knote(ACPI_KNDEV_THRM|device_get_unit(sc->tz_dev)|ACPI_KNOTE_THRM);
 	device_printf(sc->tz_dev, "notified of temperature reaching setpoint\n");
 	AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, (OSD_EXECUTION_CALLBACK)acpi_tz_monitor, sc);
 	break;
     case TZ_NOTIFY_DEVICES:
     case TZ_NOTIFY_LEVELS:
 	/* zone devices/setpoints changed */
+	acpi_knote(ACPI_KNDEV_THRM|device_get_unit(sc->tz_dev)|ACPI_KNOTE_THRMINFO);
 	device_printf(sc->tz_dev, "notified of zone configuration change\n");
 	AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, (OSD_EXECUTION_CALLBACK)acpi_tz_establish, sc);
 	break;
Index: acpiio.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpiio.h,v
retrieving revision 1.5
diff -u -r1.5 acpiio.h
--- acpiio.h	2001/06/23 10:38:25	1.5
+++ acpiio.h	2001/07/31 02:56:12
@@ -100,6 +100,25 @@
 
 #define ACPIIO_ACAD_GET_STATUS	_IOR('A', 1, int)
 
+#define ACPI_KNMASK_DEV 0xffff
+#define ACPI_KNMASK_UNIT 0xf
+#define ACPI_KNMASK_MDEV 0xfff0
+#define ACPI_KNMASK_EVENT 0xffff0000
+
+
+#define ACPI_KNDEV_SYSTEM 0x00
+#define ACPI_KNOTE_POWERBUTTON 0x10000
+#define ACPI_KNOTE_SLEEPBUTTON 0x20000
+#define ACPI_KNOTE_LID         0x40000
+#define ACPI_KNOTE_ACAD        0x80000
+#define ACPI_KNOTE_WAKEUP      0x100000
+#define ACPI_KNDEV_BATT   0x10
+#define ACPI_KNOTE_BATTSTAT 0x10000
+#define ACPI_KNOTE_BATTINFO 0x20000
+#define ACPI_KNDEV_THRM   0x20
+#define ACPI_KNOTE_THRM   0x10000
+#define ACPI_KNOTE_THRMINFO 0x20000
+
 #ifdef _KERNEL
 extern int	acpi_register_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg), void *arg);
 extern void	acpi_deregister_ioctl(u_long cmd, int (* fn)(u_long cmd, caddr_t addr, void *arg));
Index: acpivar.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/acpica/acpivar.h,v
retrieving revision 1.15
diff -u -r1.15 acpivar.h
--- acpivar.h	2001/07/30 08:59:43	1.15
+++ acpivar.h	2001/07/31 03:01:44
@@ -31,6 +31,7 @@
 #include "bus_if.h"
 #include <sys/eventhandler.h>
 #include <sys/sysctl.h>
+#include <sys/event.h>
 
 #include <machine/bus.h>
 #include <machine/resource.h>
@@ -64,6 +65,8 @@
 
     struct sysctl_ctx_list	 acpi_battery_sysctl_ctx;
     struct sysctl_oid		*acpi_battery_sysctl_tree;
+    /*kqueue stuff*/
+    struct klist 		acpi_klist;
 };
 
 struct acpi_device {
@@ -300,3 +303,5 @@
 
 typedef void (*powerprofile_change_hook)(void *);
 EVENTHANDLER_DECLARE(powerprofile_change, powerprofile_change_hook);
+/*KNOTE STUFF*/
+extern void     acpi_knote(int filter);

