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.
50 * The command bytes are different for x86 and for SPARC because on x86,
51 * all modern 8042s can properly translate scan code set 2 codes to
52 * scan code set 1. On SPARC systems that have 8042s (e.g. Tadpole laptops),
53 * setting the "translation" bit in the command byte has no effect.
54 * This is potentially dangerous if, in the future, new SPARC systems uses 8042s
55 * that implement the scan code translation when the translation bit is set.
57 * On SPARC, kb8042 will attempt to detect which scan code set the keyboard
58 * is using. In order for that code to work, the real scan code set must be the
59 * set that is returned by the keyboard (and not a different set that is
60 * translated by the 8042). (e.g. If the translation bit were enabled here,
61 * and the keyboard returned scan code set 2 when kb8042 queried it, kb8042
62 * would not be able to know with certainty that the scan codes it will receive
63 * are set 2 scancodes, or set 1 translations made by the 8042).
67 * 8042 Command Byte Layout:
69 * 0x80: 0 = Reserved, must be zero.
70 * 0x40: 1 = Translate to XT codes. (0=No translation)
71 * 0x20: 1 = Disable aux (mouse) port. (0=Enable port)
72 * 0x10: 1 = Disable main (keyboard) port. (0=Enable port)
73 * 0x08: 0 = Reserved, must be zero.
74 * 0x04: 1 = System flag, 1 means passed self-test.
75 * Caution: setting this bit to zero causes some
76 * systems (HP Kayak XA) to fail to reboot without
78 * 0x02: 0 = Disable aux port interrupts. (1=Enable aux port interrupts)
79 * 0x01: 0 = Disable main port interrupts. (1=Enable main port interrupts)
83 #define I8042_CMD_DISABLE_ALL 0x34
84 #define I8042_CMD_ENABLE_ALL 0x07
85 #elif defined(__i386) || defined(__amd64)
86 #define I8042_CMD_DISABLE_ALL 0x74
87 #define I8042_CMD_ENABLE_ALL 0x47
93 * Child nodes, used to determine which to create at bus_config time
95 #define I8042_KEYBOARD 2
106 * Only register at most MAX_INTERRUPTS interrupt handlers,
107 * regardless of the number of interrupts in the prom node.
108 * This is important, as registering for all interrupts on
109 * some systems (e.g. Tadpole laptops) results in a flood
110 * of spurious interrupts (for Tadpole, the first 2 interrupts
111 * are for the keyboard and mouse, respectively, and the
112 * third is for a proprietary device that is also accessed
113 * via the same I/O addresses.)
115 #define MAX_INTERRUPTS 2
118 * One of these for each port - main (keyboard) and aux (mouse).
121 boolean_t initialized
;
124 enum i8042_ports which
; /* main or aux port */
125 #if defined(USE_SOFT_INTRS)
126 ddi_softint_handle_t soft_hdl
;
127 boolean_t soft_intr_enabled
;
131 uint_t (*intr_func
)(caddr_t arg1
, caddr_t arg2
);
134 struct i8042
*i8042_global
;
136 * wptr is next byte to write
140 * rptr is next byte to read, == wptr means empty
141 * NB: At full, one byte is unused.
145 unsigned char buf
[BUFSIZ
];
147 * has_glock is 1 if this child has the [put8] exclusive-access lock.
149 volatile boolean_t has_glock
;
153 * Describes entire 8042 device.
157 struct i8042_port i8042_ports
[NUM_PORTS
];
158 kmutex_t i8042_mutex
;
159 kmutex_t i8042_out_mutex
;
160 boolean_t initialized
;
161 ddi_acc_handle_t io_handle
;
164 ddi_iblock_cookie_t
*iblock_cookies
;
166 /* Initialization states: */
167 #define I8042_INIT_BASIC 0x00000001
168 #define I8042_INIT_REGS_MAPPED 0x00000002
169 #define I8042_INIT_MUTEXES 0x00000004
170 #define I8042_INIT_INTRS_ENABLED 0x00000010
173 * glock is 1 if any child has the [put8] exclusive-access lock
174 * glock_cv is associated with the condition `glock == 0'
178 * Callers awaiting exclusive access in i8042_put8 sleep on glock_cv
179 * and are signaled when another child relinquishes exclusive access.
185 * i8042 hardware register definitions
189 * These are I/O registers, relative to the device's base (normally 0x60).
191 #define I8042_DATA 0x00 /* read/write data here */
192 #define I8042_STAT 0x04 /* read status here */
193 #define I8042_CMD 0x04 /* write commands here */
196 * These are bits in I8042_STAT.
198 #define I8042_STAT_OUTBF 0x01 /* Output (to host) buffer full */
199 #define I8042_STAT_INBF 0x02 /* Input (from host) buffer full */
200 #define I8042_STAT_AUXBF 0x20 /* Output buffer data is from aux */
203 * These are commands to the i8042 itself (as distinct from the devices
206 #define I8042_CMD_RCB 0x20 /* Read command byte (we don't use) */
207 #define I8042_CMD_WCB 0x60 /* Write command byte */
208 #define I8042_CMD_WRITE_AUX 0xD4 /* Send next data byte to aux port */
211 * Maximum number of times to loop while clearing pending data from the
212 * keyboard controller.
214 #define MAX_JUNK_ITERATIONS 1000
217 * Maximum time to wait for the keyboard to become ready to accept data
218 * (maximum time = MAX_WAIT_ITERATIONS * USECS_PER_WAIT (default is 250ms))
220 #define MAX_WAIT_ITERATIONS 25000
221 #define USECS_PER_WAIT 10
225 int max_wait_iterations
= MAX_WAIT_ITERATIONS
;
232 * function prototypes for bus ops routines:
234 static int i8042_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
235 off_t offset
, off_t len
, caddr_t
*addrp
);
236 static int i8042_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
237 ddi_ctl_enum_t op
, void *arg
, void *result
);
240 * function prototypes for dev ops routines:
242 static int i8042_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
);
243 static int i8042_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
);
244 static int i8042_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
,
245 ddi_intr_op_t intr_op
, ddi_intr_handle_impl_t
*hdlp
, void *result
);
246 static int i8042_bus_config(dev_info_t
*, uint_t
, ddi_bus_config_op_t
,
247 void *, dev_info_t
**);
248 static int i8042_bus_unconfig(dev_info_t
*, uint_t
,
249 ddi_bus_config_op_t
, void *);
252 * bus ops and dev ops structures:
254 static struct bus_ops i8042_bus_ops
= {
260 NULL
, /* ddi_map_fault */
261 NULL
, /* ddi_dma_map */
262 NULL
, /* ddi_dma_allochdl */
263 NULL
, /* ddi_dma_freehdl */
264 NULL
, /* ddi_dma_bindhdl */
265 NULL
, /* ddi_dma_unbindhdl */
266 NULL
, /* ddi_dma_flush */
267 NULL
, /* ddi_dma_win */
268 NULL
, /* ddi_dma_mctl */
271 NULL
, /* (*bus_get_eventcookie)(); */
272 NULL
, /* (*bus_add_eventcall)(); */
273 NULL
, /* (*bus_remove_eventcall)(); */
274 NULL
, /* (*bus_post_event)(); */
275 NULL
, /* bus_intr_ctl */
276 i8042_bus_config
, /* bus_config */
277 i8042_bus_unconfig
, /* bus_unconfig */
278 NULL
, /* bus_fm_init */
279 NULL
, /* bus_fm_fini */
280 NULL
, /* bus_fm_access_enter */
281 NULL
, /* bus_fm_access_exit */
282 NULL
, /* bus_power */
283 i8042_intr_ops
/* bus_intr_op */
286 static struct dev_ops i8042_ops
= {
298 ddi_quiesce_not_needed
,
303 * module definitions:
305 #include <sys/modctl.h>
306 extern struct mod_ops mod_driverops
;
308 static struct modldrv modldrv
= {
309 &mod_driverops
, /* Type of module. This one is a driver */
310 "i8042 nexus driver", /* Name of module. */
311 &i8042_ops
, /* driver ops */
314 static struct modlinkage modlinkage
= {
315 MODREV_1
, (void *)&modldrv
, NULL
324 * Install the module.
326 e
= mod_install(&modlinkage
);
338 e
= mod_remove(&modlinkage
);
346 _info(struct modinfo
*modinfop
)
348 return (mod_info(&modlinkage
, modinfop
));
351 #define DRIVER_NAME(dip) ddi_driver_name(dip)
353 static void i8042_timeout(void *arg
);
354 static unsigned int i8042_intr(caddr_t arg
);
355 static void i8042_write_command_byte(struct i8042
*, unsigned char);
356 static uint8_t i8042_get8(ddi_acc_impl_t
*handlep
, uint8_t *addr
);
357 static void i8042_put8(ddi_acc_impl_t
*handlep
, uint8_t *addr
,
359 static void i8042_send(struct i8042
*global
, int reg
, unsigned char cmd
);
360 static uint8_t i8042_get8(ddi_acc_impl_t
*handlep
, uint8_t *addr
);
362 unsigned int i8042_unclaimed_interrupts
= 0;
365 i8042_discard_junk_data(struct i8042
*global
)
367 /* Discard any junk data that may have been left around */
371 stat
= ddi_get8(global
->io_handle
,
372 global
->io_addr
+ I8042_STAT
);
373 if (! (stat
& I8042_STAT_OUTBF
))
375 (void) ddi_get8(global
->io_handle
,
376 global
->io_addr
+ I8042_DATA
);
382 i8042_cleanup(struct i8042
*global
)
385 struct i8042_port
*port
;
387 ASSERT(global
!= NULL
);
389 if (global
->initialized
== B_TRUE
) {
391 * If any children still have regs mapped or interrupts
392 * registered, return immediate failure (and do nothing).
394 mutex_enter(&global
->i8042_mutex
);
396 for (which_port
= 0; which_port
< NUM_PORTS
; which_port
++) {
397 port
= &global
->i8042_ports
[which_port
];
399 if (port
->initialized
== B_TRUE
) {
400 mutex_exit(&global
->i8042_mutex
);
401 return (DDI_FAILURE
);
403 #if defined(USE_SOFT_INTRS)
404 if (port
->soft_hdl
!= 0) {
405 mutex_exit(&global
->i8042_mutex
);
406 return (DDI_FAILURE
);
409 mutex_enter(&port
->intr_mutex
);
410 if (port
->intr_func
!= NULL
) {
411 mutex_exit(&port
->intr_mutex
);
412 mutex_exit(&global
->i8042_mutex
);
413 return (DDI_FAILURE
);
415 mutex_exit(&port
->intr_mutex
);
418 global
->initialized
= B_FALSE
;
420 mutex_exit(&global
->i8042_mutex
);
424 /* Stop the controller from generating interrupts */
425 if (global
->init_state
& I8042_INIT_INTRS_ENABLED
)
426 i8042_write_command_byte(global
, I8042_CMD_DISABLE_ALL
);
428 if (global
->intrs_added
) {
430 * Remove the interrupts in the reverse order in
431 * which they were added
433 for (i
= global
->nintrs
- 1; i
>= 0; i
--) {
434 if (global
->intrs_added
& (1 << i
))
435 ddi_remove_intr(global
->dip
, i
,
436 global
->iblock_cookies
[i
]);
441 if (global
->init_state
& I8042_INIT_MUTEXES
) {
442 for (which_port
= 0; which_port
< NUM_PORTS
; which_port
++) {
443 #ifndef USE_SOFT_INTRS
444 port
= &global
->i8042_ports
[which_port
];
445 mutex_destroy(&port
->intr_mutex
);
448 cv_destroy(&global
->glock_cv
);
449 mutex_destroy(&global
->i8042_out_mutex
);
450 mutex_destroy(&global
->i8042_mutex
);
453 if (global
->init_state
& I8042_INIT_REGS_MAPPED
)
454 ddi_regs_map_free(&global
->io_handle
);
456 if (global
->init_state
& I8042_INIT_BASIC
) {
457 ddi_set_driver_private(global
->dip
, NULL
);
458 if (global
->nintrs
> 0) {
459 kmem_free(global
->iblock_cookies
, global
->nintrs
*
460 sizeof (ddi_iblock_cookie_t
));
462 kmem_free(global
, sizeof (struct i8042
));
465 return (DDI_SUCCESS
);
468 #define OBF_WAIT_COUNT 1000 /* in granules of 10uS */
471 * Wait for the 8042 to fill the 'output' (from 8042 to host)
472 * buffer. If 8042 fails to fill the output buffer within an
473 * allowed time, return 1 (which means there is no data available),
477 i8042_wait_obf(struct i8042
*global
)
481 while (!(ddi_get8(global
->io_handle
, global
->io_addr
+ I8042_STAT
) &
483 if (++timer
> OBF_WAIT_COUNT
)
492 * Drain all queued bytes from the 8042.
493 * Return 0 for no error, <> 0 if there was an error.
496 i8042_purge_outbuf(struct i8042
*global
)
500 for (i
= 0; i
< MAX_JUNK_ITERATIONS
; i
++) {
501 if (i8042_wait_obf(global
))
503 (void) ddi_get8(global
->io_handle
,
504 global
->io_addr
+ I8042_DATA
);
508 * If we hit the maximum number of iterations, then there
509 * was a serious problem (e.g. our hardware may not be
510 * present or working properly).
512 return (i
== MAX_JUNK_ITERATIONS
);
516 i8042_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
518 struct i8042_port
*port
;
519 enum i8042_ports which_port
;
521 #if !defined(USE_SOFT_INTRS)
522 ddi_iblock_cookie_t cookie
;
524 static ddi_device_acc_attr_t attr
= {
529 struct i8042
*global
;
533 global
= (struct i8042
*)ddi_get_driver_private(dip
);
534 i8042_discard_junk_data(global
);
535 i8042_write_command_byte(global
, I8042_CMD_ENABLE_ALL
);
536 return (DDI_SUCCESS
);
539 /* Handled in the main function block */
543 return (DDI_FAILURE
);
547 * DDI_ATTACH processing
550 global
= kmem_zalloc(sizeof (struct i8042
), KM_SLEEP
);
551 ddi_set_driver_private(dip
, (caddr_t
)global
);
553 global
->initialized
= B_FALSE
;
555 global
->init_state
|= I8042_INIT_BASIC
;
557 if (ddi_regs_map_setup(dip
, 0, (caddr_t
*)&global
->io_addr
,
558 0, 0, &attr
, &global
->io_handle
)
562 global
->init_state
|= I8042_INIT_REGS_MAPPED
;
565 * Get the number of interrupts for this nexus
567 if (ddi_dev_nintrs(dip
, &global
->nintrs
) == DDI_FAILURE
)
570 if (global
->nintrs
== 0) {
571 cmn_err(CE_WARN
, "i8042#%d: No interrupts defined!",
572 ddi_get_instance(global
->dip
));
576 if (global
->nintrs
> MAX_INTERRUPTS
)
577 global
->nintrs
= MAX_INTERRUPTS
;
579 if (global
->nintrs
> 0) {
580 global
->iblock_cookies
= kmem_zalloc(global
->nintrs
*
581 sizeof (ddi_iblock_cookie_t
), KM_NOSLEEP
);
583 for (i
= 0; i
< global
->nintrs
; i
++) {
584 if (ddi_get_iblock_cookie(dip
, i
,
585 &global
->iblock_cookies
[i
]) != DDI_SUCCESS
)
589 global
->iblock_cookies
= NULL
;
591 mutex_init(&global
->i8042_mutex
, NULL
, MUTEX_DRIVER
,
592 (global
->nintrs
> 0) ? global
->iblock_cookies
[0] : NULL
);
594 mutex_init(&global
->i8042_out_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
596 cv_init(&global
->glock_cv
, NULL
, CV_DRIVER
, NULL
);
598 for (which_port
= 0; which_port
< NUM_PORTS
; ++which_port
) {
599 port
= &global
->i8042_ports
[which_port
];
600 port
->initialized
= B_FALSE
;
601 port
->i8042_global
= global
;
602 port
->which
= which_port
;
603 #if defined(USE_SOFT_INTRS)
608 * Assume that the interrupt block cookie for port <n>
609 * is iblock_cookies[<n>] (a 1:1 mapping). If there are not
610 * enough interrupts to cover the number of ports, use
611 * the cookie from interrupt 0.
613 if (global
->nintrs
> 0) {
614 cookie
= global
->iblock_cookies
[
615 (which_port
< global
->nintrs
) ? which_port
: 0];
617 mutex_init(&port
->intr_mutex
, NULL
, MUTEX_DRIVER
,
621 mutex_init(&port
->intr_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
627 global
->init_state
|= I8042_INIT_MUTEXES
;
630 * Disable input and interrupts from both the main and aux ports.
632 * It is difficult if not impossible to read the command byte in
633 * a completely clean way. Reading the command byte may cause
634 * an interrupt, and there is no way to suppress interrupts without
635 * writing the command byte. On a PC we might rely on the fact
636 * that IRQ 1 is disabled and guaranteed not shared, but on
637 * other platforms the interrupt line might be shared and so
638 * causing an interrupt could be bad.
640 * Since we can't read the command byte and update it, we
641 * just set it to static values.
643 i8042_write_command_byte(global
, I8042_CMD_DISABLE_ALL
);
645 global
->init_state
&= ~I8042_INIT_INTRS_ENABLED
;
647 /* Discard any junk data that may have been left around */
648 if (i8042_purge_outbuf(global
) != 0)
653 * Assume the number of interrupts is less that the number of
654 * bits in the variable used to keep track of which interrupt
657 ASSERT(global
->nintrs
<= (sizeof (global
->intrs_added
) * NBBY
));
659 for (i
= 0; i
< global
->nintrs
; i
++) {
661 * The 8042 handles all interrupts, because all
662 * device access goes through the same I/O addresses.
664 if (ddi_add_intr(dip
, i
,
665 (ddi_iblock_cookie_t
*)NULL
,
666 (ddi_idevice_cookie_t
*)NULL
,
667 i8042_intr
, (caddr_t
)global
) != DDI_SUCCESS
)
670 global
->intrs_added
|= (1 << i
);
673 global
->initialized
= B_TRUE
;
676 * Enable the main and aux data ports and interrupts
678 i8042_write_command_byte(global
, I8042_CMD_ENABLE_ALL
);
679 global
->init_state
|= I8042_INIT_INTRS_ENABLED
;
682 return (DDI_SUCCESS
);
685 /* cleanup will succeed because no children have attached yet */
686 (void) i8042_cleanup(global
);
687 return (DDI_FAILURE
);
692 i8042_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
694 struct i8042
*global
= (struct i8042
*)ddi_get_driver_private(dip
);
696 ASSERT(global
!= NULL
);
701 * Do not disable the keyboard controller for x86 suspend, as
702 * the keyboard can be used to bring the system out of
705 return (DDI_SUCCESS
);
708 /* DETACH can only succeed if cleanup succeeds */
709 return (i8042_cleanup(global
));
712 return (DDI_FAILURE
);
717 * The primary interface to us from our children is via virtual registers.
718 * This is the entry point that allows our children to "map" these
730 struct i8042_port
*port
;
731 struct i8042
*global
;
732 enum i8042_ports which_port
;
734 unsigned int iprop_len
;
736 ddi_acc_hdl_t
*handle
;
739 global
= ddi_get_driver_private(dip
);
741 switch (mp
->map_type
) {
743 which_port
= *(int *)mp
->map_obj
.rp
;
747 rnumber
= mp
->map_obj
.rnumber
;
748 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, rdip
,
749 DDI_PROP_DONTPASS
, "reg", &iprop
, &iprop_len
) !=
752 cmn_err(CE_WARN
, "%s #%d: Missing 'reg' on %s@%s",
753 DRIVER_NAME(dip
), ddi_get_instance(dip
),
754 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
756 return (DDI_FAILURE
);
759 if (iprop_len
!= 1) {
760 cmn_err(CE_WARN
, "%s #%d: Malformed 'reg' on %s@%s",
761 DRIVER_NAME(dip
), ddi_get_instance(dip
),
762 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
763 return (DDI_FAILURE
);
765 if (rnumber
< 0 || rnumber
>= iprop_len
) {
766 cmn_err(CE_WARN
, "%s #%d: bad map request for %s@%s",
767 DRIVER_NAME(dip
), ddi_get_instance(dip
),
768 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
769 return (DDI_FAILURE
);
772 which_port
= iprop
[rnumber
];
773 ddi_prop_free((void *)iprop
);
775 if (which_port
!= MAIN_PORT
&& which_port
!= AUX_PORT
) {
777 "%s #%d: bad 'reg' value %d on %s@%s",
778 DRIVER_NAME(dip
), ddi_get_instance(dip
),
780 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
781 return (DDI_FAILURE
);
788 cmn_err(CE_WARN
, "%s #%d: unknown map type %d for %s@%s",
789 DRIVER_NAME(dip
), ddi_get_instance(dip
),
791 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
793 return (DDI_FAILURE
);
797 if (offset
!= 0 || len
!= 0) {
799 "%s #%d: partial mapping attempt for %s@%s ignored",
800 DRIVER_NAME(dip
), ddi_get_instance(dip
),
801 ddi_node_name(rdip
), ddi_get_name_addr(rdip
));
805 port
= &global
->i8042_ports
[which_port
];
807 switch (mp
->map_op
) {
808 case DDI_MO_MAP_LOCKED
:
809 #if defined(USE_SOFT_INTRS)
810 port
->soft_intr_enabled
= B_FALSE
;
812 port
->intr_func
= NULL
;
818 port
->has_glock
= B_FALSE
;
819 port
->initialized
= B_TRUE
;
821 handle
= mp
->map_handlep
;
822 handle
->ah_bus_private
= port
;
824 ap
= (ddi_acc_impl_t
*)handle
->ah_platform_private
;
826 * Support get8, put8 and _rep_put8
828 ap
->ahi_put8
= i8042_put8
;
829 ap
->ahi_get8
= i8042_get8
;
830 ap
->ahi_put16
= NULL
;
831 ap
->ahi_get16
= NULL
;
832 ap
->ahi_put32
= NULL
;
833 ap
->ahi_get32
= NULL
;
834 ap
->ahi_put64
= NULL
;
835 ap
->ahi_get64
= NULL
;
836 ap
->ahi_rep_put8
= NULL
;
837 ap
->ahi_rep_get8
= NULL
;
838 ap
->ahi_rep_put16
= NULL
;
839 ap
->ahi_rep_get16
= NULL
;
840 ap
->ahi_rep_put32
= NULL
;
841 ap
->ahi_rep_get32
= NULL
;
842 ap
->ahi_rep_put64
= NULL
;
843 ap
->ahi_rep_get64
= NULL
;
845 return (DDI_SUCCESS
);
848 port
->initialized
= B_FALSE
;
849 return (DDI_SUCCESS
);
852 cmn_err(CE_WARN
, "%s: map operation %d not supported",
853 DRIVER_NAME(dip
), mp
->map_op
);
854 return (DDI_FAILURE
);
860 * i8042 hardware interrupt routine. Called for both main and aux port
864 i8042_intr(caddr_t arg
)
866 struct i8042
*global
= (struct i8042
*)arg
;
867 enum i8042_ports which_port
;
871 struct i8042_port
*port
;
873 mutex_enter(&global
->i8042_mutex
);
875 stat
= ddi_get8(global
->io_handle
, global
->io_addr
+ I8042_STAT
);
877 if (! (stat
& I8042_STAT_OUTBF
)) {
878 ++i8042_unclaimed_interrupts
;
879 mutex_exit(&global
->i8042_mutex
);
880 return (DDI_INTR_UNCLAIMED
);
883 byte
= ddi_get8(global
->io_handle
, global
->io_addr
+ I8042_DATA
);
885 which_port
= (stat
& I8042_STAT_AUXBF
) ? AUX_PORT
: MAIN_PORT
;
887 port
= &global
->i8042_ports
[which_port
];
889 if (! port
->initialized
) {
890 mutex_exit(&global
->i8042_mutex
);
891 return (DDI_INTR_CLAIMED
);
894 new_wptr
= (port
->wptr
+ 1) % BUFSIZ
;
895 if (new_wptr
== port
->rptr
) {
898 if (port
->overruns
% 50 == 1) {
899 cmn_err(CE_WARN
, "i8042/%d: %d overruns\n",
900 which_port
, port
->overruns
);
904 mutex_exit(&global
->i8042_mutex
);
905 return (DDI_INTR_CLAIMED
);
908 port
->buf
[port
->wptr
] = byte
;
909 port
->wptr
= new_wptr
;
911 #if defined(USE_SOFT_INTRS)
912 if (port
->soft_intr_enabled
)
913 (void) ddi_intr_trigger_softint(port
->soft_hdl
,
917 mutex_exit(&global
->i8042_mutex
);
919 #if !defined(USE_SOFT_INTRS)
920 mutex_enter(&port
->intr_mutex
);
921 if (port
->intr_func
!= NULL
)
922 port
->intr_func(port
->intr_arg1
, NULL
);
923 mutex_exit(&port
->intr_mutex
);
926 return (DDI_INTR_CLAIMED
);
930 i8042_write_command_byte(struct i8042
*global
, unsigned char cb
)
932 mutex_enter(&global
->i8042_out_mutex
);
933 i8042_send(global
, I8042_CMD
, I8042_CMD_WCB
);
934 i8042_send(global
, I8042_DATA
, cb
);
935 mutex_exit(&global
->i8042_out_mutex
);
939 * Send a byte to either the i8042 command or data register, depending on
943 i8042_send(struct i8042
*global
, int reg
, unsigned char val
)
949 * First, wait for the i8042 to be ready to accept data.
951 /*CONSTANTCONDITION*/
953 stat
= ddi_get8(global
->io_handle
,
954 global
->io_addr
+ I8042_STAT
);
956 if ((stat
& I8042_STAT_INBF
) == 0) {
957 ddi_put8(global
->io_handle
, global
->io_addr
+reg
, val
);
961 /* Don't wait unless we're going to check again */
962 if (++tries
>= max_wait_iterations
)
965 drv_usecwait(USECS_PER_WAIT
);
969 if (tries
>= MAX_WAIT_ITERATIONS
)
970 cmn_err(CE_WARN
, "i8042_send: timeout!");
975 * Here's the interface to the virtual registers on the device.
977 * Normal interrupt-driven I/O:
979 * I8042_INT_INPUT_AVAIL (r/o)
980 * Interrupt mode input bytes available? Zero = No.
981 * I8042_INT_INPUT_DATA (r/o)
982 * Fetch interrupt mode input byte.
983 * I8042_INT_OUTPUT_DATA (w/o)
984 * Interrupt mode output byte.
986 * Polled I/O, used by (e.g.) kmdb, when normal system services are
989 * I8042_POLL_INPUT_AVAIL (r/o)
990 * Polled mode input bytes available? Zero = No.
991 * I8042_POLL_INPUT_DATA (r/o)
992 * Polled mode input byte.
993 * I8042_POLL_OUTPUT_DATA (w/o)
994 * Polled mode output byte.
996 * Note that in polled mode we cannot use cmn_err; only prom_printf is safe.
999 i8042_get8(ddi_acc_impl_t
*handlep
, uint8_t *addr
)
1001 struct i8042_port
*port
;
1002 struct i8042
*global
;
1007 h
= (ddi_acc_hdl_t
*)handlep
;
1009 port
= (struct i8042_port
*)h
->ah_bus_private
;
1010 global
= port
->i8042_global
;
1012 switch ((uintptr_t)addr
) {
1014 ASSERT(port
->has_glock
!= B_TRUE
); /* No reentrancy */
1015 mutex_enter(&global
->i8042_out_mutex
);
1017 * Block other children requesting exclusive access here until
1018 * the child possessing it relinquishes the lock.
1020 while (global
->glock
) {
1021 cv_wait(&global
->glock_cv
, &global
->i8042_out_mutex
);
1023 port
->has_glock
= B_TRUE
;
1025 mutex_exit(&global
->i8042_out_mutex
);
1030 mutex_enter(&global
->i8042_out_mutex
);
1031 ASSERT(global
->glock
!= 0);
1032 ASSERT(port
->has_glock
== B_TRUE
);
1033 port
->has_glock
= B_FALSE
;
1036 * Signal anyone waiting for exclusive access that it is now
1039 cv_signal(&global
->glock_cv
);
1040 mutex_exit(&global
->i8042_out_mutex
);
1044 case I8042_INT_INPUT_AVAIL
:
1045 mutex_enter(&global
->i8042_mutex
);
1046 ret
= port
->rptr
!= port
->wptr
;
1047 mutex_exit(&global
->i8042_mutex
);
1050 case I8042_INT_INPUT_DATA
:
1051 mutex_enter(&global
->i8042_mutex
);
1053 if (port
->rptr
!= port
->wptr
) {
1054 ret
= port
->buf
[port
->rptr
];
1055 port
->rptr
= (port
->rptr
+ 1) % BUFSIZ
;
1059 "i8042: Tried to read from empty buffer");
1065 mutex_exit(&global
->i8042_mutex
);
1070 case I8042_INT_OUTPUT_DATA
:
1071 case I8042_POLL_OUTPUT_DATA
:
1072 cmn_err(CE_WARN
, "i8042: read of write-only register 0x%p",
1078 case I8042_POLL_INPUT_AVAIL
:
1079 if (port
->rptr
!= port
->wptr
)
1082 stat
= ddi_get8(global
->io_handle
,
1083 global
->io_addr
+ I8042_STAT
);
1084 if ((stat
& I8042_STAT_OUTBF
) == 0)
1086 switch (port
->which
) {
1088 if ((stat
& I8042_STAT_AUXBF
) == 0)
1092 if ((stat
& I8042_STAT_AUXBF
) != 0)
1096 cmn_err(CE_WARN
, "data from unknown port: %d",
1100 * Data for wrong port pending; discard it.
1102 (void) ddi_get8(global
->io_handle
,
1103 global
->io_addr
+ I8042_DATA
);
1108 case I8042_POLL_INPUT_DATA
:
1109 if (port
->rptr
!= port
->wptr
) {
1110 ret
= port
->buf
[port
->rptr
];
1111 port
->rptr
= (port
->rptr
+ 1) % BUFSIZ
;
1115 stat
= ddi_get8(global
->io_handle
,
1116 global
->io_addr
+ I8042_STAT
);
1117 if ((stat
& I8042_STAT_OUTBF
) == 0) {
1119 prom_printf("I8042_POLL_INPUT_DATA: no data!\n");
1123 ret
= ddi_get8(global
->io_handle
,
1124 global
->io_addr
+ I8042_DATA
);
1125 switch (port
->which
) {
1127 if ((stat
& I8042_STAT_AUXBF
) == 0)
1131 if ((stat
& I8042_STAT_AUXBF
) != 0)
1136 prom_printf("I8042_POLL_INPUT_DATA: data for wrong port!\n");
1142 cmn_err(CE_WARN
, "i8042: read of undefined register 0x%p",
1152 i8042_put8(ddi_acc_impl_t
*handlep
, uint8_t *addr
, uint8_t value
)
1154 struct i8042
*global
;
1155 struct i8042_port
*port
;
1158 h
= (ddi_acc_hdl_t
*)handlep
;
1159 port
= (struct i8042_port
*)h
->ah_bus_private
;
1160 global
= port
->i8042_global
;
1162 switch ((uintptr_t)addr
) {
1163 case I8042_INT_OUTPUT_DATA
:
1164 case I8042_POLL_OUTPUT_DATA
:
1166 if ((uintptr_t)addr
== I8042_INT_OUTPUT_DATA
) {
1167 mutex_enter(&global
->i8042_out_mutex
);
1170 * If no child has exclusive access, then proceed with
1171 * the put8 below. If a child (not the one making the
1172 * call) has exclusive access, wait for it to be
1173 * relinquished. The use of i8042_out_mutex prevents
1174 * children seeking exclusive access from getting it
1175 * while a child is writing to the 8042.
1177 while (global
->glock
&& !port
->has_glock
) {
1178 cv_wait(&global
->glock_cv
,
1179 &global
->i8042_out_mutex
);
1183 if (port
->which
== AUX_PORT
)
1184 i8042_send(global
, I8042_CMD
, I8042_CMD_WRITE_AUX
);
1186 i8042_send(global
, I8042_DATA
, value
);
1188 if ((uintptr_t)addr
== I8042_INT_OUTPUT_DATA
)
1189 mutex_exit(&global
->i8042_out_mutex
);
1194 case I8042_INT_INPUT_AVAIL
:
1195 case I8042_INT_INPUT_DATA
:
1196 case I8042_POLL_INPUT_AVAIL
:
1197 case I8042_POLL_INPUT_DATA
:
1198 cmn_err(CE_WARN
, "i8042: write of read-only register 0x%p",
1203 cmn_err(CE_WARN
, "i8042: read of undefined register 0x%p",
1213 i8042_intr_ops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
1214 ddi_intr_handle_impl_t
*hdlp
, void *result
)
1216 struct i8042_port
*port
;
1217 #if defined(USE_SOFT_INTRS)
1218 struct i8042
*global
;
1223 case DDI_INTROP_SUPPORTED_TYPES
:
1224 *(int *)result
= DDI_INTR_TYPE_FIXED
;
1226 case DDI_INTROP_GETCAP
:
1227 if (i_ddi_intr_ops(dip
, rdip
, intr_op
, hdlp
, result
)
1231 case DDI_INTROP_NINTRS
:
1232 case DDI_INTROP_NAVAIL
:
1235 case DDI_INTROP_ALLOC
:
1236 *(int *)result
= hdlp
->ih_scratch1
;
1238 case DDI_INTROP_FREE
:
1240 case DDI_INTROP_GETPRI
:
1241 /* Hard coding it for x86 */
1244 case DDI_INTROP_ADDISR
:
1245 port
= ddi_get_parent_data(rdip
);
1247 #if defined(USE_SOFT_INTRS)
1248 global
= port
->i8042_global
;
1249 ret
= ddi_intr_add_softint(rdip
, &port
->soft_hdl
,
1250 I8042_SOFTINT_PRI
, hdlp
->ih_cb_func
, hdlp
->ih_cb_arg1
);
1252 if (ret
!= DDI_SUCCESS
) {
1254 cmn_err(CE_WARN
, "%s #%d: "
1255 "Cannot add soft interrupt for %s #%d, ret=%d.",
1256 DRIVER_NAME(dip
), ddi_get_instance(dip
),
1257 DRIVER_NAME(rdip
), ddi_get_instance(rdip
), ret
);
1258 #endif /* defined(DEBUG) */
1262 #else /* defined(USE_SOFT_INTRS) */
1263 mutex_enter(&port
->intr_mutex
);
1264 port
->intr_func
= hdlp
->ih_cb_func
;
1265 port
->intr_arg1
= hdlp
->ih_cb_arg1
;
1266 port
->intr_arg2
= hdlp
->ih_cb_arg2
;
1267 mutex_exit(&port
->intr_mutex
);
1268 #endif /* defined(USE_SOFT_INTRS) */
1270 case DDI_INTROP_REMISR
:
1271 port
= ddi_get_parent_data(rdip
);
1273 #if defined(USE_SOFT_INTRS)
1274 global
= port
->i8042_global
;
1275 mutex_enter(&global
->i8042_mutex
);
1277 mutex_exit(&global
->i8042_mutex
);
1278 #else /* defined(USE_SOFT_INTRS) */
1279 mutex_enter(&port
->intr_mutex
);
1280 port
->intr_func
= NULL
;
1281 mutex_exit(&port
->intr_mutex
);
1282 #endif /* defined(USE_SOFT_INTRS) */
1284 case DDI_INTROP_ENABLE
:
1285 port
= ddi_get_parent_data(rdip
);
1286 #if defined(USE_SOFT_INTRS)
1287 global
= port
->i8042_global
;
1288 mutex_enter(&global
->i8042_mutex
);
1289 port
->soft_intr_enabled
= B_TRUE
;
1290 if (port
->wptr
!= port
->rptr
)
1291 (void) ddi_intr_trigger_softint(port
->soft_hdl
,
1293 mutex_exit(&global
->i8042_mutex
);
1294 #else /* defined(USE_SOFT_INTRS) */
1295 mutex_enter(&port
->intr_mutex
);
1296 if (port
->wptr
!= port
->rptr
)
1297 port
->intr_func(port
->intr_arg1
, port
->intr_arg2
);
1298 mutex_exit(&port
->intr_mutex
);
1299 #endif /* defined(USE_SOFT_INTRS) */
1301 case DDI_INTROP_DISABLE
:
1302 #if defined(USE_SOFT_INTRS)
1303 port
= ddi_get_parent_data(rdip
);
1304 global
= port
->i8042_global
;
1305 mutex_enter(&global
->i8042_mutex
);
1306 port
->soft_intr_enabled
= B_FALSE
;
1307 (void) ddi_intr_remove_softint(port
->soft_hdl
);
1308 mutex_exit(&global
->i8042_mutex
);
1309 #endif /* defined(USE_SOFT_INTRS) */
1312 return (DDI_FAILURE
);
1315 return (DDI_SUCCESS
);
1319 i8042_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
1320 ddi_ctl_enum_t op
, void *arg
, void *result
)
1323 unsigned int iprop_len
;
1326 struct i8042
*global
;
1329 global
= ddi_get_driver_private(dip
);
1332 case DDI_CTLOPS_INITCHILD
:
1333 child
= (dev_info_t
*)arg
;
1334 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, child
,
1335 DDI_PROP_DONTPASS
, "reg", &iprop
, &iprop_len
) !=
1338 cmn_err(CE_WARN
, "%s #%d: Missing 'reg' on %s@???",
1339 DRIVER_NAME(dip
), ddi_get_instance(dip
),
1340 ddi_node_name(child
));
1342 return (DDI_FAILURE
);
1344 which_port
= iprop
[0];
1345 ddi_prop_free((void *)iprop
);
1347 (void) sprintf(name
, "%d", which_port
);
1348 ddi_set_name_addr(child
, name
);
1349 ddi_set_parent_data(child
,
1350 (caddr_t
)&global
->i8042_ports
[which_port
]);
1351 return (DDI_SUCCESS
);
1353 case DDI_CTLOPS_UNINITCHILD
:
1354 child
= (dev_info_t
*)arg
;
1355 ddi_set_name_addr(child
, NULL
);
1356 ddi_set_parent_data(child
, NULL
);
1357 return (DDI_SUCCESS
);
1359 case DDI_CTLOPS_REPORTDEV
:
1360 cmn_err(CE_CONT
, "?8042 device: %s@%s, %s # %d\n",
1361 ddi_node_name(rdip
), ddi_get_name_addr(rdip
),
1362 DRIVER_NAME(rdip
), ddi_get_instance(rdip
));
1363 return (DDI_SUCCESS
);
1366 return (ddi_ctlops(dip
, rdip
, op
, arg
, result
));
1371 #if defined(__i386) || defined(__amd64)
1373 i8042_devi_findchild_by_node_name(dev_info_t
*pdip
, char *nodename
)
1377 ASSERT(DEVI_BUSY_OWNED(pdip
));
1379 if (nodename
== NULL
) {
1380 return ((dev_info_t
*)NULL
);
1383 for (child
= ddi_get_child(pdip
); child
!= NULL
;
1384 child
= ddi_get_next_sibling(child
)) {
1386 if (strcmp(ddi_node_name(child
), nodename
) == 0)
1393 alloc_kb_mouse(dev_info_t
*i8042_dip
, int nodes_needed
)
1399 /* don't alloc unless acpi is off */
1400 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, ddi_root_node(),
1401 DDI_PROP_DONTPASS
, "acpi-enum", &acpi_prop
) == DDI_PROP_SUCCESS
) {
1402 if (strcmp("off", acpi_prop
) == 0) {
1405 ddi_prop_free(acpi_prop
);
1407 if (acpi_off
== 0) {
1411 if (nodes_needed
& I8042_MOUSE
) {
1413 ndi_devi_alloc_sleep(i8042_dip
, "mouse",
1414 (pnode_t
)DEVI_SID_NODEID
, &xdip
);
1415 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1417 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1419 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1420 "compatible", "pnpPNP,f03");
1422 * The device_type property does not matter on SPARC. Retain it
1423 * on x86 for compatibility with the previous pseudo-prom.
1425 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1426 "device_type", "mouse");
1427 (void) ndi_devi_bind_driver(xdip
, 0);
1430 if (nodes_needed
& I8042_KEYBOARD
) {
1432 ndi_devi_alloc_sleep(i8042_dip
, "keyboard",
1433 (pnode_t
)DEVI_SID_NODEID
, &xdip
);
1434 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1436 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, xdip
,
1438 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1439 "compatible", "pnpPNP,303");
1440 (void) ndi_prop_update_string(DDI_DEV_T_NONE
, xdip
,
1441 "device_type", "keyboard");
1442 (void) ndi_devi_bind_driver(xdip
, 0);
1448 i8042_bus_config(dev_info_t
*parent
, uint_t flags
,
1449 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
1451 #if defined(__i386) || defined(__amd64)
1452 int nodes_needed
= 0;
1456 * On x86 systems, if ACPI is disabled, the only way the
1457 * keyboard and mouse can be enumerated is by creating them
1458 * manually. The following code searches for the existence of
1459 * the keyboard and mouse nodes and creates them if they are not
1462 ndi_devi_enter(parent
, &circ
);
1463 if (i8042_devi_findchild_by_node_name(parent
, "keyboard") == NULL
)
1464 nodes_needed
|= I8042_KEYBOARD
;
1465 if (i8042_devi_findchild_by_node_name(parent
, "mouse") == NULL
)
1466 nodes_needed
|= I8042_MOUSE
;
1468 /* If the mouse and keyboard nodes do not already exist, create them */
1470 alloc_kb_mouse(parent
, nodes_needed
);
1471 ndi_devi_exit(parent
, circ
);
1473 return (ndi_busop_bus_config(parent
, flags
, op
, arg
, childp
, 0));
1477 i8042_bus_unconfig(dev_info_t
*parent
, uint_t flags
,
1478 ddi_bus_config_op_t op
, void *arg
)
1481 * The NDI_UNCONFIG flag allows the reference count on this nexus to be
1482 * decremented when children's drivers are unloaded, enabling the nexus
1483 * itself to be unloaded.
1485 return (ndi_busop_bus_unconfig(parent
, flags
| NDI_UNCONFIG
, op
, arg
));