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