17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ 237c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */ 247c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 287c478bd9Sstevel@tonic-gate * Use is subject to license terms. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * PS/2 type Mouse Module - Streams 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <sys/param.h> 387c478bd9Sstevel@tonic-gate #include <sys/types.h> 397c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 407c478bd9Sstevel@tonic-gate #include <sys/signal.h> 417c478bd9Sstevel@tonic-gate #include <sys/errno.h> 427c478bd9Sstevel@tonic-gate #include <sys/file.h> 437c478bd9Sstevel@tonic-gate #include <sys/termio.h> 447c478bd9Sstevel@tonic-gate #include <sys/stream.h> 457c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 467c478bd9Sstevel@tonic-gate #include <sys/strtty.h> 477c478bd9Sstevel@tonic-gate #include <sys/debug.h> 487c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 497c478bd9Sstevel@tonic-gate #include <sys/stat.h> 507c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 517c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include <sys/promif.h> 547c478bd9Sstevel@tonic-gate #include <sys/cred.h> 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #include <sys/i8042.h> 577c478bd9Sstevel@tonic-gate #include <sys/note.h> 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #define DRIVER_NAME(dip) ddi_driver_name(dip) 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #ifdef DEBUG 627c478bd9Sstevel@tonic-gate #define MOUSE8042_DEBUG 637c478bd9Sstevel@tonic-gate #endif 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #define MOUSE8042_INTERNAL_OPEN(minor) (((minor) & 0x1) == 1) 667c478bd9Sstevel@tonic-gate #define MOUSE8042_MINOR_TO_INSTANCE(minor) ((minor) / 2) 677c478bd9Sstevel@tonic-gate #define MOUSE8042_INTERNAL_MINOR(minor) ((minor) + 1) 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate extern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t); 707c478bd9Sstevel@tonic-gate extern void consconfig_link(major_t major, minor_t minor); 717c478bd9Sstevel@tonic-gate extern int consconfig_unlink(major_t major, minor_t minor); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * 767c478bd9Sstevel@tonic-gate * Local Static Data 777c478bd9Sstevel@tonic-gate * 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * We only support one instance. Yes, it's theoretically possible to 827c478bd9Sstevel@tonic-gate * plug in more than one, but it's not worth the implementation cost. 837c478bd9Sstevel@tonic-gate * 847c478bd9Sstevel@tonic-gate * The introduction of USB keyboards might make it worth reassessing 857c478bd9Sstevel@tonic-gate * this decision, as they might free up the keyboard port for a second 867c478bd9Sstevel@tonic-gate * PS/2 style mouse. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate static dev_info_t *mouse8042_dip; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate struct mouse_state { 917c478bd9Sstevel@tonic-gate queue_t *ms_rqp; 927c478bd9Sstevel@tonic-gate queue_t *ms_wqp; 937c478bd9Sstevel@tonic-gate ddi_iblock_cookie_t ms_iblock_cookie; 947c478bd9Sstevel@tonic-gate ddi_acc_handle_t ms_handle; 957c478bd9Sstevel@tonic-gate uint8_t *ms_addr; 967c478bd9Sstevel@tonic-gate kmutex_t ms_mutex; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate minor_t ms_minor; 997c478bd9Sstevel@tonic-gate boolean_t ms_opened; 1007c478bd9Sstevel@tonic-gate }; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 1037c478bd9Sstevel@tonic-gate int mouse8042_debug = 0; 1047c478bd9Sstevel@tonic-gate int mouse8042_debug_minimal = 0; 1057c478bd9Sstevel@tonic-gate #endif 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate static uint_t mouse8042_intr(caddr_t arg); 1087c478bd9Sstevel@tonic-gate static int mouse8042_open(queue_t *q, dev_t *devp, int flag, int sflag, 1097c478bd9Sstevel@tonic-gate cred_t *cred_p); 1107c478bd9Sstevel@tonic-gate static int mouse8042_close(queue_t *q, int flag, cred_t *cred_p); 1117c478bd9Sstevel@tonic-gate static int mouse8042_wput(queue_t *q, mblk_t *mp); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate static int mouse8042_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, 1147c478bd9Sstevel@tonic-gate void *arg, void **result); 1157c478bd9Sstevel@tonic-gate static int mouse8042_attach(dev_info_t *dev, ddi_attach_cmd_t cmd); 1167c478bd9Sstevel@tonic-gate static int mouse8042_detach(dev_info_t *dev, ddi_detach_cmd_t cmd); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * Streams module info. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate #define MODULE_NAME "mouse8042" 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate static struct module_info mouse8042_minfo = { 1257c478bd9Sstevel@tonic-gate 23, /* Module ID number */ 1267c478bd9Sstevel@tonic-gate MODULE_NAME, 1277c478bd9Sstevel@tonic-gate 0, INFPSZ, /* minimum & maximum packet sizes */ 1287c478bd9Sstevel@tonic-gate 256, 128 /* hi and low water marks */ 1297c478bd9Sstevel@tonic-gate }; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate static struct qinit mouse8042_rinit = { 1327c478bd9Sstevel@tonic-gate NULL, /* put */ 1337c478bd9Sstevel@tonic-gate NULL, /* service */ 1347c478bd9Sstevel@tonic-gate mouse8042_open, 1357c478bd9Sstevel@tonic-gate mouse8042_close, 1367c478bd9Sstevel@tonic-gate NULL, /* admin */ 1377c478bd9Sstevel@tonic-gate &mouse8042_minfo, 1387c478bd9Sstevel@tonic-gate NULL /* statistics */ 1397c478bd9Sstevel@tonic-gate }; 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate static struct qinit mouse8042_winit = { 1427c478bd9Sstevel@tonic-gate mouse8042_wput, /* put */ 1437c478bd9Sstevel@tonic-gate NULL, /* service */ 1447c478bd9Sstevel@tonic-gate NULL, /* open */ 1457c478bd9Sstevel@tonic-gate NULL, /* close */ 1467c478bd9Sstevel@tonic-gate NULL, /* admin */ 1477c478bd9Sstevel@tonic-gate &mouse8042_minfo, 1487c478bd9Sstevel@tonic-gate NULL /* statistics */ 1497c478bd9Sstevel@tonic-gate }; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate static struct streamtab mouse8042_strinfo = { 1527c478bd9Sstevel@tonic-gate &mouse8042_rinit, 1537c478bd9Sstevel@tonic-gate &mouse8042_winit, 1547c478bd9Sstevel@tonic-gate NULL, /* muxrinit */ 1557c478bd9Sstevel@tonic-gate NULL, /* muxwinit */ 1567c478bd9Sstevel@tonic-gate }; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Local Function Declarations 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate static struct cb_ops mouse8042_cb_ops = { 1637c478bd9Sstevel@tonic-gate nodev, /* open */ 1647c478bd9Sstevel@tonic-gate nodev, /* close */ 1657c478bd9Sstevel@tonic-gate nodev, /* strategy */ 1667c478bd9Sstevel@tonic-gate nodev, /* print */ 1677c478bd9Sstevel@tonic-gate nodev, /* dump */ 1687c478bd9Sstevel@tonic-gate nodev, /* read */ 1697c478bd9Sstevel@tonic-gate nodev, /* write */ 1707c478bd9Sstevel@tonic-gate nodev, /* ioctl */ 1717c478bd9Sstevel@tonic-gate nodev, /* devmap */ 1727c478bd9Sstevel@tonic-gate nodev, /* mmap */ 1737c478bd9Sstevel@tonic-gate nodev, /* segmap */ 1747c478bd9Sstevel@tonic-gate nochpoll, /* poll */ 1757c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 1767c478bd9Sstevel@tonic-gate &mouse8042_strinfo, /* streamtab */ 1777c478bd9Sstevel@tonic-gate D_MP | D_NEW 1787c478bd9Sstevel@tonic-gate }; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate static struct dev_ops mouse8042_ops = { 1827c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 1837c478bd9Sstevel@tonic-gate 0, /* refcnt */ 1847c478bd9Sstevel@tonic-gate mouse8042_getinfo, /* getinfo */ 1857c478bd9Sstevel@tonic-gate nulldev, /* identify */ 1867c478bd9Sstevel@tonic-gate nulldev, /* probe */ 1877c478bd9Sstevel@tonic-gate mouse8042_attach, /* attach */ 1887c478bd9Sstevel@tonic-gate mouse8042_detach, /* detach */ 1897c478bd9Sstevel@tonic-gate nodev, /* reset */ 1907c478bd9Sstevel@tonic-gate &mouse8042_cb_ops, /* driver operations */ 1917c478bd9Sstevel@tonic-gate (struct bus_ops *)0 /* bus operations */ 1927c478bd9Sstevel@tonic-gate }; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * This is the loadable module wrapper. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate static struct modldrv modldrv = { 2067c478bd9Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a driver */ 2077c478bd9Sstevel@tonic-gate "PS/2 Mouse %I%, %E%", 2087c478bd9Sstevel@tonic-gate &mouse8042_ops, /* driver ops */ 2097c478bd9Sstevel@tonic-gate }; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 2127c478bd9Sstevel@tonic-gate MODREV_1, 2137c478bd9Sstevel@tonic-gate (void *)&modldrv, 2147c478bd9Sstevel@tonic-gate NULL 2157c478bd9Sstevel@tonic-gate }; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate /* 2187c478bd9Sstevel@tonic-gate * This is the driver initialization routine. 2197c478bd9Sstevel@tonic-gate */ 2207c478bd9Sstevel@tonic-gate int 2217c478bd9Sstevel@tonic-gate _init() 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate int rv; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate rv = mod_install(&modlinkage); 2267c478bd9Sstevel@tonic-gate return (rv); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate int 2317c478bd9Sstevel@tonic-gate _fini(void) 2327c478bd9Sstevel@tonic-gate { 2337c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate int 2387c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 2397c478bd9Sstevel@tonic-gate { 2407c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate static int 2447c478bd9Sstevel@tonic-gate mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate struct mouse_state *state; 247*fd9cb95cSsethg mblk_t *mp; 2487c478bd9Sstevel@tonic-gate int instance = ddi_get_instance(dip); 2497c478bd9Sstevel@tonic-gate static ddi_device_acc_attr_t attr = { 2507c478bd9Sstevel@tonic-gate DDI_DEVICE_ATTR_V0, 2517c478bd9Sstevel@tonic-gate DDI_NEVERSWAP_ACC, 2527c478bd9Sstevel@tonic-gate DDI_STRICTORDER_ACC, 2537c478bd9Sstevel@tonic-gate }; 2547c478bd9Sstevel@tonic-gate int rc; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 2587c478bd9Sstevel@tonic-gate if (mouse8042_debug) { 2597c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, MODULE_NAME "_attach entry\n"); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate #endif 2627c478bd9Sstevel@tonic-gate 263*fd9cb95cSsethg if (cmd == DDI_RESUME) { 264*fd9cb95cSsethg state = (struct mouse_state *)ddi_get_driver_private(dip); 265*fd9cb95cSsethg 266*fd9cb95cSsethg /* 267*fd9cb95cSsethg * Send a 0xaa 0x00 upstream. 268*fd9cb95cSsethg * This causes the vuid module to reset the mouse. 269*fd9cb95cSsethg */ 270*fd9cb95cSsethg if (state->ms_rqp != NULL) { 271*fd9cb95cSsethg if (mp = allocb(1, BPRI_MED)) { 272*fd9cb95cSsethg *mp->b_wptr++ = 0xaa; 273*fd9cb95cSsethg putnext(state->ms_rqp, mp); 274*fd9cb95cSsethg } 275*fd9cb95cSsethg if (mp = allocb(1, BPRI_MED)) { 276*fd9cb95cSsethg *mp->b_wptr++ = 0x0; 277*fd9cb95cSsethg putnext(state->ms_rqp, mp); 278*fd9cb95cSsethg } 279*fd9cb95cSsethg } 280*fd9cb95cSsethg return (DDI_SUCCESS); 281*fd9cb95cSsethg } 282*fd9cb95cSsethg 2837c478bd9Sstevel@tonic-gate if (cmd != DDI_ATTACH) 2847c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate if (mouse8042_dip != NULL) 2877c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* allocate and initialize state structure */ 2907c478bd9Sstevel@tonic-gate state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP); 2917c478bd9Sstevel@tonic-gate state->ms_opened = B_FALSE; 2927c478bd9Sstevel@tonic-gate ddi_set_driver_private(dip, state); 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate * In order to support virtual keyboard/mouse, we should distinguish 2967c478bd9Sstevel@tonic-gate * between internal virtual open and external physical open. 2977c478bd9Sstevel@tonic-gate * 2987c478bd9Sstevel@tonic-gate * When the physical devices are opened by application, they will 2997c478bd9Sstevel@tonic-gate * be unlinked from the virtual device and their data stream will 3007c478bd9Sstevel@tonic-gate * not be sent to the virtual device. When the opened physical 3017c478bd9Sstevel@tonic-gate * devices are closed, they will be relinked to the virtual devices. 3027c478bd9Sstevel@tonic-gate * 3037c478bd9Sstevel@tonic-gate * All these automatic switch between virtual and physical are 3047c478bd9Sstevel@tonic-gate * transparent. 3057c478bd9Sstevel@tonic-gate * 3067c478bd9Sstevel@tonic-gate * So we change minor node numbering scheme to be: 3077c478bd9Sstevel@tonic-gate * external node minor num == instance * 2 3087c478bd9Sstevel@tonic-gate * internal node minor num == instance * 2 + 1 3097c478bd9Sstevel@tonic-gate */ 310*fd9cb95cSsethg rc = ddi_create_minor_node(dip, "mouse", S_IFCHR, instance * 2, 3117c478bd9Sstevel@tonic-gate DDI_NT_MOUSE, NULL); 3127c478bd9Sstevel@tonic-gate if (rc != DDI_SUCCESS) { 3137c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 3147c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 3157c478bd9Sstevel@tonic-gate MODULE_NAME "_attach: ddi_create_minor_node failed\n"); 3167c478bd9Sstevel@tonic-gate #endif 3177c478bd9Sstevel@tonic-gate goto fail_1; 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR, 3217c478bd9Sstevel@tonic-gate instance * 2 + 1) != DDI_SUCCESS) { 3227c478bd9Sstevel@tonic-gate goto fail_2; 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr, 3267c478bd9Sstevel@tonic-gate (offset_t)0, (offset_t)0, &attr, &state->ms_handle); 3277c478bd9Sstevel@tonic-gate if (rc != DDI_SUCCESS) { 3287c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 3297c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, MODULE_NAME "_attach: can't map registers"); 3307c478bd9Sstevel@tonic-gate #endif 3317c478bd9Sstevel@tonic-gate goto fail_2; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie); 3357c478bd9Sstevel@tonic-gate if (rc != DDI_SUCCESS) { 3367c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 3377c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3387c478bd9Sstevel@tonic-gate MODULE_NAME "_attach: Can't get iblock cookie"); 3397c478bd9Sstevel@tonic-gate #endif 3407c478bd9Sstevel@tonic-gate goto fail_3; 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER, 3447c478bd9Sstevel@tonic-gate state->ms_iblock_cookie); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate rc = ddi_add_intr(dip, 0, 3477c478bd9Sstevel@tonic-gate (ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL, 3487c478bd9Sstevel@tonic-gate mouse8042_intr, (caddr_t)state); 3497c478bd9Sstevel@tonic-gate if (rc != DDI_SUCCESS) { 3507c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 3517c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, MODULE_NAME "_attach: cannot add interrupt"); 3527c478bd9Sstevel@tonic-gate #endif 3537c478bd9Sstevel@tonic-gate goto fail_3; 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate mouse8042_dip = dip; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate /* Now that we're attached, announce our presence to the world. */ 3597c478bd9Sstevel@tonic-gate ddi_report_dev(dip); 3607c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 3617c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?%s #%d: version %s\n", 3627c478bd9Sstevel@tonic-gate DRIVER_NAME(dip), ddi_get_instance(dip), "%I% (%E%)"); 3637c478bd9Sstevel@tonic-gate #endif 3647c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate fail_3: 3677c478bd9Sstevel@tonic-gate ddi_regs_map_free(&state->ms_handle); 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate fail_2: 3707c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate fail_1: 3737c478bd9Sstevel@tonic-gate kmem_free(state, sizeof (struct mouse_state)); 3747c478bd9Sstevel@tonic-gate return (rc); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3787c478bd9Sstevel@tonic-gate static int 3797c478bd9Sstevel@tonic-gate mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 3807c478bd9Sstevel@tonic-gate { 3817c478bd9Sstevel@tonic-gate struct mouse_state *state; 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate state = ddi_get_driver_private(dip); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate switch (cmd) { 386*fd9cb95cSsethg case DDI_SUSPEND: 387*fd9cb95cSsethg return (DDI_SUCCESS); 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate case DDI_DETACH: 3907c478bd9Sstevel@tonic-gate ddi_remove_intr(dip, 0, state->ms_iblock_cookie); 3917c478bd9Sstevel@tonic-gate mouse8042_dip = NULL; 3927c478bd9Sstevel@tonic-gate mutex_destroy(&state->ms_mutex); 3937c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip); 3947c478bd9Sstevel@tonic-gate ddi_regs_map_free(&state->ms_handle); 3957c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 3967c478bd9Sstevel@tonic-gate kmem_free(state, sizeof (struct mouse_state)); 3977c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate default: 4007c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 4017c478bd9Sstevel@tonic-gate if (mouse8042_debug) { 4027c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 4037c478bd9Sstevel@tonic-gate "mouse8042_detach: cmd = %d unknown\n", cmd); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate #endif 4067c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4127c478bd9Sstevel@tonic-gate static int 4137c478bd9Sstevel@tonic-gate mouse8042_getinfo( 4147c478bd9Sstevel@tonic-gate dev_info_t *dip, 4157c478bd9Sstevel@tonic-gate ddi_info_cmd_t infocmd, 4167c478bd9Sstevel@tonic-gate void *arg, 4177c478bd9Sstevel@tonic-gate void **result) 4187c478bd9Sstevel@tonic-gate { 4197c478bd9Sstevel@tonic-gate dev_t dev = (dev_t)arg; 4207c478bd9Sstevel@tonic-gate minor_t minor = getminor(dev); 4217c478bd9Sstevel@tonic-gate int instance = MOUSE8042_MINOR_TO_INSTANCE(minor); 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 4247c478bd9Sstevel@tonic-gate if (mouse8042_debug) 4257c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_getinfo: call\n"); 4267c478bd9Sstevel@tonic-gate #endif 4277c478bd9Sstevel@tonic-gate switch (infocmd) { 4287c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 4297c478bd9Sstevel@tonic-gate if (mouse8042_dip == NULL) 4307c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate *result = (void *)mouse8042_dip; 4337c478bd9Sstevel@tonic-gate break; 4347c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 4357c478bd9Sstevel@tonic-gate *result = (void *)(uintptr_t)instance; 4367c478bd9Sstevel@tonic-gate break; 4377c478bd9Sstevel@tonic-gate default: 4387c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4447c478bd9Sstevel@tonic-gate static int 4457c478bd9Sstevel@tonic-gate mouse8042_open( 4467c478bd9Sstevel@tonic-gate queue_t *q, 4477c478bd9Sstevel@tonic-gate dev_t *devp, 4487c478bd9Sstevel@tonic-gate int flag, 4497c478bd9Sstevel@tonic-gate int sflag, 4507c478bd9Sstevel@tonic-gate cred_t *cred_p) 4517c478bd9Sstevel@tonic-gate { 4527c478bd9Sstevel@tonic-gate struct mouse_state *state; 4537c478bd9Sstevel@tonic-gate minor_t minor = getminor(*devp); 4547c478bd9Sstevel@tonic-gate int rval; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate if (mouse8042_dip == NULL) 4577c478bd9Sstevel@tonic-gate return (ENXIO); 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate state = ddi_get_driver_private(mouse8042_dip); 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 4627c478bd9Sstevel@tonic-gate if (mouse8042_debug) 4637c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_open:entered\n"); 4647c478bd9Sstevel@tonic-gate #endif 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate mutex_enter(&state->ms_mutex); 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate if (state->ms_opened) { 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * Exit if the same minor node is already open 4717c478bd9Sstevel@tonic-gate */ 4727c478bd9Sstevel@tonic-gate if (state->ms_minor == minor) { 4737c478bd9Sstevel@tonic-gate mutex_exit(&state->ms_mutex); 4747c478bd9Sstevel@tonic-gate return (0); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * Check whether it is switch between physical and virtual 4797c478bd9Sstevel@tonic-gate * 4807c478bd9Sstevel@tonic-gate * Opening from virtual while the device is being physically 4817c478bd9Sstevel@tonic-gate * opened by an application should not happen. So we ASSERT 4827c478bd9Sstevel@tonic-gate * this in DEBUG version, and return error in the non-DEBUG 4837c478bd9Sstevel@tonic-gate * case. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate ASSERT(!MOUSE8042_INTERNAL_OPEN(minor)); 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate if (MOUSE8042_INTERNAL_OPEN(minor)) { 4887c478bd9Sstevel@tonic-gate mutex_exit(&state->ms_mutex); 4897c478bd9Sstevel@tonic-gate return (EINVAL); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate /* 4937c478bd9Sstevel@tonic-gate * Opening the physical one while it is being underneath 4947c478bd9Sstevel@tonic-gate * the virtual one. 4957c478bd9Sstevel@tonic-gate * 4967c478bd9Sstevel@tonic-gate * consconfig_unlink is called to unlink this device from 4977c478bd9Sstevel@tonic-gate * the virtual one, thus the old stream serving for this 4987c478bd9Sstevel@tonic-gate * device under the virtual one is closed, and then the 4997c478bd9Sstevel@tonic-gate * lower driver's close routine (here is mouse8042_close) 5007c478bd9Sstevel@tonic-gate * is also called to accomplish the whole stream close. 5017c478bd9Sstevel@tonic-gate * Here we have to drop the lock because mouse8042_close 5027c478bd9Sstevel@tonic-gate * also needs the lock. 5037c478bd9Sstevel@tonic-gate * 5047c478bd9Sstevel@tonic-gate * For mouse, the old stream is: 5057c478bd9Sstevel@tonic-gate * consms->["pushmod"->]"mouse_vp driver" 5067c478bd9Sstevel@tonic-gate * 5077c478bd9Sstevel@tonic-gate * After the consconfig_unlink returns, the old stream is closed 5087c478bd9Sstevel@tonic-gate * and we grab the lock again to reopen this device as normal. 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate mutex_exit(&state->ms_mutex); 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate /* 5137c478bd9Sstevel@tonic-gate * If unlink fails, fail the physical open. 5147c478bd9Sstevel@tonic-gate */ 5157c478bd9Sstevel@tonic-gate if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip), 5167c478bd9Sstevel@tonic-gate MOUSE8042_INTERNAL_MINOR(minor))) != 0) { 5177c478bd9Sstevel@tonic-gate return (rval); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate mutex_enter(&state->ms_mutex); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate q->q_ptr = (caddr_t)state; 5257c478bd9Sstevel@tonic-gate WR(q)->q_ptr = (caddr_t)state; 5267c478bd9Sstevel@tonic-gate state->ms_rqp = q; 5277c478bd9Sstevel@tonic-gate state->ms_wqp = WR(q); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate qprocson(q); 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate state->ms_minor = minor; 5327c478bd9Sstevel@tonic-gate state->ms_opened = B_TRUE; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate mutex_exit(&state->ms_mutex); 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate return (0); 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5417c478bd9Sstevel@tonic-gate static int 5427c478bd9Sstevel@tonic-gate mouse8042_close(queue_t *q, int flag, cred_t *cred_p) 5437c478bd9Sstevel@tonic-gate { 5447c478bd9Sstevel@tonic-gate struct mouse_state *state; 5457c478bd9Sstevel@tonic-gate minor_t minor; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate state = (struct mouse_state *)q->q_ptr; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 5507c478bd9Sstevel@tonic-gate if (mouse8042_debug) 5517c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_close:entered\n"); 5527c478bd9Sstevel@tonic-gate #endif 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate mutex_enter(&state->ms_mutex); 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate qprocsoff(q); 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate q->q_ptr = NULL; 5597c478bd9Sstevel@tonic-gate WR(q)->q_ptr = NULL; 5607c478bd9Sstevel@tonic-gate state->ms_rqp = NULL; 5617c478bd9Sstevel@tonic-gate state->ms_wqp = NULL; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate state->ms_opened = B_FALSE; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate minor = state->ms_minor; 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate mutex_exit(&state->ms_mutex); 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate if (!MOUSE8042_INTERNAL_OPEN(minor)) { 5707c478bd9Sstevel@tonic-gate /* 5717c478bd9Sstevel@tonic-gate * Closing physical PS/2 mouse 5727c478bd9Sstevel@tonic-gate * 5737c478bd9Sstevel@tonic-gate * Link it back to virtual mouse, and 5747c478bd9Sstevel@tonic-gate * mouse8042_open will be called as a result 575*fd9cb95cSsethg * of the consconfig_link call. Do NOT try 576*fd9cb95cSsethg * this if the mouse is about to be detached! 5777c478bd9Sstevel@tonic-gate * 5787c478bd9Sstevel@tonic-gate * If linking back fails, this specific mouse 5797c478bd9Sstevel@tonic-gate * will not be available underneath the virtual 5807c478bd9Sstevel@tonic-gate * mouse, and can only be accessed via physical 5817c478bd9Sstevel@tonic-gate * open. 5827c478bd9Sstevel@tonic-gate */ 5837c478bd9Sstevel@tonic-gate consconfig_link(ddi_driver_major(mouse8042_dip), 5847c478bd9Sstevel@tonic-gate MOUSE8042_INTERNAL_MINOR(minor)); 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate 5877c478bd9Sstevel@tonic-gate return (0); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate static void 5917c478bd9Sstevel@tonic-gate mouse8042_iocnack( 5927c478bd9Sstevel@tonic-gate queue_t *qp, 5937c478bd9Sstevel@tonic-gate mblk_t *mp, 5947c478bd9Sstevel@tonic-gate struct iocblk *iocp, 5957c478bd9Sstevel@tonic-gate int error, 5967c478bd9Sstevel@tonic-gate int rval) 5977c478bd9Sstevel@tonic-gate { 5987c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCNAK; 5997c478bd9Sstevel@tonic-gate iocp->ioc_rval = rval; 6007c478bd9Sstevel@tonic-gate iocp->ioc_error = error; 6017c478bd9Sstevel@tonic-gate qreply(qp, mp); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate static int 6057c478bd9Sstevel@tonic-gate mouse8042_wput(queue_t *q, mblk_t *mp) 6067c478bd9Sstevel@tonic-gate { 6077c478bd9Sstevel@tonic-gate struct iocblk *iocbp; 6087c478bd9Sstevel@tonic-gate mblk_t *bp; 6097c478bd9Sstevel@tonic-gate mblk_t *next; 6107c478bd9Sstevel@tonic-gate struct mouse_state *state; 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate state = (struct mouse_state *)q->q_ptr; 6137c478bd9Sstevel@tonic-gate 6147c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 6157c478bd9Sstevel@tonic-gate if (mouse8042_debug) 6167c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_wput:entered\n"); 6177c478bd9Sstevel@tonic-gate #endif 6187c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)mp->b_rptr; 6197c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 6207c478bd9Sstevel@tonic-gate case M_FLUSH: 6217c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 6227c478bd9Sstevel@tonic-gate if (mouse8042_debug) 6237c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_wput:M_FLUSH\n"); 6247c478bd9Sstevel@tonic-gate #endif 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW) 6277c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 6287c478bd9Sstevel@tonic-gate qreply(q, mp); 6297c478bd9Sstevel@tonic-gate break; 6307c478bd9Sstevel@tonic-gate case M_IOCTL: 6317c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 6327c478bd9Sstevel@tonic-gate if (mouse8042_debug) 6337c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_wput:M_IOCTL\n"); 6347c478bd9Sstevel@tonic-gate #endif 6357c478bd9Sstevel@tonic-gate mouse8042_iocnack(q, mp, iocbp, EINVAL, 0); 6367c478bd9Sstevel@tonic-gate break; 6377c478bd9Sstevel@tonic-gate case M_IOCDATA: 6387c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 6397c478bd9Sstevel@tonic-gate if (mouse8042_debug) 6407c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_wput:M_IOCDATA\n"); 6417c478bd9Sstevel@tonic-gate #endif 6427c478bd9Sstevel@tonic-gate mouse8042_iocnack(q, mp, iocbp, EINVAL, 0); 6437c478bd9Sstevel@tonic-gate break; 6447c478bd9Sstevel@tonic-gate case M_DATA: 6457c478bd9Sstevel@tonic-gate bp = mp; 6467c478bd9Sstevel@tonic-gate do { 6477c478bd9Sstevel@tonic-gate while (bp->b_rptr < bp->b_wptr) { 6487c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 6497c478bd9Sstevel@tonic-gate if (mouse8042_debug) { 6507c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 6517c478bd9Sstevel@tonic-gate "mouse8042: send %2x\n", 6527c478bd9Sstevel@tonic-gate *bp->b_rptr); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate if (mouse8042_debug_minimal) { 6557c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, ">a:%2x ", 6567c478bd9Sstevel@tonic-gate *bp->b_rptr); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate #endif 6597c478bd9Sstevel@tonic-gate ddi_put8(state->ms_handle, 6607c478bd9Sstevel@tonic-gate state->ms_addr + I8042_INT_OUTPUT_DATA, 6617c478bd9Sstevel@tonic-gate *bp->b_rptr++); 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate next = bp->b_cont; 6647c478bd9Sstevel@tonic-gate freeb(bp); 6657c478bd9Sstevel@tonic-gate } while ((bp = next) != NULL); 6667c478bd9Sstevel@tonic-gate break; 6677c478bd9Sstevel@tonic-gate default: 6687c478bd9Sstevel@tonic-gate freemsg(mp); 6697c478bd9Sstevel@tonic-gate break; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 6727c478bd9Sstevel@tonic-gate if (mouse8042_debug) 6737c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_wput:leaving\n"); 6747c478bd9Sstevel@tonic-gate #endif 6757c478bd9Sstevel@tonic-gate return (0); /* ignored */ 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate static uint_t 6797c478bd9Sstevel@tonic-gate mouse8042_intr(caddr_t arg) 6807c478bd9Sstevel@tonic-gate { 6817c478bd9Sstevel@tonic-gate unsigned char mdata; 6827c478bd9Sstevel@tonic-gate mblk_t *mp; 6837c478bd9Sstevel@tonic-gate struct mouse_state *state = (struct mouse_state *)arg; 6847c478bd9Sstevel@tonic-gate int rc; 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate mutex_enter(&state->ms_mutex); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 6897c478bd9Sstevel@tonic-gate if (mouse8042_debug) 6907c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_intr()\n"); 6917c478bd9Sstevel@tonic-gate #endif 6927c478bd9Sstevel@tonic-gate rc = DDI_INTR_UNCLAIMED; 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate for (;;) { 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate if (ddi_get8(state->ms_handle, 6977c478bd9Sstevel@tonic-gate state->ms_addr + I8042_INT_INPUT_AVAIL) == 0) { 6987c478bd9Sstevel@tonic-gate break; 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate mdata = ddi_get8(state->ms_handle, 7027c478bd9Sstevel@tonic-gate state->ms_addr + I8042_INT_INPUT_DATA); 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate #if defined(MOUSE8042_DEBUG) 7057c478bd9Sstevel@tonic-gate if (mouse8042_debug) 7067c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_intr: got %2x\n", mdata); 7077c478bd9Sstevel@tonic-gate if (mouse8042_debug_minimal) 7087c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "<A:%2x ", mdata); 7097c478bd9Sstevel@tonic-gate #endif 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate rc = DDI_INTR_CLAIMED; 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate if (state->ms_rqp != NULL && (mp = allocb(1, BPRI_MED))) { 7147c478bd9Sstevel@tonic-gate *mp->b_wptr++ = mdata; 7157c478bd9Sstevel@tonic-gate putnext(state->ms_rqp, mp); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate #ifdef MOUSE8042_DEBUG 7197c478bd9Sstevel@tonic-gate if (mouse8042_debug) 7207c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "mouse8042_intr() ok\n"); 7217c478bd9Sstevel@tonic-gate #endif 7227c478bd9Sstevel@tonic-gate mutex_exit(&state->ms_mutex); 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate return (rc); 7257c478bd9Sstevel@tonic-gate } 726