Home | History | Annotate | Line # | Download | only in vr
vrpiu.c revision 1.9
      1 /*	$NetBSD: vrpiu.c,v 1.9 2001/01/20 12:24:22 takemura Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1999 Shin Takemura All rights reserved.
      5  * Copyright (c) 2000 SATO Kazumi, All rights reserved.
      6  * Copyright (c) 1999,2000 PocketBSD Project. All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  *
     29  */
     30 
     31 /*
     32  * A/D polling part written by SATO Kazumi.
     33  */
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/device.h>
     38 #include <sys/kernel.h>
     39 #include <sys/callout.h>
     40 #include <sys/boot_flag.h>
     41 
     42 #include <dev/wscons/wsconsio.h>
     43 #include <dev/wscons/wsmousevar.h>
     44 
     45 #include <machine/bus.h>
     46 #include <machine/platid.h>
     47 #include <machine/platid_mask.h>
     48 #include <machine/config_hook.h>
     49 
     50 #include <hpcmips/hpcmips/machdep.h>
     51 #include <hpcmips/dev/tpcalibvar.h>
     52 
     53 #include <hpcmips/vr/vripvar.h>
     54 #include <hpcmips/vr/cmureg.h>
     55 #include <hpcmips/vr/vrpiuvar.h>
     56 #include <hpcmips/vr/vrpiureg.h>
     57 
     58 /*
     59  * contant and macro definitions
     60  */
     61 #define VRPIUDEBUG
     62 #ifdef VRPIUDEBUG
     63 int	vrpiu_debug = 0;
     64 #define	DPRINTF(arg) if (vrpiu_debug) printf arg;
     65 #define	VPRINTF(arg) if (bootverbose || vrpiu_debug) printf arg;
     66 #else
     67 #define	DPRINTF(arg)
     68 #define	VPRINTF(arg) if (bootverbose) printf arg;
     69 #endif
     70 
     71 #ifndef VRPIU_AD_POLL_INTERVAL
     72 #define VRPIU_AD_POLL_INTERVAL	60	/* interval is 60 sec */
     73 #endif /* VRPIU_AD_POLL_INTERTVAL */
     74 
     75 #define	PIUSIVL_SCANINTVAL_MIN	333			/* 10msec	*/
     76 #define	PIUSIVL_SCANINTVAL_MAX	PIUSIVL_SCANINTVAL_MASK	/* 60msec	*/
     77 
     78 #define TP_INTR	(PIUINT_ALLINTR & ~PIUINT_PADADPINTR)
     79 #define AD_INTR	(PIUINT_PADADPINTR)
     80 
     81 /*
     82  * data types
     83  */
     84 /* struct vrpiu_softc is defined in vrpiuvar.h */
     85 
     86 /*
     87  * function prototypes
     88  */
     89 static int	vrpiumatch __P((struct device *, struct cfdata *, void *));
     90 static void	vrpiuattach __P((struct device *, struct device *, void *));
     91 
     92 static void	vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
     93 static u_short	vrpiu_read __P((struct vrpiu_softc *, int));
     94 
     95 static int	vrpiu_intr __P((void *));
     96 static void	vrpiu_tp_intr __P((struct vrpiu_softc *));
     97 static void	vrpiu_ad_intr __P((struct vrpiu_softc *));
     98 #ifdef DEBUG
     99 static void	vrpiu_dump_cntreg __P((unsigned int cmd));
    100 #endif
    101 
    102 static int	vrpiu_tp_enable __P((void *));
    103 static int	vrpiu_tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
    104 static void	vrpiu_tp_disable __P((void *));
    105 int		vrpiu_ad_enable __P((void *));
    106 void		vrpiu_ad_disable __P((void *));
    107 static void	vrpiu_start_powerstate __P((void *));
    108 static void	vrpiu_calc_powerstate __P((struct vrpiu_softc *));
    109 static void	vrpiu_power __P((int, void *));
    110 static u_int	scan_interval __P((u_int data));
    111 
    112 /* mra is defined in mra.c */
    113 int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s,
    114 			 int n, int scale, int *a, int *b, int *c));
    115 
    116 /*
    117  * static or global variables
    118  */
    119 struct cfattach vrpiu_ca = {
    120 	sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
    121 };
    122 
    123 const struct wsmouse_accessops vrpiu_accessops = {
    124 	vrpiu_tp_enable,
    125 	vrpiu_tp_ioctl,
    126 	vrpiu_tp_disable,
    127 };
    128 
    129 int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
    130 
    131 /*
    132  * function definitions
    133  */
    134 static inline void
    135 vrpiu_write(sc, port, val)
    136 	struct vrpiu_softc *sc;
    137 	int port;
    138 	unsigned short val;
    139 {
    140 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
    141 }
    142 
    143 static inline u_short
    144 vrpiu_read(sc, port)
    145 	struct vrpiu_softc *sc;
    146 	int port;
    147 {
    148 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
    149 }
    150 
    151 static int
    152 vrpiumatch(parent, cf, aux)
    153 	struct device *parent;
    154 	struct cfdata *cf;
    155 	void *aux;
    156 {
    157 	return 1;
    158 }
    159 
    160 static void
    161 vrpiuattach(parent, self, aux)
    162 	struct device *parent;
    163 	struct device *self;
    164 	void *aux;
    165 {
    166 	struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
    167 	struct vrip_attach_args *va = aux;
    168 	struct wsmousedev_attach_args wsmaa;
    169 
    170 	bus_space_tag_t iot = va->va_iot;
    171 	bus_space_handle_t ioh;
    172 
    173 	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
    174 	    printf(": can't map bus space\n");
    175 	    return;
    176 	}
    177 
    178 	sc->sc_iot = iot;
    179 	sc->sc_ioh = ioh;
    180 	sc->sc_vrip = va->va_vc;
    181 
    182 	sc->sc_interval = scan_interval(WSMOUSE_RES_DEFAULT);
    183 
    184 	/*
    185 	 * disable device until vrpiu_enable called
    186 	 */
    187 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
    188 
    189 	tpcalib_init(&sc->sc_tpcalib);
    190 #if 1
    191 	/*
    192 	 * XXX, calibrate parameters
    193 	 */
    194 	{
    195 	    int i;
    196 	    static const struct {
    197 		platid_mask_t *mask;
    198 		struct wsmouse_calibcoords coords;
    199 	    } calibrations[] = {
    200 		{ &platid_mask_MACH_NEC_MCR_700A,
    201 		  { 0, 0, 799, 599,
    202 		    4,
    203 		    { { 115,  80,   0,   0 },
    204 		      { 115, 966,   0, 599 },
    205 		      { 912,  80, 799,   0 },
    206 		      { 912, 966, 799, 599 } } } },
    207 
    208 		{ NULL,		/* samples got on my MC-R500 */
    209 		  { 0, 0, 639, 239,
    210 		    5,
    211 		    { { 502, 486, 320, 120 },
    212 		      {  55, 109,   0,   0 },
    213 		      {  54, 913,   0, 239 },
    214 		      { 973, 924, 639, 239 },
    215 		      { 975, 123, 639,   0 } } } },
    216 	    };
    217 	    for (i = 0; ; i++) {
    218 		if (calibrations[i].mask == NULL
    219 		    || platid_match(&platid, calibrations[i].mask))
    220 		    break;
    221 	    }
    222 	    tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
    223 			  (caddr_t)&calibrations[i].coords, 0, 0);
    224 	}
    225 #endif
    226 
    227 	/* install interrupt handler and enable interrupt */
    228 	if (!(sc->sc_handler =
    229 	    vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
    230 				vrpiu_intr, sc))) {
    231 	    printf (": can't map interrupt line.\n");
    232 	    return;
    233 	}
    234 
    235 	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
    236 	vrpiu_tp_disable(sc);
    237 
    238 	printf("\n");
    239 
    240 	wsmaa.accessops = &vrpiu_accessops;
    241 	wsmaa.accesscookie = sc;
    242 
    243 	/*
    244 	 * attach the wsmouse
    245 	 */
    246 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
    247 
    248 	/*
    249 	 * power management events
    250 	 */
    251 	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
    252 
    253 	/*
    254 	 * init A/D port polling.
    255 	 */
    256 	sc->sc_battery.n_values = 3;
    257 	sc->sc_battery.value[0] = -1;
    258 	sc->sc_battery.value[1] = -1;
    259 	sc->sc_battery.value[2] = -1;
    260 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    261 	callout_init(&sc->sc_adpoll);
    262 	callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc);
    263 }
    264 
    265 /*
    266  * calculate interval value
    267  *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
    268  * output: value for PIUSIVL_REG
    269  */
    270 static u_int
    271 scan_interval(u_int data)
    272 {
    273 	int scale;
    274 
    275 	if (data < WSMOUSE_RES_MIN)
    276 	    data = WSMOUSE_RES_MIN;
    277 
    278 	if (WSMOUSE_RES_MAX < data)
    279 	    data = WSMOUSE_RES_MAX;
    280 
    281 	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
    282 	data += WSMOUSE_RES_MIN;
    283 
    284 	return PIUSIVL_SCANINTVAL_MIN +
    285 	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
    286 	    (scale - data) / scale;
    287 }
    288 
    289 int
    290 vrpiu_ad_enable(v)
    291 	void *v;
    292 {
    293 	struct vrpiu_softc *sc = v;
    294 	int s;
    295 	unsigned int cnt;
    296 
    297 	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
    298 		 __FILE__, __LINE__, sc->sc_interval));
    299 	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
    300 	    return EBUSY;
    301 
    302 	/* supply clock to PIU */
    303 	__vrcmu_supply(CMUMSKPIU, 1);
    304 
    305 	/* set scan interval */
    306 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
    307 
    308 	s = spltty();
    309 
    310 	/* clear interrupt status */
    311 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    312 
    313 	/* Disable -> Standby */
    314 	cnt = PIUCNT_PIUPWR |
    315 		PIUCNT_PIUMODE_COORDINATE |
    316 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    317 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    318 
    319 	/* Level2 interrupt register setting */
    320 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
    321 
    322 	/* save pen status, touch or release */
    323 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    324 
    325 	/*
    326 	 * Enable scan sequencer operation
    327 	 * Standby -> WaitPenTouch
    328 	 */
    329 	cnt |= PIUCNT_PIUSEQEN;
    330 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    331 
    332 	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
    333 
    334 	splx(s);
    335 
    336 	return 0;
    337 }
    338 
    339 void
    340 vrpiu_ad_disable(v)
    341 	void *v;
    342 {
    343 	struct vrpiu_softc *sc = v;
    344 
    345 	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
    346 
    347 	/* Set level2 interrupt register to mask interrupts */
    348 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
    349 
    350 	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
    351 
    352 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
    353 	    /* Disable scan sequencer operation and power off */
    354 	    vrpiu_write(sc, PIUCNT_REG_W, 0);
    355 
    356 	    /* mask clock to PIU */
    357 	    __vrcmu_supply(CMUMSKPIU, 1);
    358 	}
    359 }
    360 
    361 int
    362 vrpiu_tp_enable(v)
    363 	void *v;
    364 {
    365 	struct vrpiu_softc *sc = v;
    366 	int s;
    367 	unsigned int cnt;
    368 
    369 	DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
    370 		 __FILE__, __LINE__, sc->sc_interval));
    371 	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
    372 	    return EBUSY;
    373 
    374 	/* supply clock to PIU */
    375 	__vrcmu_supply(CMUMSKPIU, 1);
    376 
    377 	/* set scan interval */
    378 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
    379 
    380 	s = spltty();
    381 
    382 	/* clear interrupt status */
    383 	vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
    384 
    385 	/* Disable -> Standby */
    386 	cnt = PIUCNT_PIUPWR |
    387 		PIUCNT_PIUMODE_COORDINATE |
    388 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    389 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    390 
    391 	/* Level2 interrupt register setting */
    392 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
    393 
    394 	/* save pen status, touch or release */
    395 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    396 
    397 	/*
    398 	 * Enable scan sequencer operation
    399 	 * Standby -> WaitPenTouch
    400 	 */
    401 	cnt |= PIUCNT_PIUSEQEN;
    402 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    403 
    404 	/* transit status DISABLE -> TOUCH or RELEASE */
    405 	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
    406 		VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
    407 
    408 	splx(s);
    409 
    410 	return 0;
    411 }
    412 
    413 void
    414 vrpiu_tp_disable(v)
    415 	void *v;
    416 {
    417 	struct vrpiu_softc *sc = v;
    418 
    419 	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
    420 
    421 	/* Set level2 interrupt register to mask interrupts */
    422 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
    423 
    424 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
    425 
    426 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
    427 	    /* Disable scan sequencer operation and power off */
    428 	    vrpiu_write(sc, PIUCNT_REG_W, 0);
    429 
    430 	    /* mask clock to PIU */
    431 	    __vrcmu_supply(CMUMSKPIU, 1);
    432 	}
    433 }
    434 
    435 int
    436 vrpiu_tp_ioctl(v, cmd, data, flag, p)
    437 	void *v;
    438 	u_long cmd;
    439 	caddr_t data;
    440 	int flag;
    441 	struct proc *p;
    442 {
    443 	struct vrpiu_softc *sc = v;
    444 
    445 	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
    446 
    447 	switch (cmd) {
    448 	case WSMOUSEIO_GTYPE:
    449 	    *(u_int *)data = WSMOUSE_TYPE_TPANEL;
    450 	    break;
    451 
    452 	case WSMOUSEIO_SRES:
    453 	    {
    454 		int tp_enable;
    455 		int ad_enable;
    456 
    457 		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
    458 		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
    459 
    460 		if (tp_enable)
    461 		    vrpiu_tp_disable(sc);
    462 		if (ad_enable)
    463 		    vrpiu_ad_disable(sc);
    464 
    465 		sc->sc_interval = scan_interval(*(u_int *)data);
    466 		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
    467 		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
    468 
    469 		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
    470 		    sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
    471 
    472 		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
    473 		    sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
    474 
    475 		if (tp_enable)
    476 		    vrpiu_tp_enable(sc);
    477 		if (ad_enable)
    478 		     vrpiu_ad_enable(sc);
    479 	    }
    480 	    break;
    481 
    482 	case WSMOUSEIO_SCALIBCOORDS:
    483 	case WSMOUSEIO_GCALIBCOORDS:
    484             return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
    485 
    486 	default:
    487 	    return (-1);
    488 	}
    489 	return (0);
    490 }
    491 
    492 /*
    493  * PIU AD interrupt handler.
    494  */
    495 void
    496 vrpiu_ad_intr(sc)
    497 	struct vrpiu_softc *sc;
    498 {
    499 	unsigned int i;
    500 	unsigned int intrstat;
    501 
    502 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    503 
    504 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
    505 	    /*
    506 	     * the device isn't enabled. just clear interrupt.
    507 	     */
    508 	    vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    509 	    return;
    510 	}
    511 
    512 	if (intrstat & PIUINT_PADADPINTR) {
    513 	    sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
    514 	    sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
    515 	    sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
    516 	}
    517 
    518 	if (intrstat & PIUINT_PADADPINTR) {
    519 	    for (i = 0; i < 3; i++) {
    520 		if (sc->sc_battery.value[i] & PIUAB_VALID)
    521 		    sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
    522 		else
    523 		    sc->sc_battery.value[i] = 0;
    524 	    }
    525 	    vrpiu_calc_powerstate(sc);
    526 	}
    527 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    528 
    529 	return;
    530 }
    531 /*
    532  * PIU TP interrupt handler.
    533  */
    534 void
    535 vrpiu_tp_intr(sc)
    536 	struct vrpiu_softc *sc;
    537 {
    538 	unsigned int cnt, i;
    539 	unsigned int intrstat, page;
    540 	int tpx0, tpx1, tpy0, tpy1;
    541 	int x, y, xraw, yraw;
    542 
    543 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    544 
    545 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
    546 	    /*
    547 	     * the device isn't enabled. just clear interrupt.
    548 	     */
    549 	    vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
    550 	    return;
    551 	}
    552 
    553 	page = (intrstat & PIUINT_OVP) ? 1 : 0;
    554 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    555 	    tpx0 = vrpiu_read(sc, PIUPB(page, 0));
    556 	    tpx1 = vrpiu_read(sc, PIUPB(page, 1));
    557 	    tpy0 = vrpiu_read(sc, PIUPB(page, 2));
    558 	    tpy1 = vrpiu_read(sc, PIUPB(page, 3));
    559 	}
    560 
    561 	if (intrstat & PIUINT_PADDLOSTINTR) {
    562 	    page = page ? 0 : 1;
    563 	    for (i = 0; i < 4; i++)
    564 		vrpiu_read(sc, PIUPB(page, i));
    565 	}
    566 
    567 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    568 #ifdef DEBUG
    569 	if (vrpiu_debug)
    570 	    vrpiu_dump_cntreg(cnt);
    571 #endif
    572 
    573 	/* clear interrupt status */
    574 	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
    575 
    576 #if 0
    577 	DPRINTF(("vrpiu_intr: OVP=%d", page));
    578 	if (intrstat & PIUINT_PADCMDINTR)
    579 	    DPRINTF((" CMD"));
    580 	if (intrstat & PIUINT_PADADPINTR)
    581 	    DPRINTF((" A/D"));
    582 	if (intrstat & PIUINT_PADPAGE1INTR)
    583 	    DPRINTF((" PAGE1"));
    584 	if (intrstat & PIUINT_PADPAGE0INTR)
    585 	    DPRINTF((" PAGE0"));
    586 	if (intrstat & PIUINT_PADDLOSTINTR)
    587 	    DPRINTF((" DLOST"));
    588 	if (intrstat & PIUINT_PENCHGINTR)
    589 	    DPRINTF((" PENCHG"));
    590 	DPRINTF(("\n"));
    591 #endif
    592 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    593 	    if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
    594 		(tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
    595 		printf("vrpiu: internal error, data is not valid!\n");
    596 	    } else {
    597 		tpx0 &= PIUPB_PADDATA_MASK;
    598 		tpx1 &= PIUPB_PADDATA_MASK;
    599 		tpy0 &= PIUPB_PADDATA_MASK;
    600 		tpy1 &= PIUPB_PADDATA_MASK;
    601 #define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
    602 		if (ISVALID(tpx0 + tpx1, 1024, 200) &&
    603 		    ISVALID(tpx0 + tpx1, 1024, 200)) {
    604 #if 0
    605 		    DPRINTF(("%04x %04x %04x %04x\n",
    606 			tpx0, tpx1, tpy0, tpy1));
    607 		    DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
    608 			tpx0 + tpx1, tpy0 + tpy1));
    609 #endif
    610 		    xraw = tpy1 * 1024 / (tpy0 + tpy1);
    611 		    yraw = tpx1 * 1024 / (tpx0 + tpx1);
    612 		    DPRINTF(("%3d %3d", xraw, yraw));
    613 
    614 		    tpcalib_trans(&sc->sc_tpcalib, xraw, yraw, &x, &y);
    615 
    616 		    DPRINTF(("->%4d %4d", x, y));
    617 		    wsmouse_input(sc->sc_wsmousedev,
    618 			(cnt & PIUCNT_PENSTC) ? 1 : 0,
    619 			x, /* x */
    620 			y, /* y */
    621 			0, /* z */
    622 			WSMOUSE_INPUT_ABSOLUTE_X |
    623 			WSMOUSE_INPUT_ABSOLUTE_Y);
    624 		    DPRINTF(("\n"));
    625 		}
    626 	    }
    627 	}
    628 
    629 	if (cnt & PIUCNT_PENSTC) {
    630 	    if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
    631 		/*
    632 		 * pen touch
    633 		 */
    634 		DPRINTF(("PEN TOUCH\n"));
    635 		sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
    636 		/*
    637 		 * We should not report button down event while
    638 		 * we don't know where it occur.
    639 		 */
    640 	    }
    641 	} else {
    642 	    if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
    643 		/*
    644 		 * pen release
    645 		 */
    646 		DPRINTF(("RELEASE\n"));
    647 		sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
    648 		/* button 0 UP */
    649 		wsmouse_input(sc->sc_wsmousedev,
    650 		    0,
    651 		    0, 0, 0, 0);
    652 	    }
    653 	}
    654 
    655 	if (intrstat & PIUINT_PADDLOSTINTR) {
    656 	    cnt |= PIUCNT_PIUSEQEN;
    657 	    vrpiu_write(sc, PIUCNT_REG_W, cnt);
    658 	}
    659 
    660 	return;
    661 }
    662 
    663 /*
    664  * PIU interrupt handler.
    665  */
    666 int
    667 vrpiu_intr(arg)
    668 	void *arg;
    669 {
    670         struct vrpiu_softc *sc = arg;
    671 
    672 	vrpiu_ad_intr(sc);
    673 	vrpiu_tp_intr(sc);
    674 
    675 	return 0;
    676 }
    677 
    678 void
    679 vrpiu_start_powerstate(v)
    680 	void *v;
    681 {
    682 	int mask;
    683 	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
    684 
    685 	vrpiu_ad_enable(sc);
    686 	mask = vrpiu_read(sc, PIUAMSK_REG_W);
    687 	mask &= 0xff8f; /* XXX */
    688 	vrpiu_write(sc, PIUAMSK_REG_W, mask);
    689 	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
    690 	/*
    691 	 * restart next A/D polling
    692 	 */
    693 	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
    694 		      vrpiu_start_powerstate, sc);
    695 }
    696 
    697 void
    698 vrpiu_calc_powerstate(sc)
    699 	struct vrpiu_softc *sc;
    700 {
    701 	extern void vrgiu_diff_io __P((void));
    702 	vrpiu_ad_disable(sc);
    703 	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
    704 		sc->sc_battery.value[0],
    705 		sc->sc_battery.value[1],
    706 		sc->sc_battery.value[2]));
    707 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    708 #ifdef notyet
    709 	config_hook_call(CONFIG_HOOK_SET,
    710 			 CONFIG_HOOK_BATTERYVAL,
    711 			 (void *)&sc->sc_battery);
    712 #endif /* notyet */
    713 	/*
    714 	 * restart next A/D polling if change polling timming.
    715 	 */
    716 	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
    717 	    callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
    718 			  vrpiu_start_powerstate, sc);
    719 	if (bootverbose)
    720 	    vrgiu_diff_io();
    721 
    722 }
    723 
    724 static void
    725 vrpiu_power(why, arg)
    726 	int why;
    727 	void *arg;
    728 {
    729 	struct vrpiu_softc *sc = arg;
    730 
    731 	switch (why) {
    732 	case PWR_STANDBY:
    733 	case PWR_SUSPEND:
    734 	    break;
    735 	case PWR_RESUME:
    736 	    callout_reset(&sc->sc_adpoll, hz,
    737 			  vrpiu_start_powerstate, sc);
    738 	    break;
    739 	}
    740 }
    741 
    742 #ifdef DEBUG
    743 void
    744 vrpiu_dump_cntreg(cnt)
    745 	unsigned int cnt;
    746 {
    747 	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
    748 	printf(" state=");
    749 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
    750 	    printf("CmdScan");
    751 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
    752 	    printf("IntervalNextScan");
    753 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
    754 	    printf("PenDataScan");
    755 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
    756 	    printf("WaitPenTouch");
    757 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
    758 	    printf("???");
    759 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
    760 	    printf("ADPortScan");
    761 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
    762 	    printf("Standby");
    763 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
    764 	    printf("Disable");
    765 	if (cnt & PIUCNT_PADATSTOP)
    766 	    printf(" AutoStop");
    767 	if (cnt & PIUCNT_PADATSTART)
    768 	    printf(" AutoStart");
    769 	if (cnt & PIUCNT_PADSCANSTOP)
    770 	    printf(" Stop");
    771 	if (cnt & PIUCNT_PADSCANSTART)
    772 	    printf(" Start");
    773 	if (cnt & PIUCNT_PADSCANTYPE)
    774 	    printf(" ScanPressure");
    775 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
    776 	    printf(" A/D");
    777 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
    778 	    printf(" Coordinate");
    779 	if (cnt & PIUCNT_PIUSEQEN)
    780 	    printf(" SeqEn");
    781 	if ((cnt & PIUCNT_PIUPWR) == 0)
    782 	    printf(" PowerOff");
    783 	if ((cnt & PIUCNT_PADRST) == 0)
    784 	    printf(" Reset");
    785 	printf("\n");
    786 }
    787 #endif
    788