1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright 2023 Oxide Computer Company
28 */
29
30 #include <sys/types.h>
31 #include <sys/ddi.h>
32 #include <sys/inline.h>
33 #include <sys/conf.h>
34 #include <sys/sunddi.h>
35 #include <sys/sunndi.h>
36 #include <sys/i8042.h>
37 #include <sys/kmem.h>
38 #include <sys/promif.h> /* for prom_printf */
39 #include <sys/note.h>
40
41 /*
42 * Note: For x86, this driver is used to create keyboard/mouse nodes when
43 * booting with ACPI enumeration turned off (acpi-enum=off).
44 */
45
46 /*
47 * Unfortunately, soft interrupts are implemented poorly. Each additional
48 * soft interrupt user impacts the performance of all existing soft interrupt
49 * users. This is not the case on SPARC, however.
50 */
51 #ifdef __sparc
52 #define USE_SOFT_INTRS
53 #else
54 #undef USE_SOFT_INTRS
55 #endif
56
57 /*
58 * The command bytes are different for x86 and for SPARC because on x86,
59 * all modern 8042s can properly translate scan code set 2 codes to
60 * scan code set 1. On SPARC systems that have 8042s (e.g. Tadpole laptops),
61 * setting the "translation" bit in the command byte has no effect.
62 * This is potentially dangerous if, in the future, new SPARC systems uses 8042s
63 * that implement the scan code translation when the translation bit is set.
64 *
65 * On SPARC, kb8042 will attempt to detect which scan code set the keyboard
66 * is using. In order for that code to work, the real scan code set must be the
67 * set that is returned by the keyboard (and not a different set that is
68 * translated by the 8042). (e.g. If the translation bit were enabled here,
69 * and the keyboard returned scan code set 2 when kb8042 queried it, kb8042
70 * would not be able to know with certainty that the scan codes it will receive
71 * are set 2 scancodes, or set 1 translations made by the 8042).
72 */
73
74 /*
75 * 8042 Command Byte Layout:
76 *
77 * 0x80: 0 = Reserved, must be zero.
78 * 0x40: 1 = Translate to XT codes. (0=No translation)
79 * 0x20: 1 = Disable aux (mouse) port. (0=Enable port)
80 * 0x10: 1 = Disable main (keyboard) port. (0=Enable port)
81 * 0x08: 0 = Reserved, must be zero.
82 * 0x04: 1 = System flag, 1 means passed self-test.
83 * Caution: setting this bit to zero causes some
84 * systems (HP Kayak XA) to fail to reboot without
85 * a hard reset.
86 * 0x02: 0 = Disable aux port interrupts. (1=Enable aux port interrupts)
87 * 0x01: 0 = Disable main port interrupts. (1=Enable main port interrupts)
88 *
89 */
90 #if defined(__sparc)
91 #define I8042_CMD_DISABLE_ALL 0x34
92 #define I8042_CMD_ENABLE_ALL 0x07
93 #elif defined(__x86)
94 #define I8042_CMD_DISABLE_ALL 0x74
95 #define I8042_CMD_ENABLE_ALL 0x47
96 #endif
97
98 #define BUFSIZ 64
99
100 /*
101 * Child nodes, used to determine which to create at bus_config time
102 */
103 #define I8042_KEYBOARD 2
104 #define I8042_MOUSE 1
105
106 enum i8042_ports {
107 MAIN_PORT = 0,
108 AUX_PORT
109 };
110
111 #define NUM_PORTS 2
112
113 /*
114 * Only register at most MAX_INTERRUPTS interrupt handlers,
115 * regardless of the number of interrupts in the prom node.
116 * This is important, as registering for all interrupts on
117 * some systems (e.g. Tadpole laptops) results in a flood
118 * of spurious interrupts (for Tadpole, the first 2 interrupts
119 * are for the keyboard and mouse, respectively, and the
120 * third is for a proprietary device that is also accessed
121 * via the same I/O addresses.)
122 */
123 #define MAX_INTERRUPTS 2
124
125 /*
126 * One of these for each port - main (keyboard) and aux (mouse).
127 */
128 struct i8042_port {
129 boolean_t initialized;
130 dev_info_t *dip;
131 int inumber;
132 enum i8042_ports which; /* main or aux port */
133 #if defined(USE_SOFT_INTRS)
134 ddi_softint_handle_t soft_hdl;
135 boolean_t soft_intr_enabled;
136 #else
137 kmutex_t intr_mutex;
138 #endif
139 uint_t (*intr_func)(caddr_t arg1, caddr_t arg2);
140 caddr_t intr_arg1;
141 caddr_t intr_arg2;
142 struct i8042 *i8042_global;
143 /*
144 * wptr is next byte to write
145 */
146 int wptr;
147 /*
148 * rptr is next byte to read, == wptr means empty
149 * NB: At full, one byte is unused.
150 */
151 int rptr;
152 int overruns;
153 unsigned char buf[BUFSIZ];
154 /*
155 * has_glock is 1 if this child has the [put8] exclusive-access lock.
156 */
157 volatile boolean_t has_glock;
158 };
159
160 /*
161 * Describes entire 8042 device.
162 */
163 struct i8042 {
164 dev_info_t *dip;
165 struct i8042_port i8042_ports[NUM_PORTS];
166 kmutex_t i8042_mutex;
167 kmutex_t i8042_out_mutex;
168 boolean_t initialized;
169 ddi_acc_handle_t io_handle;
170 uint8_t *io_addr;
171 int nintrs;
172 ddi_iblock_cookie_t *iblock_cookies;
173 uint_t init_state;
174 /* Initialization states: */
175 #define I8042_INIT_BASIC 0x00000001
176 #define I8042_INIT_REGS_MAPPED 0x00000002
177 #define I8042_INIT_MUTEXES 0x00000004
178 #define I8042_INIT_INTRS_ENABLED 0x00000010
179 uint_t intrs_added;
180 #ifdef __sparc
181 timeout_id_t timeout_id;
182 #endif
183 /*
184 * glock is 1 if any child has the [put8] exclusive-access lock
185 * glock_cv is associated with the condition `glock == 0'
186 */
187 volatile int glock;
188 /*
189 * Callers awaiting exclusive access in i8042_put8 sleep on glock_cv
190 * and are signaled when another child relinquishes exclusive access.
191 */
192 kcondvar_t glock_cv;
193 };
194
195 /*
196 * i8042 hardware register definitions
197 */
198
199 /*
200 * These are I/O registers, relative to the device's base (normally 0x60).
201 */
202 #define I8042_DATA 0x00 /* read/write data here */
203 #define I8042_STAT 0x04 /* read status here */
204 #define I8042_CMD 0x04 /* write commands here */
205
206 /*
207 * These are bits in I8042_STAT.
208 */
209 #define I8042_STAT_OUTBF 0x01 /* Output (to host) buffer full */
210 #define I8042_STAT_INBF 0x02 /* Input (from host) buffer full */
211 #define I8042_STAT_AUXBF 0x20 /* Output buffer data is from aux */
212
213 /*
214 * These are commands to the i8042 itself (as distinct from the devices
215 * attached to it).
216 */
217 #define I8042_CMD_RCB 0x20 /* Read command byte (we don't use) */
218 #define I8042_CMD_WCB 0x60 /* Write command byte */
219 #define I8042_CMD_WRITE_AUX 0xD4 /* Send next data byte to aux port */
220
221 /*
222 * Maximum number of times to loop while clearing pending data from the
223 * keyboard controller.
224 */
225 #define MAX_JUNK_ITERATIONS 1000
226
227 /*
228 * Maximum time to wait for the keyboard to become ready to accept data
229 * (maximum time = MAX_WAIT_ITERATIONS * USECS_PER_WAIT (default is 250ms))
230 */
231 #define MAX_WAIT_ITERATIONS 25000
232 #define USECS_PER_WAIT 10
233
234
235 #ifdef __sparc
236
237 #define PLATFORM_MATCH(s) (strncmp(ddi_get_name(ddi_root_node()), \
238 (s), strlen(s)) == 0)
239
240 /*
241 * On some older SPARC platforms that have problems with the
242 * interrupt line attached to the PS/2 keyboard/mouse, it
243 * may be necessary to change the operating mode of the nexus
244 * to a polling-based (instead of interrupt-based) method.
245 * this variable is present to enable a worst-case workaround so
246 * owners of these systems can still retain a working keyboard.
247 *
248 * The `i8042_polled_mode' variable can be used to force polled
249 * mode for platforms that have this issue, but for which
250 * automatic relief is not implemented.
251 *
252 * In the off chance that one of the platforms is misidentified
253 * as requiried polling mode, `i8042_force_interrupt_mode' can
254 * be set to force the nexus to use interrupts.
255 */
256 #define I8042_MIN_POLL_INTERVAL 1000 /* usecs */
257 int i8042_poll_interval = 8000; /* usecs */
258 int i8042_fast_poll_interval; /* usecs */
259 int i8042_slow_poll_interval; /* usecs */
260
261 boolean_t i8042_polled_mode = B_FALSE;
262 boolean_t i8042_force_interrupt_mode = B_FALSE;
263 #endif /* __sparc */
264
265 int max_wait_iterations = MAX_WAIT_ITERATIONS;
266
267 #ifdef DEBUG
268 int i8042_debug = 0;
269 #endif
270
271 /*
272 * function prototypes for bus ops routines:
273 */
274 static int i8042_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
275 off_t offset, off_t len, caddr_t *addrp);
276 static int i8042_ctlops(dev_info_t *dip, dev_info_t *rdip,
277 ddi_ctl_enum_t op, void *arg, void *result);
278
279 /*
280 * function prototypes for dev ops routines:
281 */
282 static int i8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
283 static int i8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
284 static int i8042_intr_ops(dev_info_t *dip, dev_info_t *rdip,
285 ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result);
286 static int i8042_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t,
287 void *, dev_info_t **);
288 static int i8042_bus_unconfig(dev_info_t *, uint_t,
289 ddi_bus_config_op_t, void *);
290 #ifdef __sparc
291 static int i8042_build_interrupts_property(dev_info_t *dip);
292 static boolean_t i8042_is_polling_platform(void);
293 #endif
294
295 /*
296 * bus ops and dev ops structures:
297 */
298 static struct bus_ops i8042_bus_ops = {
299 BUSO_REV,
300 i8042_map,
301 NULL,
302 NULL,
303 NULL,
304 NULL, /* ddi_map_fault */
305 NULL, /* ddi_dma_map */
306 NULL, /* ddi_dma_allochdl */
307 NULL, /* ddi_dma_freehdl */
308 NULL, /* ddi_dma_bindhdl */
309 NULL, /* ddi_dma_unbindhdl */
310 NULL, /* ddi_dma_flush */
311 NULL, /* ddi_dma_win */
312 NULL, /* ddi_dma_mctl */
313 i8042_ctlops,
314 ddi_bus_prop_op,
315 NULL, /* (*bus_get_eventcookie)(); */
316 NULL, /* (*bus_add_eventcall)(); */
317 NULL, /* (*bus_remove_eventcall)(); */
318 NULL, /* (*bus_post_event)(); */
319 NULL, /* bus_intr_ctl */
320 i8042_bus_config, /* bus_config */
321 i8042_bus_unconfig, /* bus_unconfig */
322 NULL, /* bus_fm_init */
323 NULL, /* bus_fm_fini */
324 NULL, /* bus_fm_access_enter */
325 NULL, /* bus_fm_access_exit */
326 NULL, /* bus_power */
327 i8042_intr_ops /* bus_intr_op */
328 };
329
330 static struct dev_ops i8042_ops = {
331 DEVO_REV,
332 0,
333 ddi_no_info,
334 nulldev,
335 0,
336 i8042_attach,
337 i8042_detach,
338 nodev,
339 (struct cb_ops *)0,
340 &i8042_bus_ops,
341 NULL,
342 ddi_quiesce_not_needed,
343 };
344
345
346 /*
347 * module definitions:
348 */
349 #include <sys/modctl.h>
350 extern struct mod_ops mod_driverops;
351
352 static struct modldrv modldrv = {
353 &mod_driverops, /* Type of module. This one is a driver */
354 "i8042 nexus driver", /* Name of module. */
355 &i8042_ops, /* driver ops */
356 };
357
358 static struct modlinkage modlinkage = {
359 MODREV_1, (void *)&modldrv, NULL
360 };
361
362 int
_init(void)363 _init(void)
364 {
365 int e;
366
367 /*
368 * Install the module.
369 */
370 e = mod_install(&modlinkage);
371 return (e);
372 }
373
374 int
_fini(void)375 _fini(void)
376 {
377 int e;
378
379 /*
380 * Remove the module.
381 */
382 e = mod_remove(&modlinkage);
383 if (e != 0)
384 return (e);
385
386 return (e);
387 }
388
389 int
_info(struct modinfo * modinfop)390 _info(struct modinfo *modinfop)
391 {
392 return (mod_info(&modlinkage, modinfop));
393 }
394
395 #define DRIVER_NAME(dip) ddi_driver_name(dip)
396
397 static void i8042_timeout(void *arg);
398 static unsigned int i8042_intr(caddr_t arg);
399 static void i8042_write_command_byte(struct i8042 *, unsigned char);
400 static uint8_t i8042_get8(ddi_acc_impl_t *handlep, uint8_t *addr);
401 static void i8042_put8(ddi_acc_impl_t *handlep, uint8_t *addr,
402 uint8_t value);
403 static void i8042_send(struct i8042 *global, int reg, unsigned char cmd);
404 static uint8_t i8042_get8(ddi_acc_impl_t *handlep, uint8_t *addr);
405
406 unsigned int i8042_unclaimed_interrupts = 0;
407
408 static void
i8042_discard_junk_data(struct i8042 * global)409 i8042_discard_junk_data(struct i8042 *global)
410 {
411 /* Discard any junk data that may have been left around */
412 for (;;) {
413 unsigned char stat;
414
415 stat = ddi_get8(global->io_handle,
416 global->io_addr + I8042_STAT);
417 if (! (stat & I8042_STAT_OUTBF))
418 break;
419 (void) ddi_get8(global->io_handle,
420 global->io_addr + I8042_DATA);
421
422 }
423 }
424
425 static int
i8042_cleanup(struct i8042 * global)426 i8042_cleanup(struct i8042 *global)
427 {
428 int which_port, i;
429 struct i8042_port *port;
430
431 ASSERT(global != NULL);
432
433 if (global->initialized == B_TRUE) {
434 /*
435 * If any children still have regs mapped or interrupts
436 * registered, return immediate failure (and do nothing).
437 */
438 mutex_enter(&global->i8042_mutex);
439
440 for (which_port = 0; which_port < NUM_PORTS; which_port++) {
441 port = &global->i8042_ports[which_port];
442
443 if (port->initialized == B_TRUE) {
444 mutex_exit(&global->i8042_mutex);
445 return (DDI_FAILURE);
446 }
447 #if defined(USE_SOFT_INTRS)
448 if (port->soft_hdl != 0) {
449 mutex_exit(&global->i8042_mutex);
450 return (DDI_FAILURE);
451 }
452 #else
453 mutex_enter(&port->intr_mutex);
454 if (port->intr_func != NULL) {
455 mutex_exit(&port->intr_mutex);
456 mutex_exit(&global->i8042_mutex);
457 return (DDI_FAILURE);
458 }
459 mutex_exit(&port->intr_mutex);
460 #endif
461 }
462 global->initialized = B_FALSE;
463
464 mutex_exit(&global->i8042_mutex);
465 }
466
467 #ifdef __sparc
468 /* If there may be an outstanding timeout, cancel it */
469 if (global->timeout_id != 0) {
470 (void) untimeout(global->timeout_id);
471 }
472 #endif
473
474 /* Stop the controller from generating interrupts */
475 if (global->init_state & I8042_INIT_INTRS_ENABLED)
476 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL);
477
478 if (global->intrs_added) {
479 /*
480 * Remove the interrupts in the reverse order in
481 * which they were added
482 */
483 for (i = global->nintrs - 1; i >= 0; i--) {
484 if (global->intrs_added & (1 << i))
485 ddi_remove_intr(global->dip, i,
486 global->iblock_cookies[i]);
487 }
488 }
489
490
491 if (global->init_state & I8042_INIT_MUTEXES) {
492 for (which_port = 0; which_port < NUM_PORTS; which_port++) {
493 #ifndef USE_SOFT_INTRS
494 port = &global->i8042_ports[which_port];
495 mutex_destroy(&port->intr_mutex);
496 #endif
497 }
498 cv_destroy(&global->glock_cv);
499 mutex_destroy(&global->i8042_out_mutex);
500 mutex_destroy(&global->i8042_mutex);
501 }
502
503 if (global->init_state & I8042_INIT_REGS_MAPPED)
504 ddi_regs_map_free(&global->io_handle);
505
506 if (global->init_state & I8042_INIT_BASIC) {
507 ddi_set_driver_private(global->dip, (caddr_t)NULL);
508 if (global->nintrs > 0) {
509 kmem_free(global->iblock_cookies, global->nintrs *
510 sizeof (ddi_iblock_cookie_t));
511 }
512 kmem_free(global, sizeof (struct i8042));
513 }
514
515 return (DDI_SUCCESS);
516 }
517
518 #define OBF_WAIT_COUNT 1000 /* in granules of 10uS */
519
520 /*
521 * Wait for the 8042 to fill the 'output' (from 8042 to host)
522 * buffer. If 8042 fails to fill the output buffer within an
523 * allowed time, return 1 (which means there is no data available),
524 * otherwise return 0
525 */
526 static int
i8042_wait_obf(struct i8042 * global)527 i8042_wait_obf(struct i8042 *global)
528 {
529 int timer = 0;
530
531 while (!(ddi_get8(global->io_handle, global->io_addr + I8042_STAT) &
532 I8042_STAT_OUTBF)) {
533 if (++timer > OBF_WAIT_COUNT)
534 return (1);
535 drv_usecwait(10);
536 }
537 return (0);
538 }
539
540
541 /*
542 * Drain all queued bytes from the 8042.
543 * Return 0 for no error, <> 0 if there was an error.
544 */
545 static int
i8042_purge_outbuf(struct i8042 * global)546 i8042_purge_outbuf(struct i8042 *global)
547 {
548 int i;
549
550 for (i = 0; i < MAX_JUNK_ITERATIONS; i++) {
551 if (i8042_wait_obf(global))
552 break;
553 (void) ddi_get8(global->io_handle,
554 global->io_addr + I8042_DATA);
555 }
556
557 /*
558 * If we hit the maximum number of iterations, then there
559 * was a serious problem (e.g. our hardware may not be
560 * present or working properly).
561 */
562 return (i == MAX_JUNK_ITERATIONS);
563 }
564
565 static int
i8042_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)566 i8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
567 {
568 struct i8042_port *port;
569 enum i8042_ports which_port;
570 int i;
571 #if !defined(USE_SOFT_INTRS)
572 ddi_iblock_cookie_t cookie;
573 #endif
574 static ddi_device_acc_attr_t attr = {
575 DDI_DEVICE_ATTR_V0,
576 DDI_NEVERSWAP_ACC,
577 DDI_STRICTORDER_ACC,
578 };
579 struct i8042 *global;
580 #ifdef __sparc
581 int interval;
582 #endif
583
584 switch (cmd) {
585 case DDI_RESUME:
586 global = (struct i8042 *)ddi_get_driver_private(dip);
587 i8042_discard_junk_data(global);
588 i8042_write_command_byte(global, I8042_CMD_ENABLE_ALL);
589 return (DDI_SUCCESS);
590
591 case DDI_ATTACH:
592 /* Handled in the main function block */
593 break;
594
595 default:
596 return (DDI_FAILURE);
597 }
598
599 /*
600 * DDI_ATTACH processing
601 */
602
603 global = (struct i8042 *)kmem_zalloc(sizeof (struct i8042), KM_SLEEP);
604 ddi_set_driver_private(dip, (caddr_t)global);
605 global->dip = dip;
606 global->initialized = B_FALSE;
607
608 global->init_state |= I8042_INIT_BASIC;
609
610 if (ddi_regs_map_setup(dip, 0, (caddr_t *)&global->io_addr,
611 (offset_t)0, (offset_t)0, &attr, &global->io_handle)
612 != DDI_SUCCESS)
613 goto fail;
614
615 global->init_state |= I8042_INIT_REGS_MAPPED;
616
617 /*
618 * Get the number of interrupts for this nexus
619 */
620 if (ddi_dev_nintrs(dip, &global->nintrs) == DDI_FAILURE)
621 goto fail;
622
623 #ifdef __sparc
624 if ((i8042_polled_mode || i8042_is_polling_platform()) &&
625 !i8042_force_interrupt_mode) {
626 /*
627 * If we're on a platform that has known
628 * interrupt issues with the keyboard/mouse,
629 * use polled mode.
630 */
631 i8042_polled_mode = B_TRUE;
632 global->nintrs = 0;
633 } else if (global->nintrs == 0) {
634 /*
635 * If there are no interrupts on the i8042 node,
636 * we may be on a brain-dead platform that only
637 * has interrupts properties on i8042's children
638 * (e.g. some UltraII-based boards)
639 * In this case, scan first-level children, and
640 * build a list of interrupts that each child uses,
641 * then create an `interrupts' property on the nexus node
642 * that contains the interrupts used by all children
643 */
644 if (i8042_build_interrupts_property(dip) == DDI_FAILURE ||
645 ddi_dev_nintrs(dip, &global->nintrs) == DDI_FAILURE ||
646 global->nintrs == 0) {
647 cmn_err(CE_WARN, "i8042#%d: No interrupts defined!",
648 ddi_get_instance(global->dip));
649 goto fail;
650 }
651 }
652 #else
653 if (global->nintrs == 0) {
654 cmn_err(CE_WARN, "i8042#%d: No interrupts defined!",
655 ddi_get_instance(global->dip));
656 goto fail;
657 }
658 #endif
659
660 if (global->nintrs > MAX_INTERRUPTS)
661 global->nintrs = MAX_INTERRUPTS;
662
663 if (global->nintrs > 0) {
664 global->iblock_cookies = kmem_zalloc(global->nintrs *
665 sizeof (ddi_iblock_cookie_t), KM_NOSLEEP);
666
667 for (i = 0; i < global->nintrs; i++) {
668 if (ddi_get_iblock_cookie(dip, i,
669 &global->iblock_cookies[i]) != DDI_SUCCESS)
670 goto fail;
671 }
672 } else
673 global->iblock_cookies = NULL;
674
675 mutex_init(&global->i8042_mutex, NULL, MUTEX_DRIVER,
676 (global->nintrs > 0) ? global->iblock_cookies[0] : NULL);
677
678 mutex_init(&global->i8042_out_mutex, NULL, MUTEX_DRIVER, NULL);
679
680 cv_init(&global->glock_cv, NULL, CV_DRIVER, NULL);
681
682 for (which_port = 0; which_port < NUM_PORTS; ++which_port) {
683 port = &global->i8042_ports[which_port];
684 port->initialized = B_FALSE;
685 port->i8042_global = global;
686 port->which = which_port;
687 #if defined(USE_SOFT_INTRS)
688 port->soft_hdl = 0;
689 #else
690
691 /*
692 * Assume that the interrupt block cookie for port <n>
693 * is iblock_cookies[<n>] (a 1:1 mapping). If there are not
694 * enough interrupts to cover the number of ports, use
695 * the cookie from interrupt 0.
696 */
697 if (global->nintrs > 0) {
698 cookie = global->iblock_cookies[
699 (which_port < global->nintrs) ? which_port : 0];
700
701 mutex_init(&port->intr_mutex, NULL, MUTEX_DRIVER,
702 cookie);
703
704 } else {
705 mutex_init(&port->intr_mutex, NULL, MUTEX_DRIVER, NULL);
706 }
707
708 #endif
709 }
710
711 global->init_state |= I8042_INIT_MUTEXES;
712
713 /*
714 * Disable input and interrupts from both the main and aux ports.
715 *
716 * It is difficult if not impossible to read the command byte in
717 * a completely clean way. Reading the command byte may cause
718 * an interrupt, and there is no way to suppress interrupts without
719 * writing the command byte. On a PC we might rely on the fact
720 * that IRQ 1 is disabled and guaranteed not shared, but on
721 * other platforms the interrupt line might be shared and so
722 * causing an interrupt could be bad.
723 *
724 * Since we can't read the command byte and update it, we
725 * just set it to static values.
726 */
727 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL);
728
729 global->init_state &= ~I8042_INIT_INTRS_ENABLED;
730
731 /* Discard any junk data that may have been left around */
732 if (i8042_purge_outbuf(global) != 0)
733 goto fail;
734
735
736 /*
737 * Assume the number of interrupts is less that the number of
738 * bits in the variable used to keep track of which interrupt
739 * was added.
740 */
741 ASSERT(global->nintrs <= (sizeof (global->intrs_added) * NBBY));
742
743 for (i = 0; i < global->nintrs; i++) {
744 /*
745 * The 8042 handles all interrupts, because all
746 * device access goes through the same I/O addresses.
747 */
748 if (ddi_add_intr(dip, i,
749 (ddi_iblock_cookie_t *)NULL,
750 (ddi_idevice_cookie_t *)NULL,
751 i8042_intr, (caddr_t)global) != DDI_SUCCESS)
752 goto fail;
753
754 global->intrs_added |= (1 << i);
755 }
756
757 global->initialized = B_TRUE;
758
759 /*
760 * Enable the main and aux data ports and interrupts
761 */
762 i8042_write_command_byte(global, I8042_CMD_ENABLE_ALL);
763 global->init_state |= I8042_INIT_INTRS_ENABLED;
764
765 #ifdef __sparc
766 if (i8042_polled_mode) {
767 /*
768 * Do not allow anyone to set the polling interval
769 * to an interval more frequent than I8042_MIN_POLL_INTERVAL --
770 * it could hose the system.
771 */
772 interval = i8042_poll_interval;
773 if (interval < I8042_MIN_POLL_INTERVAL)
774 interval = I8042_MIN_POLL_INTERVAL;
775 i8042_fast_poll_interval = interval;
776 i8042_slow_poll_interval = interval << 3;
777
778 global->timeout_id = timeout(i8042_timeout, global,
779 drv_usectohz(i8042_slow_poll_interval));
780 }
781 #endif
782
783 return (DDI_SUCCESS);
784
785 fail:
786 /* cleanup will succeed because no children have attached yet */
787 (void) i8042_cleanup(global);
788 return (DDI_FAILURE);
789 }
790
791 /*ARGSUSED*/
792 static int
i8042_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)793 i8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
794 {
795 struct i8042 *global = (struct i8042 *)ddi_get_driver_private(dip);
796
797 ASSERT(global != NULL);
798
799 switch (cmd) {
800 case DDI_SUSPEND:
801 /*
802 * Do not disable the keyboard controller for x86 suspend, as
803 * the keyboard can be used to bring the system out of
804 * suspend.
805 */
806 #ifdef __sparc
807 /* Disable interrupts and controller devices before suspend */
808 i8042_write_command_byte(global, I8042_CMD_DISABLE_ALL);
809 #endif
810 return (DDI_SUCCESS);
811
812 case DDI_DETACH:
813 /* DETACH can only succeed if cleanup succeeds */
814 return (i8042_cleanup(global));
815
816 default:
817 return (DDI_FAILURE);
818 }
819 }
820
821 /*
822 * The primary interface to us from our children is via virtual registers.
823 * This is the entry point that allows our children to "map" these
824 * virtual registers.
825 */
826 static int
i8042_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * addrp)827 i8042_map(
828 dev_info_t *dip,
829 dev_info_t *rdip,
830 ddi_map_req_t *mp,
831 off_t offset,
832 off_t len,
833 caddr_t *addrp)
834 {
835 struct i8042_port *port;
836 struct i8042 *global;
837 enum i8042_ports which_port;
838 int *iprop;
839 unsigned int iprop_len;
840 int rnumber;
841 ddi_acc_hdl_t *handle;
842 ddi_acc_impl_t *ap;
843
844 global = ddi_get_driver_private(dip);
845
846 switch (mp->map_type) {
847 case DDI_MT_REGSPEC:
848 which_port = *(int *)mp->map_obj.rp;
849 break;
850
851 case DDI_MT_RNUMBER:
852 rnumber = mp->map_obj.rnumber;
853 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
854 DDI_PROP_DONTPASS, "reg", &iprop, &iprop_len) !=
855 DDI_SUCCESS) {
856 #if defined(DEBUG)
857 cmn_err(CE_WARN, "%s #%d: Missing 'reg' on %s@%s",
858 DRIVER_NAME(dip), ddi_get_instance(dip),
859 ddi_node_name(rdip), ddi_get_name_addr(rdip));
860 #endif
861 return (DDI_FAILURE);
862 }
863 #if defined(DEBUG)
864 if (iprop_len != 1) {
865 cmn_err(CE_WARN, "%s #%d: Malformed 'reg' on %s@%s",
866 DRIVER_NAME(dip), ddi_get_instance(dip),
867 ddi_node_name(rdip), ddi_get_name_addr(rdip));
868 return (DDI_FAILURE);
869 }
870 if (rnumber < 0 || rnumber >= iprop_len) {
871 cmn_err(CE_WARN, "%s #%d: bad map request for %s@%s",
872 DRIVER_NAME(dip), ddi_get_instance(dip),
873 ddi_node_name(rdip), ddi_get_name_addr(rdip));
874 return (DDI_FAILURE);
875 }
876 #endif
877 which_port = iprop[rnumber];
878 ddi_prop_free((void *)iprop);
879 #if defined(DEBUG)
880 if (which_port != MAIN_PORT && which_port != AUX_PORT) {
881 cmn_err(CE_WARN,
882 "%s #%d: bad 'reg' value %d on %s@%s",
883 DRIVER_NAME(dip), ddi_get_instance(dip),
884 which_port,
885 ddi_node_name(rdip), ddi_get_name_addr(rdip));
886 return (DDI_FAILURE);
887 }
888 #endif
889 break;
890
891 default:
892 #if defined(DEBUG)
893 cmn_err(CE_WARN, "%s #%d: unknown map type %d for %s@%s",
894 DRIVER_NAME(dip), ddi_get_instance(dip),
895 mp->map_type,
896 ddi_node_name(rdip), ddi_get_name_addr(rdip));
897 #endif
898 return (DDI_FAILURE);
899 }
900
901 #if defined(DEBUG)
902 if (offset != 0 || len != 0) {
903 cmn_err(CE_WARN,
904 "%s #%d: partial mapping attempt for %s@%s ignored",
905 DRIVER_NAME(dip), ddi_get_instance(dip),
906 ddi_node_name(rdip), ddi_get_name_addr(rdip));
907 }
908 #endif
909
910 port = &global->i8042_ports[which_port];
911
912 switch (mp->map_op) {
913 case DDI_MO_MAP_LOCKED:
914 #if defined(USE_SOFT_INTRS)
915 port->soft_intr_enabled = B_FALSE;
916 #else
917 port->intr_func = NULL;
918 #endif
919 port->wptr = 0;
920 port->rptr = 0;
921 port->dip = dip;
922 port->inumber = 0;
923 port->has_glock = B_FALSE;
924 port->initialized = B_TRUE;
925
926 handle = mp->map_handlep;
927 handle->ah_bus_private = port;
928 handle->ah_addr = 0;
929 ap = (ddi_acc_impl_t *)handle->ah_platform_private;
930 /*
931 * Support get8, put8 and _rep_put8
932 */
933 ap->ahi_put8 = i8042_put8;
934 ap->ahi_get8 = i8042_get8;
935 ap->ahi_put16 = NULL;
936 ap->ahi_get16 = NULL;
937 ap->ahi_put32 = NULL;
938 ap->ahi_get32 = NULL;
939 ap->ahi_put64 = NULL;
940 ap->ahi_get64 = NULL;
941 ap->ahi_rep_put8 = NULL;
942 ap->ahi_rep_get8 = NULL;
943 ap->ahi_rep_put16 = NULL;
944 ap->ahi_rep_get16 = NULL;
945 ap->ahi_rep_put32 = NULL;
946 ap->ahi_rep_get32 = NULL;
947 ap->ahi_rep_put64 = NULL;
948 ap->ahi_rep_get64 = NULL;
949 *addrp = 0;
950 return (DDI_SUCCESS);
951
952 case DDI_MO_UNMAP:
953 port->initialized = B_FALSE;
954 return (DDI_SUCCESS);
955
956 default:
957 cmn_err(CE_WARN, "%s: map operation %d not supported",
958 DRIVER_NAME(dip), mp->map_op);
959 return (DDI_FAILURE);
960 }
961 }
962
963 #ifdef __sparc
964 static void
i8042_timeout(void * arg)965 i8042_timeout(void *arg)
966 {
967 struct i8042 *i8042_p = (struct i8042 *)arg;
968 int interval;
969
970 /*
971 * Allow the polling speed to be changed on the fly --
972 * catch it here and update the intervals used.
973 */
974 if (i8042_fast_poll_interval != i8042_poll_interval) {
975 interval = i8042_poll_interval;
976 if (interval < I8042_MIN_POLL_INTERVAL)
977 interval = I8042_MIN_POLL_INTERVAL;
978 i8042_fast_poll_interval = interval;
979 i8042_slow_poll_interval = interval << 3;
980 }
981
982 /*
983 * If the ISR returned true, start polling at a faster rate to
984 * increate responsiveness. Once the keyboard or mouse go idle,
985 * the ISR will return UNCLAIMED, and we'll go back to the slower
986 * polling rate. This gives some positive hysteresis (but not
987 * negative, since we go back to the slower polling interval after
988 * only one UNCLAIMED). This has shown to be responsive enough,
989 * even for fast typers.
990 */
991 interval = (i8042_intr((caddr_t)i8042_p) == DDI_INTR_CLAIMED) ?
992 i8042_fast_poll_interval : i8042_slow_poll_interval;
993
994 if (i8042_polled_mode)
995 i8042_p->timeout_id = timeout(i8042_timeout, arg,
996 drv_usectohz(interval));
997 else
998 i8042_p->timeout_id = 0;
999 }
1000 #endif
1001
1002 /*
1003 * i8042 hardware interrupt routine. Called for both main and aux port
1004 * interrupts.
1005 */
1006 static unsigned int
i8042_intr(caddr_t arg)1007 i8042_intr(caddr_t arg)
1008 {
1009 struct i8042 *global = (struct i8042 *)arg;
1010 enum i8042_ports which_port;
1011 unsigned char stat;
1012 unsigned char byte;
1013 int new_wptr;
1014 struct i8042_port *port;
1015
1016 mutex_enter(&global->i8042_mutex);
1017
1018 stat = ddi_get8(global->io_handle, global->io_addr + I8042_STAT);
1019
1020 if (! (stat & I8042_STAT_OUTBF)) {
1021 ++i8042_unclaimed_interrupts;
1022 mutex_exit(&global->i8042_mutex);
1023 return (DDI_INTR_UNCLAIMED);
1024 }
1025
1026 byte = ddi_get8(global->io_handle, global->io_addr + I8042_DATA);
1027
1028 which_port = (stat & I8042_STAT_AUXBF) ? AUX_PORT : MAIN_PORT;
1029
1030 port = &global->i8042_ports[which_port];
1031
1032 if (! port->initialized) {
1033 mutex_exit(&global->i8042_mutex);
1034 return (DDI_INTR_CLAIMED);
1035 }
1036
1037 new_wptr = (port->wptr + 1) % BUFSIZ;
1038 if (new_wptr == port->rptr) {
1039 port->overruns++;
1040 #if defined(DEBUG)
1041 if (port->overruns % 50 == 1) {
1042 cmn_err(CE_WARN, "i8042/%d: %d overruns\n",
1043 which_port, port->overruns);
1044 }
1045 #endif
1046
1047 mutex_exit(&global->i8042_mutex);
1048 return (DDI_INTR_CLAIMED);
1049 }
1050
1051 port->buf[port->wptr] = byte;
1052 port->wptr = new_wptr;
1053
1054 #if defined(USE_SOFT_INTRS)
1055 if (port->soft_intr_enabled)
1056 (void) ddi_intr_trigger_softint(port->soft_hdl,
1057 port->intr_arg2);
1058 #endif
1059
1060 mutex_exit(&global->i8042_mutex);
1061
1062 #if !defined(USE_SOFT_INTRS)
1063 mutex_enter(&port->intr_mutex);
1064 if (port->intr_func != NULL)
1065 port->intr_func(port->intr_arg1, NULL);
1066 mutex_exit(&port->intr_mutex);
1067 #endif
1068
1069 return (DDI_INTR_CLAIMED);
1070 }
1071
1072 static void
i8042_write_command_byte(struct i8042 * global,unsigned char cb)1073 i8042_write_command_byte(struct i8042 *global, unsigned char cb)
1074 {
1075 mutex_enter(&global->i8042_out_mutex);
1076 i8042_send(global, I8042_CMD, I8042_CMD_WCB);
1077 i8042_send(global, I8042_DATA, cb);
1078 mutex_exit(&global->i8042_out_mutex);
1079 }
1080
1081 /*
1082 * Send a byte to either the i8042 command or data register, depending on
1083 * the argument.
1084 */
1085 static void
i8042_send(struct i8042 * global,int reg,unsigned char val)1086 i8042_send(struct i8042 *global, int reg, unsigned char val)
1087 {
1088 uint8_t stat;
1089 int tries = 0;
1090
1091 /*
1092 * First, wait for the i8042 to be ready to accept data.
1093 */
1094 /*CONSTANTCONDITION*/
1095 while (1) {
1096 stat = ddi_get8(global->io_handle,
1097 global->io_addr + I8042_STAT);
1098
1099 if ((stat & I8042_STAT_INBF) == 0) {
1100 ddi_put8(global->io_handle, global->io_addr+reg, val);
1101 break;
1102 }
1103
1104 /* Don't wait unless we're going to check again */
1105 if (++tries >= max_wait_iterations)
1106 break;
1107 else
1108 drv_usecwait(USECS_PER_WAIT);
1109 }
1110
1111 #ifdef DEBUG
1112 if (tries >= MAX_WAIT_ITERATIONS)
1113 cmn_err(CE_WARN, "i8042_send: timeout!");
1114 #endif
1115 }
1116
1117 /*
1118 * Here's the interface to the virtual registers on the device.
1119 *
1120 * Normal interrupt-driven I/O:
1121 *
1122 * I8042_INT_INPUT_AVAIL (r/o)
1123 * Interrupt mode input bytes available? Zero = No.
1124 * I8042_INT_INPUT_DATA (r/o)
1125 * Fetch interrupt mode input byte.
1126 * I8042_INT_OUTPUT_DATA (w/o)
1127 * Interrupt mode output byte.
1128 *
1129 * Polled I/O, used by (e.g.) kmdb, when normal system services are
1130 * unavailable:
1131 *
1132 * I8042_POLL_INPUT_AVAIL (r/o)
1133 * Polled mode input bytes available? Zero = No.
1134 * I8042_POLL_INPUT_DATA (r/o)
1135 * Polled mode input byte.
1136 * I8042_POLL_OUTPUT_DATA (w/o)
1137 * Polled mode output byte.
1138 *
1139 * Note that in polled mode we cannot use cmn_err; only prom_printf is safe.
1140 */
1141 static uint8_t
i8042_get8(ddi_acc_impl_t * handlep,uint8_t * addr)1142 i8042_get8(ddi_acc_impl_t *handlep, uint8_t *addr)
1143 {
1144 struct i8042_port *port;
1145 struct i8042 *global;
1146 uint8_t ret;
1147 ddi_acc_hdl_t *h;
1148 uint8_t stat;
1149
1150 h = (ddi_acc_hdl_t *)handlep;
1151
1152 port = (struct i8042_port *)h->ah_bus_private;
1153 global = port->i8042_global;
1154
1155 switch ((uintptr_t)addr) {
1156 case I8042_LOCK:
1157 ASSERT(port->has_glock != B_TRUE); /* No reentrancy */
1158 mutex_enter(&global->i8042_out_mutex);
1159 /*
1160 * Block other children requesting exclusive access here until
1161 * the child possessing it relinquishes the lock.
1162 */
1163 while (global->glock) {
1164 cv_wait(&global->glock_cv, &global->i8042_out_mutex);
1165 }
1166 port->has_glock = B_TRUE;
1167 global->glock = 1;
1168 mutex_exit(&global->i8042_out_mutex);
1169 ret = 0;
1170 break;
1171
1172 case I8042_UNLOCK:
1173 mutex_enter(&global->i8042_out_mutex);
1174 ASSERT(global->glock != 0);
1175 ASSERT(port->has_glock == B_TRUE);
1176 port->has_glock = B_FALSE;
1177 global->glock = 0;
1178 /*
1179 * Signal anyone waiting for exclusive access that it is now
1180 * available.
1181 */
1182 cv_signal(&global->glock_cv);
1183 mutex_exit(&global->i8042_out_mutex);
1184 ret = 0;
1185 break;
1186
1187 case I8042_INT_INPUT_AVAIL:
1188 mutex_enter(&global->i8042_mutex);
1189 ret = port->rptr != port->wptr;
1190 mutex_exit(&global->i8042_mutex);
1191 return (ret);
1192
1193 case I8042_INT_INPUT_DATA:
1194 mutex_enter(&global->i8042_mutex);
1195
1196 if (port->rptr != port->wptr) {
1197 ret = port->buf[port->rptr];
1198 port->rptr = (port->rptr + 1) % BUFSIZ;
1199 } else {
1200 #if defined(DEBUG)
1201 cmn_err(CE_WARN,
1202 "i8042: Tried to read from empty buffer");
1203 #endif
1204 ret = 0;
1205 }
1206
1207
1208 mutex_exit(&global->i8042_mutex);
1209
1210 break;
1211
1212 #if defined(DEBUG)
1213 case I8042_INT_OUTPUT_DATA:
1214 case I8042_POLL_OUTPUT_DATA:
1215 cmn_err(CE_WARN, "i8042: read of write-only register 0x%p",
1216 (void *)addr);
1217 ret = 0;
1218 break;
1219 #endif
1220
1221 case I8042_POLL_INPUT_AVAIL:
1222 if (port->rptr != port->wptr)
1223 return (B_TRUE);
1224 for (;;) {
1225 stat = ddi_get8(global->io_handle,
1226 global->io_addr + I8042_STAT);
1227 if ((stat & I8042_STAT_OUTBF) == 0)
1228 return (B_FALSE);
1229 switch (port->which) {
1230 case MAIN_PORT:
1231 if ((stat & I8042_STAT_AUXBF) == 0)
1232 return (B_TRUE);
1233 break;
1234 case AUX_PORT:
1235 if ((stat & I8042_STAT_AUXBF) != 0)
1236 return (B_TRUE);
1237 break;
1238 default:
1239 cmn_err(CE_WARN, "data from unknown port: %d",
1240 port->which);
1241 }
1242 /*
1243 * Data for wrong port pending; discard it.
1244 */
1245 (void) ddi_get8(global->io_handle,
1246 global->io_addr + I8042_DATA);
1247 }
1248
1249 /* NOTREACHED */
1250
1251 case I8042_POLL_INPUT_DATA:
1252 if (port->rptr != port->wptr) {
1253 ret = port->buf[port->rptr];
1254 port->rptr = (port->rptr + 1) % BUFSIZ;
1255 return (ret);
1256 }
1257
1258 stat = ddi_get8(global->io_handle,
1259 global->io_addr + I8042_STAT);
1260 if ((stat & I8042_STAT_OUTBF) == 0) {
1261 #if defined(DEBUG)
1262 prom_printf("I8042_POLL_INPUT_DATA: no data!\n");
1263 #endif
1264 return (0);
1265 }
1266 ret = ddi_get8(global->io_handle,
1267 global->io_addr + I8042_DATA);
1268 switch (port->which) {
1269 case MAIN_PORT:
1270 if ((stat & I8042_STAT_AUXBF) == 0)
1271 return (ret);
1272 break;
1273 case AUX_PORT:
1274 if ((stat & I8042_STAT_AUXBF) != 0)
1275 return (ret);
1276 break;
1277 }
1278 #if defined(DEBUG)
1279 prom_printf("I8042_POLL_INPUT_DATA: data for wrong port!\n");
1280 #endif
1281 return (0);
1282
1283 default:
1284 #if defined(DEBUG)
1285 cmn_err(CE_WARN, "i8042: read of undefined register 0x%p",
1286 (void *)addr);
1287 #endif
1288 ret = 0;
1289 break;
1290 }
1291 return (ret);
1292 }
1293
1294 static void
i8042_put8(ddi_acc_impl_t * handlep,uint8_t * addr,uint8_t value)1295 i8042_put8(ddi_acc_impl_t *handlep, uint8_t *addr, uint8_t value)
1296 {
1297 struct i8042 *global;
1298 struct i8042_port *port;
1299 ddi_acc_hdl_t *h;
1300
1301 h = (ddi_acc_hdl_t *)handlep;
1302 port = (struct i8042_port *)h->ah_bus_private;
1303 global = port->i8042_global;
1304
1305 switch ((uintptr_t)addr) {
1306 case I8042_INT_OUTPUT_DATA:
1307 case I8042_POLL_OUTPUT_DATA:
1308
1309 if ((uintptr_t)addr == I8042_INT_OUTPUT_DATA) {
1310 mutex_enter(&global->i8042_out_mutex);
1311
1312 /*
1313 * If no child has exclusive access, then proceed with
1314 * the put8 below. If a child (not the one making the
1315 * call) has exclusive access, wait for it to be
1316 * relinquished. The use of i8042_out_mutex prevents
1317 * children seeking exclusive access from getting it
1318 * while a child is writing to the 8042.
1319 */
1320 while (global->glock && !port->has_glock) {
1321 cv_wait(&global->glock_cv,
1322 &global->i8042_out_mutex);
1323 }
1324 }
1325
1326 if (port->which == AUX_PORT)
1327 i8042_send(global, I8042_CMD, I8042_CMD_WRITE_AUX);
1328
1329 i8042_send(global, I8042_DATA, value);
1330
1331 if ((uintptr_t)addr == I8042_INT_OUTPUT_DATA)
1332 mutex_exit(&global->i8042_out_mutex);
1333
1334 break;
1335
1336 #if defined(DEBUG)
1337 case I8042_INT_INPUT_AVAIL:
1338 case I8042_INT_INPUT_DATA:
1339 case I8042_POLL_INPUT_AVAIL:
1340 case I8042_POLL_INPUT_DATA:
1341 cmn_err(CE_WARN, "i8042: write of read-only register 0x%p",
1342 (void *)addr);
1343 break;
1344
1345 default:
1346 cmn_err(CE_WARN, "i8042: read of undefined register 0x%p",
1347 (void *)addr);
1348 break;
1349 #endif
1350 }
1351 }
1352
1353
1354 /* ARGSUSED */
1355 static int
i8042_intr_ops(dev_info_t * dip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)1356 i8042_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
1357 ddi_intr_handle_impl_t *hdlp, void *result)
1358 {
1359 struct i8042_port *port;
1360 #if defined(USE_SOFT_INTRS)
1361 struct i8042 *global;
1362 int ret;
1363 #endif
1364
1365 switch (intr_op) {
1366 case DDI_INTROP_SUPPORTED_TYPES:
1367 *(int *)result = DDI_INTR_TYPE_FIXED;
1368 break;
1369 case DDI_INTROP_GETCAP:
1370 if (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result)
1371 == DDI_FAILURE)
1372 *(int *)result = 0;
1373 break;
1374 case DDI_INTROP_NINTRS:
1375 case DDI_INTROP_NAVAIL:
1376 *(int *)result = 1;
1377 break;
1378 case DDI_INTROP_ALLOC:
1379 *(int *)result = hdlp->ih_scratch1;
1380 break;
1381 case DDI_INTROP_FREE:
1382 break;
1383 case DDI_INTROP_GETPRI:
1384 /* Hard coding it for x86 */
1385 *(int *)result = 5;
1386 break;
1387 case DDI_INTROP_ADDISR:
1388 port = ddi_get_parent_data(rdip);
1389
1390 #if defined(USE_SOFT_INTRS)
1391 global = port->i8042_global;
1392 ret = ddi_intr_add_softint(rdip, &port->soft_hdl,
1393 I8042_SOFTINT_PRI, hdlp->ih_cb_func, hdlp->ih_cb_arg1);
1394
1395 if (ret != DDI_SUCCESS) {
1396 #if defined(DEBUG)
1397 cmn_err(CE_WARN, "%s #%d: "
1398 "Cannot add soft interrupt for %s #%d, ret=%d.",
1399 DRIVER_NAME(dip), ddi_get_instance(dip),
1400 DRIVER_NAME(rdip), ddi_get_instance(rdip), ret);
1401 #endif /* defined(DEBUG) */
1402 return (ret);
1403 }
1404
1405 #else /* defined(USE_SOFT_INTRS) */
1406 mutex_enter(&port->intr_mutex);
1407 port->intr_func = hdlp->ih_cb_func;
1408 port->intr_arg1 = hdlp->ih_cb_arg1;
1409 port->intr_arg2 = hdlp->ih_cb_arg2;
1410 mutex_exit(&port->intr_mutex);
1411 #endif /* defined(USE_SOFT_INTRS) */
1412 break;
1413 case DDI_INTROP_REMISR:
1414 port = ddi_get_parent_data(rdip);
1415
1416 #if defined(USE_SOFT_INTRS)
1417 global = port->i8042_global;
1418 mutex_enter(&global->i8042_mutex);
1419 port->soft_hdl = 0;
1420 mutex_exit(&global->i8042_mutex);
1421 #else /* defined(USE_SOFT_INTRS) */
1422 mutex_enter(&port->intr_mutex);
1423 port->intr_func = NULL;
1424 mutex_exit(&port->intr_mutex);
1425 #endif /* defined(USE_SOFT_INTRS) */
1426 break;
1427 case DDI_INTROP_ENABLE:
1428 port = ddi_get_parent_data(rdip);
1429 #if defined(USE_SOFT_INTRS)
1430 global = port->i8042_global;
1431 mutex_enter(&global->i8042_mutex);
1432 port->soft_intr_enabled = B_TRUE;
1433 if (port->wptr != port->rptr)
1434 (void) ddi_intr_trigger_softint(port->soft_hdl,
1435 port->intr_arg2);
1436 mutex_exit(&global->i8042_mutex);
1437 #else /* defined(USE_SOFT_INTRS) */
1438 mutex_enter(&port->intr_mutex);
1439 if (port->wptr != port->rptr)
1440 port->intr_func(port->intr_arg1, port->intr_arg2);
1441 mutex_exit(&port->intr_mutex);
1442 #endif /* defined(USE_SOFT_INTRS) */
1443 break;
1444 case DDI_INTROP_DISABLE:
1445 #if defined(USE_SOFT_INTRS)
1446 port = ddi_get_parent_data(rdip);
1447 global = port->i8042_global;
1448 mutex_enter(&global->i8042_mutex);
1449 port->soft_intr_enabled = B_FALSE;
1450 (void) ddi_intr_remove_softint(port->soft_hdl);
1451 mutex_exit(&global->i8042_mutex);
1452 #endif /* defined(USE_SOFT_INTRS) */
1453 break;
1454 default:
1455 return (DDI_FAILURE);
1456 }
1457
1458 return (DDI_SUCCESS);
1459 }
1460
1461 static int
i8042_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t op,void * arg,void * result)1462 i8042_ctlops(dev_info_t *dip, dev_info_t *rdip,
1463 ddi_ctl_enum_t op, void *arg, void *result)
1464 {
1465 int *iprop;
1466 unsigned int iprop_len;
1467 int which_port;
1468 char name[16];
1469 struct i8042 *global;
1470 dev_info_t *child;
1471
1472 global = ddi_get_driver_private(dip);
1473
1474 switch (op) {
1475 case DDI_CTLOPS_INITCHILD:
1476 child = (dev_info_t *)arg;
1477 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
1478 DDI_PROP_DONTPASS, "reg", &iprop, &iprop_len) !=
1479 DDI_SUCCESS) {
1480 #if defined(DEBUG)
1481 cmn_err(CE_WARN, "%s #%d: Missing 'reg' on %s@???",
1482 DRIVER_NAME(dip), ddi_get_instance(dip),
1483 ddi_node_name(child));
1484 #endif
1485 return (DDI_FAILURE);
1486 }
1487 which_port = iprop[0];
1488 ddi_prop_free((void *)iprop);
1489
1490 (void) sprintf(name, "%d", which_port);
1491 ddi_set_name_addr(child, name);
1492 ddi_set_parent_data(child,
1493 (caddr_t)&global->i8042_ports[which_port]);
1494 return (DDI_SUCCESS);
1495
1496 case DDI_CTLOPS_UNINITCHILD:
1497 child = (dev_info_t *)arg;
1498 ddi_set_name_addr(child, NULL);
1499 ddi_set_parent_data(child, NULL);
1500 return (DDI_SUCCESS);
1501
1502 case DDI_CTLOPS_REPORTDEV:
1503 cmn_err(CE_CONT, "?8042 device: %s@%s, %s # %d\n",
1504 ddi_node_name(rdip), ddi_get_name_addr(rdip),
1505 DRIVER_NAME(rdip), ddi_get_instance(rdip));
1506 return (DDI_SUCCESS);
1507
1508 default:
1509 return (ddi_ctlops(dip, rdip, op, arg, result));
1510 }
1511 /* NOTREACHED */
1512 }
1513
1514 #if defined(__x86)
1515 static dev_info_t *
i8042_devi_findchild_by_node_name(dev_info_t * pdip,char * nodename)1516 i8042_devi_findchild_by_node_name(dev_info_t *pdip, char *nodename)
1517 {
1518 dev_info_t *child;
1519
1520 ASSERT(DEVI_BUSY_OWNED(pdip));
1521
1522 if (nodename == NULL) {
1523 return ((dev_info_t *)NULL);
1524 }
1525
1526 for (child = ddi_get_child(pdip); child != NULL;
1527 child = ddi_get_next_sibling(child)) {
1528
1529 if (strcmp(ddi_node_name(child), nodename) == 0)
1530 break;
1531 }
1532 return (child);
1533 }
1534
1535 static void
alloc_kb_mouse(dev_info_t * i8042_dip,int nodes_needed)1536 alloc_kb_mouse(dev_info_t *i8042_dip, int nodes_needed)
1537 {
1538 dev_info_t *xdip;
1539 int acpi_off = 0;
1540 char *acpi_prop;
1541
1542 /*
1543 * If ACPI enumeration is not disabled and has taken place, return
1544 * early and do nothing.
1545 */
1546 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
1547 DDI_PROP_DONTPASS, "acpi-enum", &acpi_prop) == DDI_PROP_SUCCESS) {
1548 if (strcmp("off", acpi_prop) == 0) {
1549 acpi_off = 1;
1550 }
1551 ddi_prop_free(acpi_prop);
1552 }
1553 if (acpi_off == 0) {
1554 return;
1555 }
1556
1557 if (nodes_needed & I8042_MOUSE) {
1558 /* mouse */
1559 ndi_devi_alloc_sleep(i8042_dip, "mouse",
1560 (pnode_t)DEVI_SID_NODEID, &xdip);
1561 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1562 "reg", 1);
1563 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1564 "interrupts", 2);
1565 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1566 "compatible", "pnpPNP,f03");
1567 /*
1568 * The device_type property does not matter on SPARC. Retain it
1569 * on x86 for compatibility with the previous pseudo-prom.
1570 */
1571 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1572 "device_type", "mouse");
1573 (void) ndi_devi_bind_driver(xdip, 0);
1574 }
1575
1576 if (nodes_needed & I8042_KEYBOARD) {
1577 /* keyboard */
1578 ndi_devi_alloc_sleep(i8042_dip, "keyboard",
1579 (pnode_t)DEVI_SID_NODEID, &xdip);
1580 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1581 "reg", 0);
1582 (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip,
1583 "interrupts", 1);
1584 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1585 "compatible", "pnpPNP,303");
1586 (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip,
1587 "device_type", "keyboard");
1588 (void) ndi_devi_bind_driver(xdip, 0);
1589 }
1590 }
1591 #endif
1592
1593 static int
i8042_bus_config(dev_info_t * parent,uint_t flags,ddi_bus_config_op_t op,void * arg,dev_info_t ** childp)1594 i8042_bus_config(dev_info_t *parent, uint_t flags,
1595 ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
1596 {
1597 #if defined(__x86)
1598 int nodes_needed = 0;
1599
1600 /*
1601 * On x86 systems, if ACPI is disabled, the only way the
1602 * keyboard and mouse can be enumerated is by creating them
1603 * manually. The following code searches for the existence of
1604 * the keyboard and mouse nodes and creates them if they are not
1605 * found.
1606 */
1607 ndi_devi_enter(parent);
1608 if (i8042_devi_findchild_by_node_name(parent, "keyboard") == NULL)
1609 nodes_needed |= I8042_KEYBOARD;
1610 if (i8042_devi_findchild_by_node_name(parent, "mouse") == NULL)
1611 nodes_needed |= I8042_MOUSE;
1612
1613 /* If the mouse and keyboard nodes do not already exist, create them */
1614 if (nodes_needed)
1615 alloc_kb_mouse(parent, nodes_needed);
1616 ndi_devi_exit(parent);
1617 #endif
1618 return (ndi_busop_bus_config(parent, flags, op, arg, childp, 0));
1619 }
1620
1621 static int
i8042_bus_unconfig(dev_info_t * parent,uint_t flags,ddi_bus_config_op_t op,void * arg)1622 i8042_bus_unconfig(dev_info_t *parent, uint_t flags,
1623 ddi_bus_config_op_t op, void *arg)
1624 {
1625 /*
1626 * The NDI_UNCONFIG flag allows the reference count on this nexus to be
1627 * decremented when children's drivers are unloaded, enabling the nexus
1628 * itself to be unloaded.
1629 */
1630 return (ndi_busop_bus_unconfig(parent, flags | NDI_UNCONFIG, op, arg));
1631 }
1632
1633 #ifdef __sparc
1634 static int
i8042_build_interrupts_property(dev_info_t * dip)1635 i8042_build_interrupts_property(dev_info_t *dip)
1636 {
1637 dev_info_t *child = ddi_get_child(dip);
1638 uint_t nintr;
1639 int *intrs = NULL;
1640 int interrupts[MAX_INTERRUPTS];
1641 int i = 0;
1642
1643 /* Walk the children of this node, scanning for interrupts properties */
1644 while (child != NULL && i < MAX_INTERRUPTS) {
1645
1646 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child,
1647 DDI_PROP_DONTPASS, "interrupts", &intrs, &nintr)
1648 == DDI_PROP_SUCCESS && intrs != NULL) {
1649
1650 while (nintr > 0 && i < MAX_INTERRUPTS) {
1651 interrupts[i++] = intrs[--nintr];
1652 }
1653 ddi_prop_free(intrs);
1654 }
1655
1656 child = ddi_get_next_sibling(child);
1657 }
1658
1659 if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, "interrupts",
1660 interrupts, i) != DDI_PROP_SUCCESS) {
1661
1662 return (DDI_FAILURE);
1663 }
1664
1665 /*
1666 * Oh, the humanity. On the platforms on which we need to
1667 * synthesize an interrupts property, we ALSO need to update the
1668 * device_type property, and set it to "serial" in order for the
1669 * correct interrupt PIL to be chosen by the framework.
1670 */
1671 if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, "device_type", "serial")
1672 != DDI_PROP_SUCCESS) {
1673
1674 return (DDI_FAILURE);
1675 }
1676
1677 return (DDI_SUCCESS);
1678 }
1679
1680 static boolean_t
i8042_is_polling_platform(void)1681 i8042_is_polling_platform(void)
1682 {
1683 /*
1684 * Returns true if this platform is one of the platforms
1685 * that has interrupt issues with the PS/2 keyboard/mouse.
1686 */
1687 if (PLATFORM_MATCH("SUNW,UltraAX-"))
1688 return (B_TRUE);
1689 else
1690 return (B_FALSE);
1691 }
1692 #endif
1693