Print this page
4823 don't open-code NSEC2MSEC and MSEC2NSEC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sun4u/io/todds1287.c
+++ new/usr/src/uts/sun4u/io/todds1287.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 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /*
28 28 * The "todds1287" module has implementation for both tod
29 29 * and power button (pbio) interfaces. This driver controls
30 30 * RTC & APC units of National Semiconductor's 87317 SuperI/O
31 31 * chip. The tod interface accesses the RTC unit and pbio
32 32 * interface accesses the APC unit of SuperI/O. Since both
33 33 * units are implemented in the same Logical Device, registers
34 34 * for both units are accessible through a common set of index
35 35 * address & data registers. That is why both interfaces are
36 36 * implemented in a same driver.
37 37 *
38 38 * The APC unit is used to implement the power button. When the
39 39 * button momentarily is pressed, an interrupt is generated and
40 40 * at the same time a Fail-safe timer starts to run. If the
41 41 * timer is not stopped in 21 seconds, the power to system is
42 42 * turned off. So the first task in the interrupt handler is to
43 43 * reset the Fail-safe timer. Note that OBP is not clearing
44 44 * the Fail-safe timer due to limitation in handling interrupts,
45 45 * so when OBP is running, the power button should be pressed
46 46 * and held for 4 seconds for the power to go off, otherwise
47 47 * a momentarily press will delay the power-off for 21 seconds.
48 48 *
49 49 * PSARC/1999/393 describes the pbio(7I) interface.
50 50 */
51 51
52 52 #include <sys/types.h>
53 53 #include <sys/conf.h>
54 54 #include <sys/kmem.h>
55 55 #include <sys/open.h>
56 56 #include <sys/ddi.h>
57 57 #include <sys/sunddi.h>
58 58
59 59 #include <sys/todds1287.h>
60 60 #include <sys/modctl.h>
61 61 #include <sys/stat.h>
62 62 #include <sys/clock.h>
63 63 #include <sys/reboot.h>
64 64 #include <sys/machsystm.h>
65 65 #include <sys/poll.h>
66 66 #include <sys/pbio.h>
67 67
68 68 #define ABORT_INCREMENT_DELAY 10
69 69
70 70 static timestruc_t todds_get(void);
71 71 static void todds_set(timestruc_t);
72 72 static uint_t todds_set_watchdog_timer(uint_t);
73 73 static uint_t todds_clear_watchdog_timer(void);
74 74 static void todds_set_power_alarm(timestruc_t);
75 75 static void todds_clear_power_alarm(void);
76 76 static uint64_t todds_get_cpufrequency(void);
77 77
78 78 extern uint64_t find_cpufrequency(volatile uint8_t *);
79 79
80 80 /*
81 81 * External variables
82 82 */
83 83 extern int watchdog_activated;
84 84 extern uint_t watchdog_timeout_seconds;
85 85 extern volatile uint8_t *v_pmc_addr_reg;
86 86
87 87 /*
88 88 * Global variables
89 89 */
90 90 int ds1287_debug_flags;
91 91 int ds1287_caddr_warn;
92 92
93 93 /*
94 94 * cb ops
95 95 */
96 96 static int ds1287_open(dev_t *, int, int, cred_t *);
97 97 static int ds1287_close(dev_t, int, int, cred_t *);
98 98 static int ds1287_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
99 99 static int ds1287_chpoll(dev_t, short, int, short *, struct pollhead **);
100 100
101 101 static void read_rtc(struct rtc_t *);
102 102 static void write_rtc_time(struct rtc_t *);
103 103 static void write_rtc_alarm(struct rtc_t *);
104 104 static void select_bank(int bank);
105 105 static uint_t ds1287_intr(caddr_t);
106 106 static uint_t ds1287_softintr(caddr_t);
107 107 static void ds1287_timeout(caddr_t);
108 108 static uint_t ds1287_issue_shutdown(caddr_t);
109 109 static void ds1287_log_message(void);
110 110
111 111 static struct cb_ops ds1287_cbops = {
112 112 ds1287_open, /* open */
113 113 ds1287_close, /* close */
114 114 nodev, /* strategy */
115 115 nodev, /* print */
116 116 nodev, /* dump */
117 117 nodev, /* read */
118 118 nodev, /* write */
119 119 ds1287_ioctl, /* ioctl */
120 120 nodev, /* devmap */
121 121 nodev, /* mmap */
122 122 nodev, /* segmap */
123 123 ds1287_chpoll, /* poll */
124 124 ddi_prop_op, /* cb_prop_op */
125 125 NULL, /* streamtab */
126 126 D_NEW | D_MP, /* Driver compatibility flag */
127 127 CB_REV, /* rev */
128 128 nodev, /* int (*cb_aread)() */
129 129 nodev /* int (*cb_awrite)() */
130 130 };
131 131
132 132 /*
133 133 * dev ops
134 134 */
135 135 static int ds1287_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
136 136 static int ds1287_attach(dev_info_t *, ddi_attach_cmd_t);
137 137 static int ds1287_detach(dev_info_t *, ddi_detach_cmd_t);
138 138
139 139 static struct dev_ops ds1287_ops = {
140 140 DEVO_REV, /* devo_rev */
141 141 0, /* refcnt */
142 142 ds1287_getinfo, /* getinfo */
143 143 nulldev, /* identify */
144 144 nulldev, /* probe */
145 145 ds1287_attach, /* attach */
146 146 ds1287_detach, /* detach */
147 147 nodev, /* reset */
148 148 &ds1287_cbops, /* cb_ops */
149 149 (struct bus_ops *)NULL, /* bus_ops */
150 150 NULL, /* power */
↓ open down ↓ |
150 lines elided |
↑ open up ↑ |
151 151 ddi_quiesce_not_supported, /* devo_quiesce */
152 152 };
153 153
154 154
155 155 static void *ds1287_state;
156 156 static int instance = -1;
157 157
158 158 /* Driver Tunables */
159 159 static int ds1287_interrupt_priority = 15;
160 160 static int ds1287_softint_priority = 2;
161 -static hrtime_t power_button_debounce = NANOSEC/MILLISEC*10;
161 +static hrtime_t power_button_debounce = MSEC2NSEC(10);
162 162 static hrtime_t power_button_abort_interval = 1.5 * NANOSEC;
163 163 static int power_button_abort_presses = 3;
164 164 static int power_button_abort_enable = 1;
165 165 static int power_button_enable = 1;
166 166
167 167 static int power_button_pressed = 0;
168 168 static int power_button_cancel = 0;
169 169 static int power_button_timeouts = 0;
170 170 static int timeout_cancel = 0;
171 171 static int additional_presses = 0;
172 172
173 173 static ddi_iblock_cookie_t ds1287_lo_iblock;
174 174 static ddi_iblock_cookie_t ds1287_hi_iblock;
175 175 static ddi_softintr_t ds1287_softintr_id;
176 176 static kmutex_t ds1287_reg_mutex; /* Protects ds1287 Registers */
177 177
178 178 static struct modldrv modldrv = {
179 179 &mod_driverops, /* Type of module. This one is a driver */
180 180 "ds1287 clock driver", /* Name of the module. */
181 181 &ds1287_ops, /* driver ops */
182 182 };
183 183
184 184 static struct modlinkage modlinkage = {
185 185 MODREV_1, &modldrv, NULL
186 186 };
187 187
188 188
189 189 int
190 190 _init(void)
191 191 {
192 192 int status;
193 193
194 194 status = ddi_soft_state_init(&ds1287_state, sizeof (struct ds1287), 0);
195 195 if (status != 0) {
196 196 return (status);
197 197 }
198 198
199 199 if ((status = mod_install(&modlinkage)) != 0) {
200 200 ddi_soft_state_fini(&ds1287_state);
201 201 return (status);
202 202 }
203 203
204 204
205 205 ds1287_hi_iblock = (ddi_iblock_cookie_t)(uintptr_t)
206 206 ipltospl(ds1287_interrupt_priority);
207 207 mutex_init(&ds1287_reg_mutex, NULL, MUTEX_DRIVER, ds1287_hi_iblock);
208 208
209 209 mutex_enter(&ds1287_reg_mutex);
210 210 /* Select Bank 1 */
211 211 select_bank(1);
212 212 DS1287_ADDR_REG = RTC_B;
213 213 DS1287_DATA_REG = (RTC_DM | RTC_HM);
214 214 mutex_exit(&ds1287_reg_mutex);
215 215
216 216 tod_ops.tod_get = todds_get;
217 217 tod_ops.tod_set = todds_set;
218 218
219 219 /*
220 220 * If v_pmc_addr_reg isn't set, it's because it wasn't set in
221 221 * sun4u/os/fillsysinfo.c:have_pmc(). This means the real (pmc)
222 222 * watchdog routines (sun4u/io/pmc.c) will not be used. If the
223 223 * user were to set watchdog_enable in /etc/system, we'll need to
224 224 * use our own NOP routines.
225 225 */
226 226 if (v_pmc_addr_reg == NULL) {
227 227 tod_ops.tod_set_watchdog_timer = todds_set_watchdog_timer;
228 228 tod_ops.tod_clear_watchdog_timer = todds_clear_watchdog_timer;
229 229 }
230 230 tod_ops.tod_set_power_alarm = todds_set_power_alarm;
231 231 tod_ops.tod_clear_power_alarm = todds_clear_power_alarm;
232 232 tod_ops.tod_get_cpufrequency = todds_get_cpufrequency;
233 233
234 234 return (status);
235 235 }
236 236
237 237 int
238 238 _fini(void)
239 239 {
240 240 if (strcmp(tod_module_name, "todds1287") == 0)
241 241 return (EBUSY);
242 242
243 243 return (mod_remove(&modlinkage));
244 244 }
245 245
246 246 /*
247 247 * The loadable-module _info(9E) entry point
248 248 */
249 249 int
250 250 _info(struct modinfo *modinfop)
251 251 {
252 252 return (mod_info(&modlinkage, modinfop));
253 253 }
254 254
255 255 /*ARGSUSED*/
256 256 static int
257 257 ds1287_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
258 258 void **result)
259 259 {
260 260 struct ds1287 *softsp;
261 261
262 262 if (instance == -1)
263 263 return (DDI_FAILURE);
264 264
265 265 switch (infocmd) {
266 266 case DDI_INFO_DEVT2DEVINFO:
267 267 if ((softsp = ddi_get_soft_state(ds1287_state, instance))
268 268 == NULL)
269 269 return (DDI_FAILURE);
270 270 *result = (void *)softsp->dip;
271 271 return (DDI_SUCCESS);
272 272
273 273 case DDI_INFO_DEVT2INSTANCE:
274 274 *result = (void *)(uintptr_t)instance;
275 275 return (DDI_SUCCESS);
276 276
277 277 default:
278 278 return (DDI_FAILURE);
279 279 }
280 280 }
281 281
282 282 static int
283 283 ds1287_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
284 284 {
285 285 struct ds1287 *softsp;
286 286
287 287 DPRINTF("ds1287_attach\n");
288 288 switch (cmd) {
289 289 case DDI_ATTACH:
290 290 break;
291 291 case DDI_RESUME:
292 292 return (DDI_SUCCESS);
293 293 default:
294 294 return (DDI_FAILURE);
295 295 }
296 296
297 297 if (instance != -1) {
298 298 cmn_err(CE_WARN, "ds1287_attach: Another instance is already "
299 299 "attached.");
300 300 return (DDI_FAILURE);
301 301 }
302 302
303 303 instance = ddi_get_instance(dip);
304 304
305 305 if (v_rtc_addr_reg == NULL) {
306 306 cmn_err(CE_WARN, "ds1287_attach: v_rtc_addr_reg is NULL");
307 307 return (DDI_FAILURE);
308 308 }
309 309
310 310 /*
311 311 * Allocate softc information.
312 312 */
313 313 if (ddi_soft_state_zalloc(ds1287_state, instance) != DDI_SUCCESS) {
314 314 cmn_err(CE_WARN, "ds1287_attach: Failed to allocate "
315 315 "soft states.");
316 316 return (DDI_FAILURE);
317 317 }
318 318
319 319 softsp = ddi_get_soft_state(ds1287_state, instance);
320 320 DPRINTF("ds1287_attach: instance=%d softsp=0x%p\n", instance,
321 321 (void *)softsp);
322 322
323 323 softsp->dip = dip;
324 324
325 325 if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
326 326 "interrupt-priorities", (caddr_t)&ds1287_interrupt_priority,
327 327 sizeof (int)) != DDI_PROP_SUCCESS) {
328 328 cmn_err(CE_WARN, "ds1287_attach: Failed to create \""
329 329 "interrupt-priorities\" property.");
330 330 goto error;
331 331 }
332 332
333 333 /* add the softint */
334 334 ds1287_lo_iblock = (ddi_iblock_cookie_t)(uintptr_t)
335 335 ipltospl(ds1287_softint_priority);
336 336
337 337 if (ddi_add_softintr(dip, DDI_SOFTINT_FIXED, &ds1287_softintr_id,
338 338 &ds1287_lo_iblock, NULL, ds1287_softintr, (caddr_t)softsp) !=
339 339 DDI_SUCCESS) {
340 340 cmn_err(CE_WARN, "ds1287_attach: Failed to add low interrupt.");
341 341 goto error1;
342 342 }
343 343
344 344 /* add the hi interrupt */
345 345 if (ddi_add_intr(dip, 0, NULL, (ddi_idevice_cookie_t *)
346 346 &ds1287_hi_iblock, ds1287_intr, NULL) != DDI_SUCCESS) {
347 347 cmn_err(CE_WARN, "ds1287_attach: Failed to add high "
348 348 "interrupt.");
349 349 goto error2;
350 350 }
351 351
352 352 /*
353 353 * Combination of instance number and clone number 0 is used for
354 354 * creating the minor node.
355 355 */
356 356 if (ddi_create_minor_node(dip, "power_button", S_IFCHR,
357 357 (instance << 8) + 0, "ddi_power_button", NULL) == DDI_FAILURE) {
358 358 cmn_err(CE_WARN, "ds1287_attach: Failed to create minor node");
359 359 goto error3;
360 360 }
361 361
362 362 ddi_report_dev(dip);
363 363
364 364 return (DDI_SUCCESS);
365 365
366 366 error3:
367 367 ddi_remove_intr(dip, 0, NULL);
368 368 error2:
369 369 ddi_remove_softintr(ds1287_softintr_id);
370 370 error1:
371 371 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "interrupt-priorities");
372 372 error:
373 373 ddi_soft_state_free(ds1287_state, instance);
374 374 return (DDI_FAILURE);
375 375 }
376 376
377 377 /*ARGSUSED*/
378 378 static int
379 379 ds1287_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
380 380 {
381 381 DPRINTF("ds1287_detach\n");
382 382 switch (cmd) {
383 383 case DDI_DETACH:
384 384 /*
385 385 * Since it needs to always handle the power button, fail
386 386 * to detach.
387 387 */
388 388 return (DDI_FAILURE);
389 389 case DDI_SUSPEND:
390 390 return (DDI_SUCCESS);
391 391 default:
392 392 return (DDI_FAILURE);
393 393 }
394 394 }
395 395
396 396 /*ARGSUSED1*/
397 397 static int
398 398 ds1287_open(dev_t *devp, int flags, int otyp, cred_t *credp)
399 399 {
400 400 struct ds1287 *softsp;
401 401 int clone;
402 402
403 403 if (otyp != OTYP_CHR)
404 404 return (EINVAL);
405 405
406 406 if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
407 407 NULL)
408 408 return (ENXIO);
409 409
410 410 mutex_enter(&softsp->ds1287_mutex);
411 411 for (clone = 1; clone < DS1287_MAX_CLONE; clone++)
412 412 if (!softsp->clones[clone])
413 413 break;
414 414
415 415 if (clone == DS1287_MAX_CLONE) {
416 416 cmn_err(CE_WARN, "ds1287_open: No more allocation left "
417 417 "to clone a minor.");
418 418 mutex_exit(&softsp->ds1287_mutex);
419 419 return (ENXIO);
420 420 }
421 421
422 422 *devp = makedevice(getmajor(*devp), (instance << 8) + clone);
423 423 softsp->clones[clone] = 1;
424 424 mutex_exit(&softsp->ds1287_mutex);
425 425
426 426 return (0);
427 427 }
428 428
429 429 /*ARGSUSED*/
430 430 static int
431 431 ds1287_close(dev_t dev, int flags, int otyp, cred_t *credp)
432 432 {
433 433 struct ds1287 *softsp;
434 434 int clone;
435 435
436 436 if (otyp != OTYP_CHR)
437 437 return (EINVAL);
438 438
439 439 if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
440 440 NULL)
441 441 return (ENXIO);
442 442
443 443 clone = DS1287_MINOR_TO_CLONE(getminor(dev));
444 444 mutex_enter(&softsp->ds1287_mutex);
445 445 if (softsp->monitor_on == clone)
446 446 softsp->monitor_on = 0;
447 447 softsp->clones[clone] = 0;
448 448 mutex_exit(&softsp->ds1287_mutex);
449 449
450 450 return (0);
451 451 }
452 452
453 453 /*ARGSUSED4*/
454 454 static int
455 455 ds1287_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
456 456 cred_t *credp, int *rvalp)
457 457 {
458 458 struct ds1287 *softsp;
459 459 int clone;
460 460
461 461 if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
462 462 NULL)
463 463 return (ENXIO);
464 464
465 465 clone = DS1287_MINOR_TO_CLONE(getminor(dev));
466 466 switch (cmd) {
467 467 case PB_BEGIN_MONITOR:
468 468 DPRINTF("ds1287_ioctl: PB_BEGIN_MONITOR is called.\n");
469 469 mutex_enter(&softsp->ds1287_mutex);
470 470 if (softsp->monitor_on) {
471 471 mutex_exit(&softsp->ds1287_mutex);
472 472 return (EBUSY);
473 473 }
474 474 softsp->monitor_on = clone;
475 475 mutex_exit(&softsp->ds1287_mutex);
476 476 return (0);
477 477
478 478 case PB_END_MONITOR:
479 479 DPRINTF("ds1287_ioctl: PB_END_MONITOR is called.\n");
480 480 mutex_enter(&softsp->ds1287_mutex);
481 481
482 482 /*
483 483 * If PB_END_MONITOR is called without first
484 484 * calling PB_BEGIN_MONITOR, an error will be
485 485 * returned.
486 486 */
487 487 if (!softsp->monitor_on) {
488 488 mutex_exit(&softsp->ds1287_mutex);
489 489 return (ENXIO);
490 490 }
491 491
492 492 /*
493 493 * This clone is not monitoring the button.
494 494 */
495 495 if (softsp->monitor_on != clone) {
496 496 mutex_exit(&softsp->ds1287_mutex);
497 497 return (EINVAL);
498 498 }
499 499 softsp->monitor_on = 0;
500 500 mutex_exit(&softsp->ds1287_mutex);
501 501 return (0);
502 502
503 503 case PB_GET_EVENTS:
504 504 DPRINTF("ds1287_ioctl: PB_GET_EVENTS is called.\n");
505 505 mutex_enter(&softsp->ds1287_mutex);
506 506 if (ddi_copyout((void *)&softsp->events, (void *)arg,
507 507 sizeof (int), mode) != 0) {
508 508 mutex_exit(&softsp->ds1287_mutex);
509 509 return (EFAULT);
510 510 }
511 511
512 512 /*
513 513 * This ioctl returned the events detected since last
514 514 * call. Note that any application can get the events
515 515 * and clear the event register.
516 516 */
517 517 softsp->events = 0;
518 518 mutex_exit(&softsp->ds1287_mutex);
519 519 return (0);
520 520
521 521 /*
522 522 * This ioctl is used by the test suite.
523 523 */
524 524 case PB_CREATE_BUTTON_EVENT:
525 525 DPRINTF("ds1287_ioctl: PB_CREATE_BUTTON_EVENT is called.\n");
526 526 (void) ds1287_intr(NULL);
527 527 return (0);
528 528
529 529 default:
530 530 return (ENOTTY);
531 531 }
532 532 }
533 533
534 534 /*ARGSUSED*/
535 535 static int
536 536 ds1287_chpoll(dev_t dev, short events, int anyyet,
537 537 short *reventsp, struct pollhead **phpp)
538 538 {
539 539 struct ds1287 *softsp;
540 540
541 541 if ((softsp = ddi_get_soft_state(ds1287_state, instance)) == NULL)
542 542 return (ENXIO);
543 543
544 544 mutex_enter(&softsp->ds1287_mutex);
545 545 *reventsp = 0;
546 546 if (softsp->events)
547 547 *reventsp = POLLRDNORM|POLLIN;
548 548 else {
549 549 if (!anyyet)
550 550 *phpp = &softsp->pollhd;
551 551 }
552 552 mutex_exit(&softsp->ds1287_mutex);
553 553
554 554 return (0);
555 555 }
556 556
557 557 static void
558 558 ds1287_log_message(void)
559 559 {
560 560 struct ds1287 *softsp;
561 561
562 562 if ((softsp = ddi_get_soft_state(ds1287_state, instance)) == NULL) {
563 563 cmn_err(CE_WARN, "ds1287: Failed to get internal state!");
564 564 return;
565 565 }
566 566
567 567 mutex_enter(&softsp->ds1287_mutex);
568 568 softsp->shutdown_pending = 0;
569 569 cmn_err(CE_WARN, "ds1287: Failed to shut down the system!");
570 570 mutex_exit(&softsp->ds1287_mutex);
571 571 }
572 572
573 573 /*
574 574 * To facilitate a power button abort, ds1287_intr() now posts
575 575 * a softint (calling ds1287_softintr()) for all power button presses and
576 576 * counts the number of button presses. An abort is issued if the desired
577 577 * number of button presses within the given time interval.
578 578 *
579 579 * Two variables are used to synchronize between the high level intr;
580 580 * the softint handler and timeout handler
581 581 *
582 582 * power_button_cancel - Indicates that an abort happened and the number
583 583 * of outstanding timeouts that have to be cancelled
584 584 *
585 585 * power_button_pressed - Indicates the number of button presses outstanding
586 586 * which have not been serviced
587 587 */
588 588 /*ARGSUSED*/
589 589 static uint_t
590 590 ds1287_intr(caddr_t ignore)
591 591 {
592 592 hrtime_t tstamp;
593 593 static hrtime_t o_tstamp = 0;
594 594 static hrtime_t power_button_tstamp = 0;
595 595 static int power_button_cnt;
596 596 uint8_t apcr1;
597 597
598 598 /*
599 599 * Stop the Fail-safe timer that starts running
600 600 * after power button is pressed. If it is not
601 601 * stopped in 21 seconds, system powers off.
602 602 */
603 603 mutex_enter(&ds1287_reg_mutex);
604 604 select_bank(2);
605 605 DS1287_ADDR_REG = APC_APCR1;
606 606 apcr1 = DS1287_DATA_REG;
607 607 apcr1 |= APC_FSTRC;
608 608 DS1287_DATA_REG = apcr1;
609 609 select_bank(1);
610 610 mutex_exit(&ds1287_reg_mutex);
611 611
612 612 tstamp = gethrtime();
613 613
614 614 /* need to deal with power button debounce */
615 615 if (o_tstamp && (tstamp - o_tstamp) < power_button_debounce) {
616 616 o_tstamp = tstamp;
617 617 return (DDI_INTR_CLAIMED);
618 618 }
619 619 o_tstamp = tstamp;
620 620
621 621 power_button_cnt++;
622 622
623 623 mutex_enter(&ds1287_reg_mutex);
624 624 power_button_pressed++;
625 625 mutex_exit(&ds1287_reg_mutex);
626 626
627 627 /*
628 628 * If power button abort is enabled and power button was pressed
629 629 * power_button_abort_presses times within power_button_abort_interval
630 630 * then call abort_sequence_enter();
631 631 */
632 632 if (power_button_abort_enable) {
633 633 if (power_button_abort_presses == 1 ||
634 634 tstamp < (power_button_tstamp +
635 635 power_button_abort_interval)) {
636 636 if (power_button_cnt == power_button_abort_presses) {
637 637 mutex_enter(&ds1287_reg_mutex);
638 638 power_button_cancel += power_button_timeouts;
639 639 power_button_pressed = 0;
640 640 mutex_exit(&ds1287_reg_mutex);
641 641 power_button_cnt = 0;
642 642 abort_sequence_enter("Power Button Abort");
643 643 return (DDI_INTR_CLAIMED);
644 644 }
645 645 } else {
646 646 power_button_cnt = 1;
647 647 power_button_tstamp = tstamp;
648 648 }
649 649 }
650 650
651 651 if (!power_button_enable)
652 652 return (DDI_INTR_CLAIMED);
653 653
654 654 /* post softint to issue timeout for power button action */
655 655 ddi_trigger_softintr(ds1287_softintr_id);
656 656
657 657 return (DDI_INTR_CLAIMED);
658 658 }
659 659
660 660 /*
661 661 * Handle the softints....
662 662 *
663 663 * If only one softint is posted for several button presses, record
664 664 * the number of additional presses just incase this was actually not quite
665 665 * an Abort sequence so that we can log this event later.
666 666 *
667 667 * Issue a timeout with a duration being a fraction larger than
668 668 * the specified Abort interval inorder to perform a power down if required.
669 669 */
670 670 static uint_t
671 671 ds1287_softintr(caddr_t arg)
672 672 {
673 673 struct ds1287 *softsp = (struct ds1287 *)arg;
674 674
675 675 DPRINTF("ds1287_softintr\n");
676 676
677 677 if (!power_button_abort_enable)
678 678 return (ds1287_issue_shutdown(arg));
679 679
680 680 mutex_enter(&ds1287_reg_mutex);
681 681 if (!power_button_pressed) {
682 682 mutex_exit(&ds1287_reg_mutex);
683 683 return (DDI_INTR_CLAIMED);
684 684 }
685 685
686 686 /*
687 687 * Schedule a timeout to do the necessary
688 688 * work for shutdown, only one timeout for
689 689 * n presses if power button was pressed
690 690 * more than once before softint fired
691 691 */
692 692 if (power_button_pressed > 1)
693 693 additional_presses += power_button_pressed - 1;
694 694
695 695 timeout_cancel = 0;
696 696 power_button_pressed = 0;
697 697 power_button_timeouts++;
698 698 mutex_exit(&ds1287_reg_mutex);
699 699 (void) timeout((void(*)(void *))ds1287_timeout,
700 700 softsp, NSEC_TO_TICK(power_button_abort_interval) +
701 701 ABORT_INCREMENT_DELAY);
702 702
703 703 return (DDI_INTR_CLAIMED);
704 704 }
705 705
706 706 /*
707 707 * Upon receiving a timeout the following is determined:
708 708 *
709 709 * If an Abort sequence was issued, then we cancel all outstanding timeouts
710 710 * and additional presses prior to the Abort sequence.
711 711 *
712 712 * If we had multiple timeouts issued and the abort sequence was not met,
713 713 * then we had more than one button press to power down the machine. We
714 714 * were probably trying to issue an abort. So log a message indicating this
715 715 * and cancel all outstanding timeouts.
716 716 *
717 717 * If we had just one timeout and the abort sequence was not met then
718 718 * we really did want to power down the machine, so call ds1287_issue_shutdown()
719 719 * to do the work and schedule a power down
720 720 */
721 721 static void
722 722 ds1287_timeout(caddr_t arg)
723 723 {
724 724 static int first = 0;
725 725
726 726 DPRINTF("ds1287_timeout\n");
727 727
728 728 /*
729 729 * Abort was generated cancel all outstanding power
730 730 * button timeouts
731 731 */
732 732 mutex_enter(&ds1287_reg_mutex);
733 733 if (power_button_cancel) {
734 734 power_button_cancel--;
735 735 power_button_timeouts--;
736 736 if (!first) {
737 737 first++;
738 738 additional_presses = 0;
739 739 }
740 740 mutex_exit(&ds1287_reg_mutex);
741 741 return;
742 742 }
743 743 first = 0;
744 744
745 745 /*
746 746 * We get here if the timeout(s) have fired and they were
747 747 * not issued prior to an abort.
748 748 *
749 749 * If we had more than one press in the interval we were
750 750 * probably trying to issue an abort, but didnt press the
751 751 * required number within the interval. Hence cancel all
752 752 * timeouts and do not continue towards shutdown.
753 753 */
754 754 if (!timeout_cancel) {
755 755 timeout_cancel = power_button_timeouts +
756 756 additional_presses;
757 757
758 758 power_button_timeouts--;
759 759 if (!power_button_timeouts)
760 760 additional_presses = 0;
761 761
762 762 if (timeout_cancel > 1) {
763 763 mutex_exit(&ds1287_reg_mutex);
764 764 cmn_err(CE_NOTE, "Power Button pressed "
765 765 "%d times, cancelling all requests",
766 766 timeout_cancel);
767 767 return;
768 768 }
769 769 mutex_exit(&ds1287_reg_mutex);
770 770
771 771 /* Go and do the work to request shutdown */
772 772 (void) ds1287_issue_shutdown(arg);
773 773 return;
774 774 }
775 775
776 776 power_button_timeouts--;
777 777 if (!power_button_timeouts)
778 778 additional_presses = 0;
779 779 mutex_exit(&ds1287_reg_mutex);
780 780 }
781 781
782 782 static uint_t
783 783 ds1287_issue_shutdown(caddr_t arg)
784 784 {
785 785 struct ds1287 *softsp = (struct ds1287 *)arg;
786 786
787 787 DPRINTF("ds1287_issue_shutdown\n");
788 788
789 789 mutex_enter(&softsp->ds1287_mutex);
790 790 softsp->events |= PB_BUTTON_PRESS;
791 791 if (softsp->monitor_on != 0) {
792 792 mutex_exit(&softsp->ds1287_mutex);
793 793 pollwakeup(&softsp->pollhd, POLLRDNORM);
794 794 pollwakeup(&softsp->pollhd, POLLIN);
795 795 return (DDI_INTR_CLAIMED);
796 796 }
797 797
798 798 if (!softsp->shutdown_pending) {
799 799 cmn_err(CE_WARN, "Power button is pressed, powering down "
800 800 "the system!");
801 801 softsp->shutdown_pending = 1;
802 802 do_shutdown();
803 803
804 804 /*
805 805 * Wait a while for "do_shutdown()" to shut down the system
806 806 * before logging an error message.
807 807 */
808 808 (void) timeout((void(*)(void *))ds1287_log_message, NULL,
809 809 100 * hz);
810 810 }
811 811 mutex_exit(&softsp->ds1287_mutex);
812 812
813 813 return (DDI_INTR_CLAIMED);
814 814 }
815 815
816 816 /*
817 817 * Read the current time from the clock chip and convert to UNIX form.
818 818 * Assumes that the year in the clock chip is valid.
819 819 * Must be called with tod_lock held.
820 820 */
821 821 static timestruc_t
822 822 todds_get(void)
823 823 {
824 824 timestruc_t ts;
825 825 todinfo_t tod;
826 826 struct rtc_t rtc;
827 827
828 828 ASSERT(MUTEX_HELD(&tod_lock));
829 829
830 830 read_rtc(&rtc);
831 831 DPRINTF("todds_get: century=%d year=%d dom=%d hrs=%d\n",
832 832 rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs);
833 833
834 834 /*
835 835 * tod_year is base 1900 so this code needs to adjust the true
836 836 * year retrieved from the rtc's century and year fields.
837 837 */
838 838 tod.tod_year = rtc.rtc_year + (rtc.rtc_century * 100) - 1900;
839 839 tod.tod_month = rtc.rtc_mon;
840 840 tod.tod_day = rtc.rtc_dom;
841 841 tod.tod_dow = rtc.rtc_dow;
842 842 tod.tod_hour = rtc.rtc_hrs;
843 843 tod.tod_min = rtc.rtc_min;
844 844 tod.tod_sec = rtc.rtc_sec;
845 845
846 846 ts.tv_sec = tod_to_utc(tod);
847 847 ts.tv_nsec = 0;
848 848
849 849 /* set the hw watchdog timer if it's been activated */
850 850 if (watchdog_activated) {
851 851 int ret = 0;
852 852 ret = tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds);
853 853 if (ret == 0)
854 854 cmn_err(CE_WARN, "ds1287: failed to set hardware "
855 855 "watchdog timer.");
856 856 }
857 857
858 858 return (ts);
859 859 }
860 860
861 861 void
862 862 read_rtc(struct rtc_t *rtc)
863 863 {
864 864 uint8_t regb;
865 865
866 866 /*
867 867 * Some SuperIO tod devices don't seem to properly initialize
868 868 * the CADDR register to place the Century register at bank 1
869 869 * address 0x48.
870 870 */
871 871 mutex_enter(&ds1287_reg_mutex);
872 872
873 873 select_bank(2);
874 874 DS1287_ADDR_REG = RTC_CADDR;
875 875 regb = DS1287_DATA_REG;
876 876 if (regb != 0xc8) {
877 877 if (!ds1287_caddr_warn) {
878 878 ds1287_caddr_warn = 1;
879 879 cmn_err(CE_WARN, "ds1287: century address register "
880 880 "incorrect (exp 0xc8, obs %x)", regb);
881 881 }
882 882 DS1287_DATA_REG = 0xc8;
883 883 }
884 884
885 885 select_bank(1);
886 886 /*
887 887 * Freeze clock update
888 888 */
889 889 DS1287_ADDR_REG = RTC_B;
890 890 regb = DS1287_DATA_REG;
891 891 DS1287_DATA_REG = (regb | RTC_SET);
892 892
893 893 DS1287_ADDR_REG = RTC_SEC;
894 894 rtc->rtc_sec = DS1287_DATA_REG;
895 895 DS1287_ADDR_REG = RTC_ASEC;
896 896 rtc->rtc_asec = DS1287_DATA_REG;
897 897 DS1287_ADDR_REG = RTC_MIN;
898 898 rtc->rtc_min = DS1287_DATA_REG;
899 899 DS1287_ADDR_REG = RTC_AMIN;
900 900 rtc->rtc_amin = DS1287_DATA_REG;
901 901 DS1287_ADDR_REG = RTC_HRS;
902 902 rtc->rtc_hrs = DS1287_DATA_REG;
903 903 DS1287_ADDR_REG = RTC_AHRS;
904 904 rtc->rtc_ahrs = DS1287_DATA_REG;
905 905 DS1287_ADDR_REG = RTC_DOW;
906 906 rtc->rtc_dow = DS1287_DATA_REG;
907 907 DS1287_ADDR_REG = RTC_DOM;
908 908 rtc->rtc_dom = DS1287_DATA_REG;
909 909 DS1287_ADDR_REG = RTC_MON;
910 910 rtc->rtc_mon = DS1287_DATA_REG;
911 911 DS1287_ADDR_REG = RTC_YEAR;
912 912 rtc->rtc_year = DS1287_DATA_REG;
913 913 DS1287_ADDR_REG = RTC_CENTURY;
914 914 rtc->rtc_century = DS1287_DATA_REG;
915 915
916 916 /* Read date alarm */
917 917 DS1287_ADDR_REG = RTC_ADOM;
918 918 rtc->rtc_adom = DS1287_DATA_REG;
919 919 DS1287_ADDR_REG = RTC_AMON;
920 920 rtc->rtc_amon = DS1287_DATA_REG;
921 921
922 922 /* Read wakeup data */
923 923 select_bank(2);
924 924 DS1287_ADDR_REG = APC_WDWR;
925 925 rtc->apc_wdwr = DS1287_DATA_REG;
926 926 DS1287_ADDR_REG = APC_WDMR;
927 927 rtc->apc_wdmr = DS1287_DATA_REG;
928 928 DS1287_ADDR_REG = APC_WMR;
929 929 rtc->apc_wmr = DS1287_DATA_REG;
930 930 DS1287_ADDR_REG = APC_WYR;
931 931 rtc->apc_wyr = DS1287_DATA_REG;
932 932 DS1287_ADDR_REG = APC_WCR;
933 933 rtc->apc_wcr = DS1287_DATA_REG;
934 934
935 935 /*
936 936 * Unfreeze clock update
937 937 */
938 938 DS1287_ADDR_REG = RTC_B;
939 939 DS1287_DATA_REG = regb;
940 940
941 941 mutex_exit(&ds1287_reg_mutex);
942 942 }
943 943
944 944 /*
945 945 * Write the specified time into the clock chip.
946 946 * Must be called with tod_lock held.
947 947 */
948 948 static void
949 949 todds_set(timestruc_t ts)
950 950 {
951 951 struct rtc_t rtc;
952 952 todinfo_t tod = utc_to_tod(ts.tv_sec);
953 953 int year;
954 954
955 955 ASSERT(MUTEX_HELD(&tod_lock));
956 956
957 957 /* tod_year is base 1900 so this code needs to adjust */
958 958 year = 1900 + tod.tod_year;
959 959 rtc.rtc_year = year % 100;
960 960 rtc.rtc_century = year / 100;
961 961 rtc.rtc_mon = (uint8_t)tod.tod_month;
962 962 rtc.rtc_dom = (uint8_t)tod.tod_day;
963 963 rtc.rtc_dow = (uint8_t)tod.tod_dow;
964 964 rtc.rtc_hrs = (uint8_t)tod.tod_hour;
965 965 rtc.rtc_min = (uint8_t)tod.tod_min;
966 966 rtc.rtc_sec = (uint8_t)tod.tod_sec;
967 967 DPRINTF("todds_set: century=%d year=%d dom=%d hrs=%d\n",
968 968 rtc.rtc_century, rtc.rtc_year, rtc.rtc_dom, rtc.rtc_hrs);
969 969
970 970 write_rtc_time(&rtc);
971 971 }
972 972
973 973 void
974 974 write_rtc_time(struct rtc_t *rtc)
975 975 {
976 976 uint8_t regb;
977 977
978 978 /*
979 979 * Some SuperIO tod devices don't seem to properly initialize
980 980 * the CADDR register to place the Century register at bank 1
981 981 * address 0x48.
982 982 */
983 983 mutex_enter(&ds1287_reg_mutex);
984 984
985 985 select_bank(2);
986 986 DS1287_ADDR_REG = RTC_CADDR;
987 987 regb = DS1287_DATA_REG;
988 988 if (regb != 0xc8) {
989 989 if (!ds1287_caddr_warn) {
990 990 ds1287_caddr_warn = 1;
991 991 cmn_err(CE_WARN, "ds1287: century address register "
992 992 "incorrect (exp 0xc8, obs %x)", regb);
993 993 }
994 994 DS1287_DATA_REG = 0xc8;
995 995 }
996 996
997 997 select_bank(1);
998 998
999 999 /*
1000 1000 * Freeze
1001 1001 */
1002 1002 DS1287_ADDR_REG = RTC_B;
1003 1003 regb = DS1287_DATA_REG;
1004 1004
1005 1005 DS1287_DATA_REG = (regb | RTC_SET);
1006 1006
1007 1007 DS1287_ADDR_REG = RTC_SEC;
1008 1008 DS1287_DATA_REG = rtc->rtc_sec;
1009 1009 DS1287_ADDR_REG = RTC_MIN;
1010 1010 DS1287_DATA_REG = rtc->rtc_min;
1011 1011 DS1287_ADDR_REG = RTC_HRS;
1012 1012 DS1287_DATA_REG = rtc->rtc_hrs;
1013 1013 DS1287_ADDR_REG = RTC_DOW;
1014 1014 DS1287_DATA_REG = rtc->rtc_dow;
1015 1015 DS1287_ADDR_REG = RTC_DOM;
1016 1016 DS1287_DATA_REG = rtc->rtc_dom;
1017 1017 DS1287_ADDR_REG = RTC_MON;
1018 1018 DS1287_DATA_REG = rtc->rtc_mon;
1019 1019 DS1287_ADDR_REG = RTC_YEAR;
1020 1020 DS1287_DATA_REG = rtc->rtc_year;
1021 1021 DS1287_ADDR_REG = RTC_CENTURY;
1022 1022 DS1287_DATA_REG = rtc->rtc_century;
1023 1023
1024 1024 /*
1025 1025 * Unfreeze
1026 1026 */
1027 1027 DS1287_ADDR_REG = RTC_B;
1028 1028 DS1287_DATA_REG = regb;
1029 1029
1030 1030 mutex_exit(&ds1287_reg_mutex);
1031 1031 }
1032 1032
1033 1033 void
1034 1034 write_rtc_alarm(struct rtc_t *rtc)
1035 1035 {
1036 1036 mutex_enter(&ds1287_reg_mutex);
1037 1037
1038 1038 select_bank(1);
1039 1039 DS1287_ADDR_REG = RTC_ASEC;
1040 1040 DS1287_DATA_REG = rtc->rtc_asec;
1041 1041 DS1287_ADDR_REG = RTC_AMIN;
1042 1042 DS1287_DATA_REG = rtc->rtc_amin;
1043 1043 DS1287_ADDR_REG = RTC_AHRS;
1044 1044 DS1287_DATA_REG = rtc->rtc_ahrs;
1045 1045 DS1287_ADDR_REG = RTC_ADOM;
1046 1046 DS1287_DATA_REG = rtc->rtc_adom;
1047 1047 DS1287_ADDR_REG = RTC_AMON;
1048 1048 DS1287_DATA_REG = rtc->rtc_amon;
1049 1049
1050 1050 select_bank(2);
1051 1051 DS1287_ADDR_REG = APC_WDWR;
1052 1052 DS1287_DATA_REG = rtc->apc_wdwr;
1053 1053 DS1287_ADDR_REG = APC_WDMR;
1054 1054 DS1287_DATA_REG = rtc->apc_wdmr;
1055 1055 DS1287_ADDR_REG = APC_WMR;
1056 1056 DS1287_DATA_REG = rtc->apc_wmr;
1057 1057 DS1287_ADDR_REG = APC_WYR;
1058 1058 DS1287_DATA_REG = rtc->apc_wyr;
1059 1059 DS1287_ADDR_REG = APC_WCR;
1060 1060 DS1287_DATA_REG = rtc->apc_wcr;
1061 1061
1062 1062 mutex_exit(&ds1287_reg_mutex);
1063 1063 }
1064 1064
1065 1065 /*
1066 1066 * program the rtc registers for alarm to go off at the specified time
1067 1067 */
1068 1068 static void
1069 1069 todds_set_power_alarm(timestruc_t ts)
1070 1070 {
1071 1071 todinfo_t tod;
1072 1072 uint8_t apcr2;
1073 1073 struct rtc_t rtc;
1074 1074
1075 1075 ASSERT(MUTEX_HELD(&tod_lock));
1076 1076 tod = utc_to_tod(ts.tv_sec);
1077 1077 mutex_enter(&ds1287_reg_mutex);
1078 1078
1079 1079 /* Clear Time Match Detect */
1080 1080 select_bank(2);
1081 1081 DS1287_ADDR_REG = APC_APSR;
1082 1082 apcr2 = DS1287_DATA_REG;
1083 1083
1084 1084 /* Disable Time Match Enable */
1085 1085 DS1287_ADDR_REG = APC_APCR2;
1086 1086 apcr2 = DS1287_DATA_REG;
1087 1087 DS1287_DATA_REG = (apcr2 & (~APC_TME));
1088 1088
1089 1089 mutex_exit(&ds1287_reg_mutex);
1090 1090
1091 1091 rtc.rtc_asec = (uint8_t)tod.tod_sec;
1092 1092 rtc.rtc_amin = (uint8_t)tod.tod_min;
1093 1093 rtc.rtc_ahrs = (uint8_t)tod.tod_hour;
1094 1094 rtc.rtc_adom = (uint8_t)tod.tod_day;
1095 1095 rtc.rtc_amon = (uint8_t)tod.tod_month;
1096 1096
1097 1097 rtc.apc_wdwr = (uint8_t)tod.tod_dow;
1098 1098 rtc.apc_wdmr = (uint8_t)tod.tod_day;
1099 1099 rtc.apc_wmr = (uint8_t)tod.tod_month;
1100 1100 rtc.apc_wyr = tod.tod_year % 100;
1101 1101 rtc.apc_wcr = (tod.tod_year / 100) + 19;
1102 1102
1103 1103 write_rtc_alarm(&rtc);
1104 1104
1105 1105 mutex_enter(&ds1287_reg_mutex);
1106 1106 /* Enable Time Match enable */
1107 1107 select_bank(2);
1108 1108 DS1287_ADDR_REG = APC_APCR2;
1109 1109 DS1287_DATA_REG = (apcr2 | APC_TME);
1110 1110
1111 1111 mutex_exit(&ds1287_reg_mutex);
1112 1112 }
1113 1113
1114 1114 /*
1115 1115 * clear alarm interrupt
1116 1116 */
1117 1117 static void
1118 1118 todds_clear_power_alarm(void)
1119 1119 {
1120 1120 uint8_t apcr2;
1121 1121
1122 1122 ASSERT(MUTEX_HELD(&tod_lock));
1123 1123
1124 1124 mutex_enter(&ds1287_reg_mutex);
1125 1125
1126 1126 /* Clear Time Match Detect */
1127 1127 select_bank(2);
1128 1128 DS1287_ADDR_REG = APC_APSR;
1129 1129 apcr2 = DS1287_DATA_REG;
1130 1130
1131 1131 /* Disable Time Match Enable */
1132 1132 DS1287_ADDR_REG = APC_APCR2;
1133 1133 apcr2 = DS1287_DATA_REG;
1134 1134 DS1287_DATA_REG = (apcr2 & (~APC_TME));
1135 1135
1136 1136 mutex_exit(&ds1287_reg_mutex);
1137 1137 }
1138 1138
1139 1139 /*
1140 1140 * Determine the cpu frequency by watching the TOD chip rollover twice.
1141 1141 * Cpu clock rate is determined by computing the ticks added (in tick register)
1142 1142 * during one second interval on TOD.
1143 1143 */
1144 1144 uint64_t
1145 1145 todds_get_cpufrequency(void)
1146 1146 {
1147 1147 uint64_t cpu_freq;
1148 1148
1149 1149 ASSERT(MUTEX_HELD(&tod_lock));
1150 1150 mutex_enter(&ds1287_reg_mutex);
1151 1151
1152 1152 select_bank(1);
1153 1153 DS1287_ADDR_REG = RTC_SEC;
1154 1154 cpu_freq = find_cpufrequency(v_rtc_data_reg);
1155 1155
1156 1156 mutex_exit(&ds1287_reg_mutex);
1157 1157 return (cpu_freq);
1158 1158 }
1159 1159
1160 1160 static void
1161 1161 select_bank(int bank)
1162 1162 {
1163 1163 uint8_t rega;
1164 1164 int banksel;
1165 1165
1166 1166 /* Select Bank 1 */
1167 1167 DS1287_ADDR_REG = RTC_A;
1168 1168 rega = DS1287_DATA_REG;
1169 1169 rega = rega & ~(RTC_DIV0 | RTC_DIV1 | RTC_DIV2);
1170 1170 switch (bank) {
1171 1171 case 0:
1172 1172 banksel = RTC_DIV1;
1173 1173 break;
1174 1174 case 1:
1175 1175 banksel = RTC_DIV0 | RTC_DIV1;
1176 1176 break;
1177 1177 case 2:
1178 1178 banksel = RTC_DIV2;
1179 1179 break;
1180 1180 }
1181 1181 rega |= banksel;
1182 1182 DS1287_DATA_REG = rega;
1183 1183 }
1184 1184
1185 1185 /*ARGSUSED*/
1186 1186 static uint_t
1187 1187 todds_set_watchdog_timer(uint_t timeoutval)
1188 1188 {
1189 1189 ASSERT(MUTEX_HELD(&tod_lock));
1190 1190 return (0);
1191 1191 }
1192 1192
1193 1193 static uint_t
1194 1194 todds_clear_watchdog_timer(void)
1195 1195 {
1196 1196 ASSERT(MUTEX_HELD(&tod_lock));
1197 1197 return (0);
1198 1198 }
↓ open down ↓ |
1027 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX