4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
28 #include <sys/inline.h>
30 #include <sys/sunddi.h>
31 #include <sys/sunndi.h>
32 #include <sys/i8042.h>
34 #include <sys/promif.h> /* for prom_printf */
38 * Note: For x86, this driver is used to create keyboard/mouse nodes when
39 * booting with ACPI enumeration turned off (acpi-enum=off).
43 * Unfortunately, soft interrupts are implemented poorly. Each additional
44 * soft interrupt user impacts the performance of all existing soft interrupt
45 * users. This is not the case on SPARC, however.
48 #define USE_SOFT_INTRS
54 * The command bytes are different for x86 and for SPARC because on x86,
55 * all modern 8042s can properly translate scan code set 2 codes to
56 * scan code set 1. On SPARC systems that have 8042s (e.g. Tadpole laptops),
57 * setting the "translation" bit in the command byte has no effect.
58 * This is potentially dangerous if, in the future, new SPARC systems uses 8042s
59 * that implement the scan code translation when the translation bit is set.
61 * On SPARC, kb8042 will attempt to detect which scan code set the keyboard
62 * is using. In order for that code to work, the real scan code set must be the
63 * set that is returned by the keyboard (and not a different set that is
64 * translated by the 8042). (e.g. If the translation bit were enabled here,
65 * and the keyboard returned scan code set 2 when kb8042 queried it, kb8042
66 * would not be able to know with certainty that the scan codes it will receive
67 * are set 2 scancodes, or set 1 translations made by the 8042).
71 * 8042 Command Byte Layout:
73 * 0x80: 0 = Reserved, must be zero.
74 * 0x40: 1 = Translate to XT codes. (0=No translation)
75 * 0x20: 1 = Disable aux (mouse) port. (0=Enable port)
76 * 0x10: 1 = Disable main (keyboard) port. (0=Enable port)
77 * 0x08: 0 = Reserved, must be zero.
78 * 0x04: 1 = System flag, 1 means passed self-test.
79 * Caution: setting this bit to zero causes some
80 * systems (HP Kayak XA) to fail to reboot without
82 * 0x02: 0 = Disable aux port interrupts. (1=Enable aux port interrupts)
83 * 0x01: 0 = Disable main port interrupts. (1=Enable main port interrupts)
87 #define I8042_CMD_DISABLE_ALL 0x34
88 #define I8042_CMD_ENABLE_ALL 0x07
89 #elif defined(__i386) || defined(__amd64)
90 #define I8042_CMD_DISABLE_ALL 0x74
91 #define I8042_CMD_ENABLE_ALL 0x47
97 * Child nodes, used to determine which to create at bus_config time
99 #define I8042_KEYBOARD 2
100 #define I8042_MOUSE 1
110 * Only register at most MAX_INTERRUPTS interrupt handlers,
111 * regardless of the number of interrupts in the prom node.
112 * This is important, as registering for all interrupts on
113 * some systems (e.g. Tadpole laptops) results in a flood
114 * of spurious interrupts (for Tadpole, the first 2 interrupts
115 * are for the keyboard and mouse, respectively, and the
116 * third is for a proprietary device that is also accessed
117 * via the same I/O addresses.)
119 #define MAX_INTERRUPTS 2
122 * One of these for each port - main (keyboard) and aux (mouse).
125 boolean_t initialized
;
128 enum i8042_ports which
; /* main or aux port */
129 #if defined(USE_SOFT_INTRS)
130 ddi_softint_handle_t soft_hdl
;
131 boolean_t soft_intr_enabled
;
135 uint_t (*intr_func
)(caddr_t arg1
, caddr_t arg2
);
138 struct i8042
*i8042_global
;
140 * wptr is next byte to write
144 * rptr is next byte to read, == wptr means empty
145 * NB: At full, one byte is unused.
149 unsigned char buf
[BUFSIZ
];
151 * has_glock is 1 if this child has the [put8] exclusive-access lock.
153 volatile boolean_t has_glock
;
157 * Describes entire 8042 device.
161 struct i8042_port i8042_ports
[NUM_PORTS
];
162 kmutex_t i8042_mutex
;
163 kmutex_t i8042_out_mutex
;
164 boolean_t initialized
;
165 ddi_acc_handle_t io_handle
;
168 ddi_iblock_cookie_t
*iblock_cookies
;
170 /* Initialization states: */
171 #define I8042_INIT_BASIC 0x00000001
172 #define I8042_INIT_REGS_MAPPED 0x00000002
173 #define I8042_INIT_MUTEXES 0x00000004
174 #define I8042_INIT_INTRS_ENABLED 0x00000010
177 timeout_id_t timeout_id
;
180 * glock is 1 if any child has the [put8] exclusive-access lock
181 * glock_cv is associated with the condition `glock == 0'
185 * Callers awaiting exclusive access in i8042_put8 sleep on glock_cv
186 * and are signaled when another child relinquishes exclusive access.
192 * i8042 hardware register definitions
196 * These are I/O registers, relative to the device's base (normally 0x60).
198 #define I8042_DATA 0x00 /* read/write data here */
199 #define I8042_STAT 0x04 /* read status here */
200 #define I8042_CMD 0x04 /* write commands here */
203 * These are bits in I8042_STAT.
205 #define I8042_STAT_OUTBF 0x01 /* Output (to host) buffer full */
206 #define I8042_STAT_INBF 0x02 /* Input (from host) buffer full */
207 #define I8042_STAT_AUXBF 0x20 /* Output buffer data is from aux */
210 * These are commands to the i8042 itself (as distinct from the devices
213 #define I8042_CMD_RCB 0x20 /* Read command byte (we don't use) */
214 #define I8042_CMD_WCB 0x60 /* Write command byte */
215 #define I8042_CMD_WRITE_AUX 0xD4 /* Send next data byte to aux port */
218 * Maximum number of times to loop while clearing pending data from the
219 * keyboard controller.
221 #define MAX_JUNK_ITERATIONS 1000
224 * Maximum time to wait for the keyboard to become ready to accept data
225 * (maximum time = MAX_WAIT_ITERATIONS * USECS_PER_WAIT (default is 250ms))
227 #define MAX_WAIT_ITERATIONS 25000
228 #define USECS_PER_WAIT 10
233 #define PLATFORM_MATCH(s) (strncmp(ddi_get_name(ddi_root_node()), \
234 (s), strlen(s)) == 0)
237 * On some older SPARC platforms that have problems with the
238 * interrupt line attached to the PS/2 keyboard/mouse, it
239 * may be necessary to change the operating mode of the nexus
240 * to a polling-based (instead of interrupt-based) method.
241 * this variable is present to enable a worst-case workaround so
242 * owners of these systems can still retain a working keyboard.
244 * The `i8042_polled_mode' variable can be used to force polled
245 * mode for platforms that have this issue, but for which
246 * automatic relief is not implemented.
248 * In the off chance that one of the platforms is misidentified
249 * as requiried polling mode, `i8042_force_interrupt_mode' can
250 * be set to force the nexus to use interrupts.
252 #define I8042_MIN_POLL_INTERVAL 1000 /* usecs */
253 int i8042_poll_interval
= 8000; /* usecs */
254 int i8042_fast_poll_interval
; /* usecs */
255 int i8042_slow_poll_interval
; /* usecs */
257 boolean_t i8042_polled_mode
= B_FALSE
;
258 boolean_t i8042_force_interrupt_mode
= B_FALSE
;
261 int max_wait_iterations
= MAX_WAIT_ITERATIONS
;
268 * function prototypes for bus ops routines:
270 static int i8042_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
271 off_t offset
, off_t len
, caddr_t
*addrp
);
272 static int i8042_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
273 ddi_ctl_enum_t op
, void *arg
, void *result
);
276 * function prototypes for dev ops routines:
278 static int i8042_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
);
279 static int i8042_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
);
280 static int i8042_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
,
281 ddi_intr_op_t intr_op
, ddi_intr_handle_impl_t
*hdlp
, void *result
);
282 static int i8042_bus_config(dev_info_t
*, uint_t
, ddi_bus_config_op_t
,
283 void *, dev_info_t
**);
284 static int i8042_bus_unconfig(dev_info_t
*, uint_t
,
285 ddi_bus_config_op_t
, void *);
287 static int i8042_build_interrupts_property(dev_info_t
*dip
);
288 static boolean_t
i8042_is_polling_platform(void);
292 * bus ops and dev ops structures:
294 static struct bus_ops i8042_bus_ops
= {
300 NULL
, /* ddi_map_fault */
301 NULL
, /* ddi_dma_map */
302 NULL
, /* ddi_dma_allochdl */
303 NULL
, /* ddi_dma_freehdl */
304 NULL
, /* ddi_dma_bindhdl */
305 NULL
, /* ddi_dma_unbindhdl */
306 NULL
, /* ddi_dma_flush */
307 NULL
, /* ddi_dma_win */
308 NULL
, /* ddi_dma_mctl */
311 NULL
, /* (*bus_get_eventcookie)(); */
312 NULL
, /* (*bus_add_eventcall)(); */
313 NULL
, /* (*bus_remove_eventcall)(); */
314 NULL
, /* (*bus_post_event)(); */
315 NULL
, /* bus_intr_ctl */
316 i8042_bus_config
, /* bus_config */
317 i8042_bus_unconfig
, /* bus_unconfig */
318 NULL
, /* bus_fm_init */
319 NULL
, /* bus_fm_fini */
320 NULL
, /* bus_fm_access_enter */
321 NULL
, /* bus_fm_access_exit */
322 NULL
, /* bus_power */
323 i8042_intr_ops
/* bus_intr_op */
326 static struct dev_ops i8042_ops
= {
338 ddi_quiesce_not_needed
,
343 * module definitions:
345 #include <sys/modctl.h>
346 extern struct mod_ops mod_driverops
;
348 static struct modldrv modldrv
= {
349 &mod_driverops
, /* Type of module. This one is a driver */
350 "i8042 nexus driver", /* Name of module. */
351 &i8042_ops
, /* driver ops */
354 static struct modlinkage modlinkage
= {
355 MODREV_1
, (void *)&modldrv
, NULL
364 * Install the module.
366 e
= mod_install(&modlinkage
);
378 e
= mod_remove(&modlinkage
);
386 _info(struct modinfo
*modinfop
)
388 return (mod_info(&modlinkage
, modinfop
));
391 #define DRIVER_NAME(dip) ddi_driver_name(dip)
393 static void i8042_timeout(void *arg
);
394 static unsigned int i8042_intr(caddr_t arg
);
395 static void i8042_write_command_byte(struct i8042
*, unsigned char);
396 static uint8_t i8042_get8(ddi_acc_impl_t
*handlep
, uint8_t *addr
);
397 static void i8042_put8(ddi_acc_impl_t
*handlep
, uint8_t *addr
,
399 static void i8042_send(struct i8042
*global
, int reg
, unsigned char cmd
);
400 static uint8_t i8042_get8(ddi_acc_impl_t
*handlep
, uint8_t *addr
);
402 unsigned int i8042_unclaimed_interrupts
= 0;
405 i8042_discard_junk_data(struct i8042
*global
)
407 /* Discard any junk data that may have been left around */
411 stat
= ddi_get8(global
->io_handle
,
412 global
->io_addr
+ I8042_STAT
);
413 if (! (stat
& I8042_STAT_OUTBF
))
415 (void) ddi_get8(global
->io_handle
,
416 global
->io_addr
+ I8042_DATA
);
422 i8042_cleanup(struct i8042
*global
)
425 struct i8042_port
*port
;
427 ASSERT(global
!= NULL
);
429 if (global
->initialized
== B_TRUE
) {
431 * If any children still have regs mapped or interrupts
432 * registered, return immediate failure (and do nothing).
434 mutex_enter(&global
->i8042_mutex
);
436 for (which_port
= 0; which_port
< NUM_PORTS
; which_port
++) {
437 port
= &global
->i8042_ports
[which_port
];
439 if (port
->initialized
== B_TRUE
) {
440 mutex_exit(&global
->i8042_mutex
);
441 return (DDI_FAILURE
);
443 #if defined(USE_SOFT_INTRS)
444 if (port
->soft_hdl
!= 0) {
445 mutex_exit(&global
->i8042_mutex
);
446 return (DDI_FAILURE
);
449 mutex_enter(&port
->intr_mutex
);
450 if (port
->intr_func
!= NULL
) {
451 mutex_exit(&port
->intr_mutex
);
452 mutex_exit(&global
->i8042_mutex
);
453 return (DDI_FAILURE
);
455 mutex_exit(&port
->intr_mutex
);
458 global
->initialized
= B_FALSE
;
460 mutex_exit(&global
->i8042_mutex
);
464 /* If there may be an outstanding timeout, cancel it */
465 if (global
->timeout_id
!= 0) {
466 (void) untimeout(global
->timeout_id
);
470 /* Stop the controller from generating interrupts */
471 if (global
->init_state
& I8042_INIT_INTRS_ENABLED
)
472 i8042_write_command_byte(global
, I8042_CMD_DISABLE_ALL
);
474 if (global
->intrs_added
) {
476 * Remove the interrupts in the reverse order in
477 * which they were added
479 for (i
= global
->nintrs
- 1; i
>= 0; i
--) {
480 if (global
->intrs_added
& (1 << i
))
481 ddi_remove_intr(global
->dip
, i
,
482 global
->iblock_cookies
[i
]);
487 if (global
->init_state
& I8042_INIT_MUTEXES
) {
488 for (which_port
= 0; which_port
< NUM_PORTS
; which_port
++) {
489 #ifndef USE_SOFT_INTRS
490 port
= &global
->i8042_ports
[which_port
];
491 mutex_destroy(&port
->intr_mutex
);
494 cv_destroy(&global
->glock_cv
);
495 mutex_destroy(&global
->i8042_out_mutex
);
496 mutex_destroy(&global
->i8042_mutex
);
499 if (global
->init_state
& I8042_INIT_REGS_MAPPED
)
500 ddi_regs_map_free(&global
->io_handle
);
502 if (global
->init_state
& I8042_INIT_BASIC
) {
503 ddi_set_driver_private(global
->dip
, (caddr_t
)NULL
);
504 if (global
->nintrs
> 0) {
505 kmem_free(global
->iblock_cookies
, global
->nintrs
*
506 sizeof (ddi_iblock_cookie_t
));
508 kmem_free(global
, sizeof (struct i8042
));
511 return (DDI_SUCCESS
);
514 #define OBF_WAIT_COUNT 1000 /* in granules of 10uS */
517 * Wait for the 8042 to fill the 'output' (from 8042 to host)
518 * buffer. If 8042 fails to fill the output buffer within an
519 * allowed time, return 1 (which means there is no data available),
523 i8042_wait_obf(struct i8042
*global
)
527 while (!(ddi_get8(global
->io_handle
, global
->io_addr
+ I8042_STAT
) &
529 if (++timer
> OBF_WAIT_COUNT
)
538 * Drain all queued bytes from the 8042.
539 * Return 0 for no error, <> 0 if there was an error.
542 i8042_purge_outbuf(struct i8042
*global
)
546 for (i
= 0; i
< MAX_JUNK_ITERATIONS
; i
++) {
547 if (i8042_wait_obf(global
))
549 (void) ddi_get8(global
->io_handle
,
550 global
->io_addr
+ I8042_DATA
);
554 * If we hit the maximum number of iterations, then there
555 * was a serious problem (e.g. our hardware may not be
556 * present or working properly).
558 return (i
== MAX_JUNK_ITERATIONS
);
562 i8042_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
564 struct i8042_port
*port
;
565 enum i8042_ports which_port
;
567 #if !defined(USE_SOFT_INTRS)
568 ddi_iblock_cookie_t cookie
;
570 static ddi_device_acc_attr_t attr
= {
575 struct i8042
*global
;
582 global
= (struct i8042
*)ddi_get_driver_private(dip
);
583 i8042_discard_junk_data(global
);
584 i8042_write_command_byte(global
, I8042_CMD_ENABLE_ALL
);
585 return (DDI_SUCCESS
);
588 /* Handled in the main function block */
592 return (DDI_FAILURE
);
596 * DDI_ATTACH processing
599 global
= (struct i8042
*)kmem_zalloc(sizeof (struct i8042
), KM_SLEEP
);
600 ddi_set_driver_private(dip
, (caddr_t
)global
);
602 global
->initialized
= B_FALSE
;
604 global
->init_state
|= I8042_INIT_BASIC
;
606 if (ddi_regs_map_setup(dip
, 0, (caddr_t
*)&global
->io_addr
,
607 (offset_t
)0, (offset_t
)0, &attr
, &global
->io_handle
)
611 global
->init_state
|= I8042_INIT_REGS_MAPPED
;
614 * Get the number of interrupts for this nexus
616 if (ddi_dev_nintrs(dip
, &global
->nintrs
) == DDI_FAILURE
)
620 if ((i8042_polled_mode
|| i8042_is_polling_platform()) &&
621 !i8042_force_interrupt_mode
) {
623 * If we're on a platform that has known
624 * interrupt issues with the keyboard/mouse,
627 i8042_polled_mode
= B_TRUE
;
629 } else if (global
->nintrs
== 0) {
631 * If there are no interrupts on the i8042 node,
632 * we may be on a brain-dead platform that only
633 * has interrupts properties on i8042's children
634 * (e.g. some UltraII-based boards)
635 * In this case, scan first-level children, and
636 * build a list of interrupts that each child uses,
637 * then create an `interrupts' property on the nexus node
638 * that contains the interrupts used by all children
640 if (i8042_build_interrupts_property(dip
) == DDI_FAILURE
||
641 ddi_dev_nintrs(dip
, &global
->nintrs
) == DDI_FAILURE
||
642 global
->nintrs
== 0) {
643 cmn_err(CE_WARN
, "i8042#%d: No interrupts defined!",
644 ddi_get_instance(global
->dip
));
649 if (global
->nintrs
== 0) {
650 cmn_err(CE_WARN
, "i8042#%d: No interrupts defined!",
651 ddi_get_instance(global
->dip
));
656 if (global
->nintrs
> MAX_INTERRUPTS
)
657 global
->nintrs
= MAX_INTERRUPTS
;
659 if (global
->nintrs
> 0) {
660 global
->iblock_cookies
= kmem_zalloc(global
->nintrs
*
661 sizeof (ddi_iblock_cookie_t
), KM_NOSLEEP
);
663 for (i
= 0; i
< global
->nintrs
; i
++) {
664 if (ddi_get_iblock_cookie(dip
, i
,
665 &global
->iblock_cookies
[i
]) != DDI_SUCCESS
)
669 global
->iblock_cookies
= NULL
;
671 mutex_init(&global
->i8042_mutex
, NULL
, MUTEX_DRIVER
,
672 (global
->nintrs
> 0) ? global
->iblock_cookies
[0] : NULL
);
674 mutex_init(&global
->i8042_out_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
676 cv_init(&global
->glock_cv
, NULL
, CV_DRIVER
, NULL
);
678 for (which_port
= 0; which_port
< NUM_PORTS
; ++which_port
) {
679 port
= &global
->i8042_ports
[which_port
];
680 port
->initialized
= B_FALSE
;
681 port
->i8042_global
= global
;
682 port
->which
= which_port
;
683 #if defined(USE_SOFT_INTRS)
688 * Assume that the interrupt block cookie for port <n>
689 * is iblock_cookies[<n>] (a 1:1 mapping). If there are not
690 * enough interrupts to cover the number of ports, use
691 * the cookie from interrupt 0.
693 if (global
->nintrs
> 0) {
694 cookie
= global
->iblock_cookies
[
695 (which_port
< global
->nintrs
) ? which_port
: 0];
697 mutex_init(&port
->intr_mutex
, NULL
, MUTEX_DRIVER
,
701 mutex_init(&port
->intr_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
707 global
->init_state
|= I8042_INIT_MUTEXES
;
710 * Disable input and interrupts from both the main and aux ports.
712 * It is difficult if not impossible to read the command byte in
713 * a completely clean way. Reading the command byte may cause
714 * an interrupt, and there is no way to suppress interrupts without
715 * writing the command byte. On a PC we might rely on the fact
716 * that IRQ 1 is disabled and guaranteed not shared, but on
717 * other platforms the interrupt line might be shared and so
718 * causing an interrupt could be bad.
720 * Since we can't read the command byte and update it, we
721 * just set it to static values.
723 i8042_write_command_byte(global
, I8042_CMD_DISABLE_ALL
);
725 global
->init_state
&= ~I8042_INIT_INTRS_ENABLED
;
727 /* Discard any junk data that may have been left around */
728 if (i8042_purge_outbuf(global
) != 0)
733 * Assume the number of interrupts is less that the number of
734 * bits in the variable used to keep track of which interrupt
737 ASSERT(global
->nintrs
<= (sizeof (global
->intrs_added
) * NBBY
));
739 for (i
= 0; i
< global
->nintrs
; i
++) {
741 * The 8042 handles all interrupts, because all
742 * device access goes through the same I/O addresses.
744 if (ddi_add_intr(dip
, i
,
745 (ddi_iblock_cookie_t
*)NULL
,
746 (ddi_idevice_cookie_t
*)NULL
,
747 i8042_intr
, (caddr_t
)global
) != DDI_SUCCESS
)
750 global
->intrs_added
|= (1 << i
);
753 global
->initialized
= B_TRUE
;
756 * Enable the main and aux data ports and interrupts
758 i8042_write_command_byte(global
, I8042_CMD_ENABLE_ALL
);
759 global
->init_state
|= I8042_INIT_INTRS_ENABLED
;
762 if (i8042_polled_mode
) {
764 * Do not allow anyone to set the polling interval
765 * to an interval more frequent than I8042_MIN_POLL_INTERVAL --
766 * it could hose the system.
768 interval
= i8042_poll_interval
;
769 if (interval
< I8042_MIN_POLL_INTERVAL
)
770 interval
= I8042_MIN_POLL_INTERVAL
;
771 i8042_fast_poll_interval
= interval
;
772 i8042_slow_poll_interval
= interval
<< 3;
774 global
->timeout_id
= timeout(i8042_timeout
, global
,
775 drv_usectohz(i8042_slow_poll_interval
));
779 return (DDI_SUCCESS
);
782 /* cleanup will succeed because no children have attached yet */
783 (void) i8042_cleanup(global
);
784 return (DDI_FAILURE
);
789 i8042_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
791 struct i8042
*global
= (struct i8042
*)ddi_get_driver_private(dip
);
793 ASSERT(global
!= NULL
);
798 * Do not disable the keyboard controller for x86 suspend, as
799 * the keyboard can be used to bring the system out of
803 /* Disable interrupts and controller devices before suspend */
804 i8042_write_command_byte(global
, I8042_CMD_DISABLE_ALL
);
806 return (DDI_SUCCESS
);
809 /* DETACH can only succeed if cleanup succeeds */
810 return (i8042_cleanup(global
));
813 return (DDI_FAILURE
);
818 * The primary interface to us from our children is via virtual registers.
819 * This is the entry point that allows our children to "map" these
831 struct i8042_port
*port
;
832 struct i8042
*global
;
833 enum i8042_ports which_port
;
835 unsigned int iprop_len
;
837 ddi_acc_hdl_t
*handle
;
840 global
= ddi_get_driver_private(dip
);
842 switch (mp
->map_type
) {
844 which_port
= *(int *)mp
->map_obj
.rp
;
848 rnumber
= mp
->map_obj
.rnumber
;
849 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, rdip
,
850 DDI_PROP_DONTPASS
, "reg", &iprop
, &iprop_len
) !=
853 cmn_err(CE_WARN
, "%s #%d: Missing 'reg' on %s@%s",
854 DRIVER_NAME(dip
), ddi_get_instance(dip
),
855 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
857 return (DDI_FAILURE
);
860 if (iprop_len
!= 1) {
861 cmn_err(CE_WARN
, "%s #%d: Malformed 'reg' on %s@%s",
862 DRIVER_NAME(dip
), ddi_get_instance(dip
),
863 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
864 return (DDI_FAILURE
);
866 if (rnumber
< 0 || rnumber
>= iprop_len
) {
867 cmn_err(CE_WARN
, "%s #%d: bad map request for %s@%s",
868 DRIVER_NAME(dip
), ddi_get_instance(dip
),
869 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
870 return (DDI_FAILURE
);
873 which_port
= iprop
[rnumber
];
874 ddi_prop_free((void *)iprop
);
876 if (which_port
!= MAIN_PORT
&& which_port
!= AUX_PORT
) {
878 "%s #%d: bad 'reg' value %d on %s@%s",
879 DRIVER_NAME(dip
), ddi_get_instance(dip
),
881 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
882 return (DDI_FAILURE
);
889 cmn_err(CE_WARN
, "%s #%d: unknown map type %d for %s@%s",
890 DRIVER_NAME(dip
), ddi_get_instance(dip
),
892 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
894 return (DDI_FAILURE
);
898 if (offset
!= 0 || len
!= 0) {
900 "%s #%d: partial mapping attempt for %s@%s ignored",
901 DRIVER_NAME(dip
), ddi_get_instance(dip
),
902 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
906 port
= &global
->i8042_ports
[which_port
];
908 switch (mp
->map_op
) {
909 case DDI_MO_MAP_LOCKED
:
910 #if defined(USE_SOFT_INTRS)
911 port
->soft_intr_enabled
= B_FALSE
;
913 port
->intr_func
= NULL
;
919 port
->has_glock
= B_FALSE
;
920 port
->initialized
= B_TRUE
;
922 handle
= mp
->map_handlep
;
923 handle
->ah_bus_private
= port
;
925 ap
= (ddi_acc_impl_t
*)handle
->ah_platform_private
;
927 * Support get8, put8 and _rep_put8
929 ap
->ahi_put8
= i8042_put8
;
930 ap
->ahi_get8
= i8042_get8
;
931 ap
->ahi_put16
= NULL
;
932 ap
->ahi_get16
= NULL
;
933 ap
->ahi_put32
= NULL
;
934 ap
->ahi_get32
= NULL
;
935 ap
->ahi_put64
= NULL
;
936 ap
->ahi_get64
= NULL
;
937 ap
->ahi_rep_put8
= NULL
;
938 ap
->ahi_rep_get8
= NULL
;
939 ap
->ahi_rep_put16
= NULL
;
940 ap
->ahi_rep_get16
= NULL
;
941 ap
->ahi_rep_put32
= NULL
;
942 ap
->ahi_rep_get32
= NULL
;
943 ap
->ahi_rep_put64
= NULL
;
944 ap
->ahi_rep_get64
= NULL
;
946 return (DDI_SUCCESS
);
949 port
->initialized
= B_FALSE
;
950 return (DDI_SUCCESS
);
953 cmn_err(CE_WARN
, "%s: map operation %d not supported",
954 DRIVER_NAME(dip
), mp
->map_op
);
955 return (DDI_FAILURE
);
961 i8042_timeout(void *arg
)
963 struct i8042
*i8042_p
= (struct i8042
*)arg
;
967 * Allow the polling speed to be changed on the fly --
968 * catch it here and update the intervals used.
970 if (i8042_fast_poll_interval
!= i8042_poll_interval
) {
971 interval
= i8042_poll_interval
;
972 if (interval
< I8042_MIN_POLL_INTERVAL
)
973 interval
= I8042_MIN_POLL_INTERVAL
;
974 i8042_fast_poll_interval
= interval
;
975 i8042_slow_poll_interval
= interval
<< 3;
979 * If the ISR returned true, start polling at a faster rate to
980 * increate responsiveness. Once the keyboard or mouse go idle,
981 * the ISR will return UNCLAIMED, and we'll go back to the slower
982 * polling rate. This gives some positive hysteresis (but not
983 * negative, since we go back to the slower polling interval after
984 * only one UNCLAIMED). This has shown to be responsive enough,
985 * even for fast typers.
987 interval
= (i8042_intr((caddr_t
)i8042_p
) == DDI_INTR_CLAIMED
) ?
988 i8042_fast_poll_interval
: i8042_slow_poll_interval
;
990 if (i8042_polled_mode
)
991 i8042_p
->timeout_id
= timeout(i8042_timeout
, arg
,
992 drv_usectohz(interval
));
994 i8042_p
->timeout_id
= 0;
999 * i8042 hardware interrupt routine. Called for both main and aux port
1003 i8042_intr(caddr_t arg
)
1005 struct i8042
*global
= (struct i8042
*)arg
;
1006 enum i8042_ports which_port
;
1010 struct i8042_port
*port
;
1012 mutex_enter(&global
->i8042_mutex
);
1014 stat
= ddi_get8(global
->io_handle
, global
->io_addr
+ I8042_STAT
);
1016 if (! (stat
& I8042_STAT_OUTBF
)) {
1017 ++i8042_unclaimed_interrupts
;
1018 mutex_exit(&global
->i8042_mutex
);
1019 return (DDI_INTR_UNCLAIMED
);
1022 byte
= ddi_get8(global
->io_handle
, global
->io_addr
+ I8042_DATA
);
1024 which_port
= (stat
& I8042_STAT_AUXBF
) ? AUX_PORT
: MAIN_PORT
;
1026 port
= &global
->i8042_ports
[which_port
];
1028 if (! port
->initialized
) {
1029 mutex_exit(&global
->i8042_mutex
);
1030 return (DDI_INTR_CLAIMED
);
1033 new_wptr
= (port
->wptr
+ 1) % BUFSIZ
;
1034 if (new_wptr
== port
->rptr
) {
1037 if (port
->overruns
% 50 == 1) {
1038 cmn_err(CE_WARN
, "i8042/%d: %d overruns\n",
1039 which_port
, port
->overruns
);
1043 mutex_exit(&global
->i8042_mutex
);
1044 return (DDI_INTR_CLAIMED
);
1047 port
->buf
[port
->wptr
] = byte
;
1048 port
->wptr
= new_wptr
;
1050 #if defined(USE_SOFT_INTRS)
1051 if (port
->soft_intr_enabled
)
1052 (void) ddi_intr_trigger_softint(port
->soft_hdl
,
1056 mutex_exit(&global
->i8042_mutex
);
1058 #if !defined(USE_SOFT_INTRS)
1059 mutex_enter(&port
->intr_mutex
);
1060 if (port
->intr_func
!= NULL
)
1061 port
->intr_func(port
->intr_arg1
, NULL
);
1062 mutex_exit(&port
->intr_mutex
);
1065 return (DDI_INTR_CLAIMED
);
1069 i8042_write_command_byte(struct i8042
*global
, unsigned char cb
)
1071 mutex_enter(&global
->i8042_out_mutex
);
1072 i8042_send(global
, I8042_CMD
, I8042_CMD_WCB
);
1073 i8042_send(global
, I8042_DATA
, cb
);
1074 mutex_exit(&global
->i8042_out_mutex
);
1078 * Send a byte to either the i8042 command or data register, depending on
1082 i8042_send(struct i8042
*global
, int reg
, unsigned char val
)
1088 * First, wait for the i8042 to be ready to accept data.
1090 /*CONSTANTCONDITION*/
1092 stat
= ddi_get8(global
->io_handle
,
1093 global
->io_addr
+ I8042_STAT
);
1095 if ((stat
& I8042_STAT_INBF
) == 0) {
1096 ddi_put8(global
->io_handle
, global
->io_addr
+reg
, val
);
1100 /* Don't wait unless we're going to check again */
1101 if (++tries
>= max_wait_iterations
)
1104 drv_usecwait(USECS_PER_WAIT
);
1108 if (tries
>= MAX_WAIT_ITERATIONS
)
1109 cmn_err(CE_WARN
, "i8042_send: timeout!");
1114 * Here's the interface to the virtual registers on the device.
1116 * Normal interrupt-driven I/O:
1118 * I8042_INT_INPUT_AVAIL (r/o)
1119 * Interrupt mode input bytes available? Zero = No.
1120 * I8042_INT_INPUT_DATA (r/o)
1121 * Fetch interrupt mode input byte.
1122 * I8042_INT_OUTPUT_DATA (w/o)
1123 * Interrupt mode output byte.
1125 * Polled I/O, used by (e.g.) kmdb, when normal system services are
1128 * I8042_POLL_INPUT_AVAIL (r/o)
1129 * Polled mode input bytes available? Zero = No.
1130 * I8042_POLL_INPUT_DATA (r/o)
1131 * Polled mode input byte.
1132 * I8042_POLL_OUTPUT_DATA (w/o)
1133 * Polled mode output byte.
1135 * Note that in polled mode we cannot use cmn_err; only prom_printf is safe.
1138 i8042_get8(ddi_acc_impl_t
*handlep
, uint8_t *addr
)
1140 struct i8042_port
*port
;
1141 struct i8042
*global
;
1146 h
= (ddi_acc_hdl_t
*)handlep
;
1148 port
= (struct i8042_port
*)h
->ah_bus_private
;
1149 global
= port
->i8042_global
;
1151 switch ((uintptr_t)addr
) {
1153 ASSERT(port
->has_glock
!= B_TRUE
); /* No reentrancy */
1154 mutex_enter(&global
->i8042_out_mutex
);
1156 * Block other children requesting exclusive access here until
1157 * the child possessing it relinquishes the lock.
1159 while (global
->glock
) {
1160 cv_wait(&global
->glock_cv
, &global
->i8042_out_mutex
);
1162 port
->has_glock
= B_TRUE
;
1164 mutex_exit(&global
->i8042_out_mutex
);
1169 mutex_enter(&global
->i8042_out_mutex
);
1170 ASSERT(global
->glock
!= 0);
1171 ASSERT(port
->has_glock
== B_TRUE
);
1172 port
->has_glock
= B_FALSE
;
1175 * Signal anyone waiting for exclusive access that it is now
1178 cv_signal(&global
->glock_cv
);
1179 mutex_exit(&global
->i8042_out_mutex
);
1183 case I8042_INT_INPUT_AVAIL
:
1184 mutex_enter(&global
->i8042_mutex
);
1185 ret
= port
->rptr
!= port
->wptr
;
1186 mutex_exit(&global
->i8042_mutex
);
1189 case I8042_INT_INPUT_DATA
:
1190 mutex_enter(&global
->i8042_mutex
);
1192 if (port
->rptr
!= port
->wptr
) {
1193 ret
= port
->buf
[port
->rptr
];
1194 port
->rptr
= (port
->rptr
+ 1) % BUFSIZ
;
1198 "i8042: Tried to read from empty buffer");
1204 mutex_exit(&global
->i8042_mutex
);
1209 case I8042_INT_OUTPUT_DATA
:
1210 case I8042_POLL_OUTPUT_DATA
:
1211 cmn_err(CE_WARN
, "i8042: read of write-only register 0x%p",
1217 case I8042_POLL_INPUT_AVAIL
:
1218 if (port
->rptr
!= port
->wptr
)
1221 stat
= ddi_get8(global
->io_handle
,
1222 global
->io_addr
+ I8042_STAT
);
1223 if ((stat
& I8042_STAT_OUTBF
) == 0)
1225 switch (port
->which
) {
1227 if ((stat
& I8042_STAT_AUXBF
) == 0)
1231 if ((stat
& I8042_STAT_AUXBF
) != 0)
1235 cmn_err(CE_WARN
, "data from unknown port: %d",
1239 * Data for wrong port pending; discard it.
1241 (void) ddi_get8(global
->io_handle
,
1242 global
->io_addr
+ I8042_DATA
);
1247 case I8042_POLL_INPUT_DATA
:
1248 if (port
->rptr
!= port
->wptr
) {
1249 ret
= port
->buf
[port
->rptr
];
1250 port
->rptr
= (port
->rptr
+ 1) % BUFSIZ
;
1254 stat
= ddi_get8(global
->io_handle
,
1255 global
->io_addr
+ I8042_STAT
);
1256 if ((stat
& I8042_STAT_OUTBF
) == 0) {
1258 prom_printf("I8042_POLL_INPUT_DATA: no data!\n");
1262 ret
= ddi_get8(global
->io_handle
,
1263 global
->io_addr
+ I8042_DATA
);
1264 switch (port
->which
) {
1266 if ((stat
& I8042_STAT_AUXBF
) == 0)
1270 if ((stat
& I8042_STAT_AUXBF
) != 0)
1275 prom_printf("I8042_POLL_INPUT_DATA: data for wrong port!\n");
1281 cmn_err(CE_WARN
, "i8042: read of undefined register 0x%p",
1291 i8042_put8(ddi_acc_impl_t
*handlep
, uint8_t *addr
, uint8_t value
)
1293 struct i8042
*global
;
1294 struct i8042_port
*port
;
1297 h
= (ddi_acc_hdl_t
*)handlep
;
1298 port
= (struct i8042_port
*)h
->ah_bus_private
;
1299 global
= port
->i8042_global
;
1301 switch ((uintptr_t)addr
) {
1302 case I8042_INT_OUTPUT_DATA
:
1303 case I8042_POLL_OUTPUT_DATA
:
1305 if ((uintptr_t)addr
== I8042_INT_OUTPUT_DATA
) {
1306 mutex_enter(&global
->i8042_out_mutex
);
1309 * If no child has exclusive access, then proceed with
1310 * the put8 below. If a child (not the one making the
1311 * call) has exclusive access, wait for it to be
1312 * relinquished. The use of i8042_out_mutex prevents
1313 * children seeking exclusive access from getting it
1314 * while a child is writing to the 8042.
1316 while (global
->glock
&& !port
->has_glock
) {
1317 cv_wait(&global
->glock_cv
,
1318 &global
->i8042_out_mutex
);
1322 if (port
->which
== AUX_PORT
)
1323 i8042_send(global
, I8042_CMD
, I8042_CMD_WRITE_AUX
);
1325 i8042_send(global
, I8042_DATA
, value
);
1327 if ((uintptr_t)addr
== I8042_INT_OUTPUT_DATA
)
1328 mutex_exit(&global
->i8042_out_mutex
);
1333 case I8042_INT_INPUT_AVAIL
:
1334 case I8042_INT_INPUT_DATA
:
1335 case I8042_POLL_INPUT_AVAIL
:
1336 case I8042_POLL_INPUT_DATA
:
1337 cmn_err(CE_WARN
, "i8042: write of read-only register 0x%p",
1342 cmn_err(CE_WARN
, "i8042: read of undefined register 0x%p",
1352 i8042_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
1353 ddi_intr_handle_impl_t
*hdlp
, void *result
)
1355 struct i8042_port
*port
;
1356 #if defined(USE_SOFT_INTRS)
1357 struct i8042
*global
;
1362 case DDI_INTROP_SUPPORTED_TYPES
:
1363 *(int *)result
= DDI_INTR_TYPE_FIXED
;
1365 case DDI_INTROP_GETCAP
:
1366 if (i_ddi_intr_ops(dip
, rdip
, intr_op
, hdlp
, result
)
1370 case DDI_INTROP_NINTRS
:
1371 case DDI_INTROP_NAVAIL
:
1374 case DDI_INTROP_ALLOC
:
1375 *(int *)result
= hdlp
->ih_scratch1
;
1377 case DDI_INTROP_FREE
:
1379 case DDI_INTROP_GETPRI
:
1380 /* Hard coding it for x86 */
1383 case DDI_INTROP_ADDISR
:
1384 port
= ddi_get_parent_data(rdip
);
1386 #if defined(USE_SOFT_INTRS)
1387 global
= port
->i8042_global
;
1388 ret
= ddi_intr_add_softint(rdip
, &port
->soft_hdl
,
1389 I8042_SOFTINT_PRI
, hdlp
->ih_cb_func
, hdlp
->ih_cb_arg1
);
1391 if (ret
!= DDI_SUCCESS
) {
1393 cmn_err(CE_WARN
, "%s #%d: "
1394 "Cannot add soft interrupt for %s #%d, ret=%d.",
1395 DRIVER_NAME(dip
), ddi_get_instance(dip
),
1396 DRIVER_NAME(rdip
), ddi_get_instance(rdip
), ret
);
1397 #endif /* defined(DEBUG) */
1401 #else /* defined(USE_SOFT_INTRS) */
1402 mutex_enter(&port
->intr_mutex
);
1403 port
->intr_func
= hdlp
->ih_cb_func
;
1404 port
->intr_arg1
= hdlp
->ih_cb_arg1
;
1405 port
->intr_arg2
= hdlp
->ih_cb_arg2
;
1406 mutex_exit(&port
->intr_mutex
);
1407 #endif /* defined(USE_SOFT_INTRS) */
1409 case DDI_INTROP_REMISR
:
1410 port
= ddi_get_parent_data(rdip
);
1412 #if defined(USE_SOFT_INTRS)
1413 global
= port
->i8042_global
;
1414 mutex_enter(&global
->i8042_mutex
);
1416 mutex_exit(&global
->i8042_mutex
);
1417 #else /* defined(USE_SOFT_INTRS) */
1418 mutex_enter(&port
->intr_mutex
);
1419 port
->intr_func
= NULL
;
1420 mutex_exit(&port
->intr_mutex
);
1421 #endif /* defined(USE_SOFT_INTRS) */
1423 case DDI_INTROP_ENABLE
:
1424 port
= ddi_get_parent_data(rdip
);
1425 #if defined(USE_SOFT_INTRS)
1426 global
= port
->i8042_global
;
1427 mutex_enter(&global
->i8042_mutex
);
1428 port
->soft_intr_enabled
= B_TRUE
;
1429 if (port
->wptr
!= port
->rptr
)
1430 (void) ddi_intr_trigger_softint(port
->soft_hdl
,
1432 mutex_exit(&global
->i8042_mutex
);
1433 #else /* defined(USE_SOFT_INTRS) */
1434 mutex_enter(&port
->intr_mutex
);
1435 if (port
->wptr
!= port
->rptr
)
1436 port
->intr_func(port
->intr_arg1
, port
->intr_arg2
);
1437 mutex_exit(&port
->intr_mutex
);
1438 #endif /* defined(USE_SOFT_INTRS) */
1440 case DDI_INTROP_DISABLE
:
1441 #if defined(USE_SOFT_INTRS)
1442 port
= ddi_get_parent_data(rdip
);
1443 global
= port
->i8042_global
;
1444 mutex_enter(&global
->i8042_mutex
);
1445 port
->soft_intr_enabled
= B_FALSE
;
1446 (void) ddi_intr_remove_softint(port
->soft_hdl
);
1447 mutex_exit(&global
->i8042_mutex
);
1448 #endif /* defined(USE_SOFT_INTRS) */
1451 return (DDI_FAILURE
);
1454 return (DDI_SUCCESS
);
1458 i8042_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
1459 ddi_ctl_enum_t op
, void *arg
, void *result
)
1462 unsigned int iprop_len
;
1465 struct i8042
*global
;
1468 global
= ddi_get_driver_private(dip
);
1471 case DDI_CTLOPS_INITCHILD
:
1472 child
= (dev_info_t
*)arg
;
1473 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, child
,
1474 DDI_PROP_DONTPASS
, "reg", &iprop
, &iprop_len
) !=
1477 cmn_err(CE_WARN
, "%s #%d: Missing 'reg' on %s@???",
1478 DRIVER_NAME(dip
), ddi_get_instance(dip
),
1479 ddi_node_name(child
));
1481 return (DDI_FAILURE
);
1483 which_port
= iprop
[0];
1484 ddi_prop_free((void *)iprop
);
1486 (void) sprintf(name
, "%d", which_port
);
1487 ddi_set_name_addr(child
, name
);
1488 ddi_set_parent_data(child
,
1489 (caddr_t
)&global
->i8042_ports
[which_port
]);
1490 return (DDI_SUCCESS
);
1492 case DDI_CTLOPS_UNINITCHILD
:
1493 child
= (dev_info_t
*)arg
;
1494 ddi_set_name_addr(child
, NULL
);
1495 ddi_set_parent_data(child
, NULL
);
1496 return (DDI_SUCCESS
);
1498 case DDI_CTLOPS_REPORTDEV
:
1499 cmn_err(CE_CONT
, "?8042 device: %s@%s, %s # %d\n",
1500 ddi_node_name(rdip
), ddi_get_name_addr(rdip
),
1501 DRIVER_NAME(rdip
), ddi_get_instance(rdip
));
1502 return (DDI_SUCCESS
);
1505 return (ddi_ctlops(dip
, rdip
, op
, arg
, result
));
1510 #if defined(__i386) || defined(__amd64)
1512 i8042_devi_findchild_by_node_name(dev_info_t
*pdip
, char *nodename
)
1516 ASSERT(DEVI_BUSY_OWNED(pdip
));
1518 if (nodename
== NULL
) {
1519 return ((dev_info_t
*)NULL
);
1522 for (child
= ddi_get_child(pdip
); child
!= NULL
;
1523 child
= ddi_get_next_sibling(child
)) {
1525 if (strcmp(ddi_node_name(child
), nodename
) == 0)
1532 alloc_kb_mouse(dev_info_t
*i8042_dip
, int nodes_needed
)
1538 /* don't alloc unless acpi is off */
1539 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, ddi_root_node(),
1540 DDI_PROP_DONTPASS
, "acpi-enum", &acpi_prop
) == DDI_PROP_SUCCESS
) {
1541 if (strcmp("off", acpi_prop
) == 0) {
1544 ddi_prop_free(acpi_prop
);
1546 if (acpi_off
== 0) {
1550 if (nodes_needed
& I8042_MOUSE
) {
1552 ndi_devi_alloc_sleep(i8042_dip
, "mouse",
1553 (pnode_t
)DEVI_SID_NODEID
, &xdip
);
1554 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1556 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1558 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1559 "compatible", "pnpPNP,f03");
1561 * The device_type property does not matter on SPARC. Retain it
1562 * on x86 for compatibility with the previous pseudo-prom.
1564 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1565 "device_type", "mouse");
1566 (void) ndi_devi_bind_driver(xdip
, 0);
1569 if (nodes_needed
& I8042_KEYBOARD
) {
1571 ndi_devi_alloc_sleep(i8042_dip
, "keyboard",
1572 (pnode_t
)DEVI_SID_NODEID
, &xdip
);
1573 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1575 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1577 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1578 "compatible", "pnpPNP,303");
1579 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1580 "device_type", "keyboard");
1581 (void) ndi_devi_bind_driver(xdip
, 0);
1587 i8042_bus_config(dev_info_t
*parent
, uint_t flags
,
1588 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
1590 #if defined(__i386) || defined(__amd64)
1591 int nodes_needed
= 0;
1595 * On x86 systems, if ACPI is disabled, the only way the
1596 * keyboard and mouse can be enumerated is by creating them
1597 * manually. The following code searches for the existence of
1598 * the keyboard and mouse nodes and creates them if they are not
1601 ndi_devi_enter(parent
, &circ
);
1602 if (i8042_devi_findchild_by_node_name(parent
, "keyboard") == NULL
)
1603 nodes_needed
|= I8042_KEYBOARD
;
1604 if (i8042_devi_findchild_by_node_name(parent
, "mouse") == NULL
)
1605 nodes_needed
|= I8042_MOUSE
;
1607 /* If the mouse and keyboard nodes do not already exist, create them */
1609 alloc_kb_mouse(parent
, nodes_needed
);
1610 ndi_devi_exit(parent
, circ
);
1612 return (ndi_busop_bus_config(parent
, flags
, op
, arg
, childp
, 0));
1616 i8042_bus_unconfig(dev_info_t
*parent
, uint_t flags
,
1617 ddi_bus_config_op_t op
, void *arg
)
1620 * The NDI_UNCONFIG flag allows the reference count on this nexus to be
1621 * decremented when children's drivers are unloaded, enabling the nexus
1622 * itself to be unloaded.
1624 return (ndi_busop_bus_unconfig(parent
, flags
| NDI_UNCONFIG
, op
, arg
));
1629 i8042_build_interrupts_property(dev_info_t
*dip
)
1631 dev_info_t
*child
= ddi_get_child(dip
);
1634 int interrupts
[MAX_INTERRUPTS
];
1637 /* Walk the children of this node, scanning for interrupts properties */
1638 while (child
!= NULL
&& i
< MAX_INTERRUPTS
) {
1640 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, child
,
1641 DDI_PROP_DONTPASS
, "interrupts", &intrs
, &nintr
)
1642 == DDI_PROP_SUCCESS
&& intrs
!= NULL
) {
1644 while (nintr
> 0 && i
< MAX_INTERRUPTS
) {
1645 interrupts
[i
++] = intrs
[--nintr
];
1647 ddi_prop_free(intrs
);
1650 child
= ddi_get_next_sibling(child
);
1653 if (ddi_prop_update_int_array(DDI_DEV_T_NONE
, dip
, "interrupts",
1654 interrupts
, i
) != DDI_PROP_SUCCESS
) {
1656 return (DDI_FAILURE
);
1660 * Oh, the humanity. On the platforms on which we need to
1661 * synthesize an interrupts property, we ALSO need to update the
1662 * device_type property, and set it to "serial" in order for the
1663 * correct interrupt PIL to be chosen by the framework.
1665 if (ddi_prop_update_string(DDI_DEV_T_NONE
, dip
, "device_type", "serial")
1666 != DDI_PROP_SUCCESS
) {
1668 return (DDI_FAILURE
);
1671 return (DDI_SUCCESS
);
1675 i8042_is_polling_platform(void)
1678 * Returns true if this platform is one of the platforms
1679 * that has interrupt issues with the PS/2 keyboard/mouse.
1681 if (PLATFORM_MATCH("SUNW,UltraAX-"))