Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sun4u/littleneck/io/pcf8574_lneck.c
+++ new/usr/src/uts/sun4u/littleneck/io/pcf8574_lneck.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 #include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */
29 29 #include <sys/modctl.h> /* for modldrv */
30 30 #include <sys/open.h> /* for open params. */
31 31 #include <sys/types.h>
32 32 #include <sys/kmem.h>
33 33 #include <sys/sunddi.h>
34 34 #include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */
35 35 #include <sys/ddi.h>
36 36 #include <sys/file.h>
37 37 #include <sys/note.h>
38 38
39 39 #include <sys/i2c/clients/pcf8574_impl.h>
40 40
41 41 static void *pcf8574soft_statep;
42 42
43 43 static int pcf8574_do_attach(dev_info_t *);
44 44 static int pcf8574_do_detach(dev_info_t *);
45 45 static int pcf8574_do_resume(void);
46 46 static int pcf8574_do_suspend(void);
47 47 static int pcf8574_get(struct pcf8574_unit *, uchar_t *);
48 48 static int pcf8574_set(struct pcf8574_unit *, uchar_t);
49 49
50 50 static void littleneck_abort_seq_handler(char *msg);
51 51 extern void (*abort_seq_handler)();
52 52
53 53 static void littleneck_ks_poll(void *);
54 54
55 55 /*
56 56 * cb ops (only need ioctl)
57 57 */
58 58 static int pcf8574_open(dev_t *, int, int, cred_t *);
59 59 static int pcf8574_close(dev_t, int, int, cred_t *);
60 60 static int pcf8574_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
61 61
62 62 static struct cb_ops pcf8574_cbops = {
63 63 pcf8574_open, /* open */
64 64 pcf8574_close, /* close */
65 65 nodev, /* strategy */
66 66 nodev, /* print */
67 67 nodev, /* dump */
68 68 nodev, /* read */
69 69 nodev, /* write */
70 70 pcf8574_ioctl, /* ioctl */
71 71 nodev, /* devmap */
72 72 nodev, /* mmap */
73 73 nodev, /* segmap */
74 74 nochpoll, /* poll */
75 75 ddi_prop_op, /* cb_prop_op */
76 76 NULL, /* streamtab */
77 77 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
78 78 CB_REV, /* rev */
79 79 nodev, /* int (*cb_aread)() */
80 80 nodev /* int (*cb_awrite)() */
81 81 };
82 82
83 83 /*
84 84 * dev ops
85 85 */
86 86 static int pcf8574_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
87 87 static int pcf8574_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
88 88
89 89 static struct dev_ops pcf8574_ops = {
90 90 DEVO_REV,
91 91 0,
92 92 ddi_getinfo_1to1,
93 93 nulldev,
94 94 nulldev,
95 95 pcf8574_attach,
96 96 pcf8574_detach,
97 97 nodev,
98 98 &pcf8574_cbops,
99 99 NULL, /* bus_ops */
100 100 NULL, /* power */
101 101 ddi_quiesce_not_needed, /* quiesce */
102 102 };
103 103
104 104 extern struct mod_ops mod_driverops;
105 105
106 106 static struct modldrv pcf8574_modldrv = {
107 107 &mod_driverops, /* type of module - driver */
108 108 "PCF8574 i2c device driver: v1.9",
109 109 &pcf8574_ops
110 110 };
111 111
112 112 static struct modlinkage pcf8574_modlinkage = {
113 113 MODREV_1,
114 114 &pcf8574_modldrv,
115 115 0
116 116 };
117 117
118 118 #define LNECK_KEY_POLL_BIT 5
119 119 #define LNECK_KEY_POLL_INTVL 10 /* 10 seconds poll interval */
120 120 static timeout_id_t keypoll_timeout_id;
121 121 static clock_t keypoll_timeout_hz;
122 122 static boolean_t key_locked_bit;
123 123
124 124
125 125 int
126 126 _init(void)
127 127 {
128 128 int error;
129 129
130 130 error = mod_install(&pcf8574_modlinkage);
131 131
132 132 if (!error)
133 133 (void) ddi_soft_state_init(&pcf8574soft_statep,
134 134 sizeof (struct pcf8574_unit), 1);
135 135 return (error);
136 136 }
137 137
138 138 int
139 139 _fini(void)
140 140 {
141 141 int error;
142 142
143 143 error = mod_remove(&pcf8574_modlinkage);
144 144 if (!error)
145 145 ddi_soft_state_fini(&pcf8574soft_statep);
146 146
147 147 return (error);
148 148 }
149 149
150 150 int
151 151 _info(struct modinfo *modinfop)
152 152 {
153 153 return (mod_info(&pcf8574_modlinkage, modinfop));
154 154 }
155 155
156 156 static int
157 157 pcf8574_open(dev_t *devp, int flags, int otyp, cred_t *credp)
158 158 {
159 159 _NOTE(ARGUNUSED(credp))
160 160 struct pcf8574_unit *unitp;
161 161 int instance;
162 162 int error = 0;
163 163
164 164 D1CMN_ERR((CE_WARN, "Opening the PCF8574 device\n"));
165 165
166 166 instance = getminor(*devp);
167 167
168 168 if (instance < 0) {
169 169 return (ENXIO);
170 170 }
171 171
172 172 unitp = (struct pcf8574_unit *)
173 173 ddi_get_soft_state(pcf8574soft_statep, instance);
174 174
175 175 if (unitp == NULL) {
176 176 return (ENXIO);
177 177 }
178 178
179 179 if (otyp != OTYP_CHR) {
180 180 return (EINVAL);
181 181 }
182 182
183 183 mutex_enter(&unitp->pcf8574_mutex);
184 184
185 185 if (flags & FEXCL) {
186 186 if (unitp->pcf8574_oflag != 0) {
187 187 error = EBUSY;
188 188 } else {
189 189 unitp->pcf8574_oflag = FEXCL;
190 190 }
191 191 } else {
192 192 if (unitp->pcf8574_oflag == FEXCL) {
193 193 error = EBUSY;
194 194 } else {
195 195 unitp->pcf8574_oflag = FOPEN;
196 196 }
197 197 }
198 198
199 199 mutex_exit(&unitp->pcf8574_mutex);
200 200
201 201 return (error);
202 202 }
203 203
204 204 static int
205 205 pcf8574_close(dev_t dev, int flags, int otyp, cred_t *credp)
206 206 {
207 207 _NOTE(ARGUNUSED(flags, otyp, credp))
208 208 struct pcf8574_unit *unitp;
209 209 int instance;
210 210
211 211 instance = getminor(dev);
212 212
213 213 if (instance < 0) {
214 214 return (ENXIO);
215 215 }
216 216 unitp = (struct pcf8574_unit *)
217 217 ddi_get_soft_state(pcf8574soft_statep, instance);
218 218
219 219 if (unitp == NULL) {
220 220 return (ENXIO);
221 221 }
222 222
223 223 mutex_enter(&unitp->pcf8574_mutex);
224 224
225 225 unitp->pcf8574_oflag = 0;
226 226
227 227 mutex_exit(&unitp->pcf8574_mutex);
228 228 return (DDI_SUCCESS);
229 229 }
230 230
231 231 static int
232 232 pcf8574_get(struct pcf8574_unit *unitp, uchar_t *byte) {
233 233 i2c_transfer_t *i2c_tran_pointer;
234 234 int err = I2C_SUCCESS;
235 235
236 236 D1CMN_ERR((CE_WARN, "Entered the pcf8574_get routine\n"));
237 237
238 238 (void) i2c_transfer_alloc(unitp->pcf8574_hdl, &i2c_tran_pointer,
239 239 0, 1, I2C_SLEEP);
240 240 if (i2c_tran_pointer == NULL) {
241 241 D2CMN_ERR((CE_WARN, "%s: Failed in pcf8574_get "
242 242 "i2c_tran_pointer not allocated\n",
243 243 unitp->pcf8574_name));
244 244 return (ENOMEM);
245 245 }
246 246
247 247 i2c_tran_pointer->i2c_flags = I2C_RD;
248 248
249 249 err = i2c_transfer(unitp->pcf8574_hdl, i2c_tran_pointer);
250 250 if (err) {
251 251 D2CMN_ERR((CE_WARN, "%s: Failed in the i2c_transfer routine\n",
252 252 unitp->pcf8574_name));
253 253 i2c_transfer_free(unitp->pcf8574_hdl, i2c_tran_pointer);
254 254 return (err);
255 255 }
256 256
257 257 D1CMN_ERR((CE_WARN, "Back from a transfer value is %x\n",
258 258 i2c_tran_pointer->i2c_rbuf[0]));
259 259 *byte = i2c_tran_pointer->i2c_rbuf[0];
260 260
261 261 i2c_transfer_free(unitp->pcf8574_hdl, i2c_tran_pointer);
262 262 return (err);
263 263 }
264 264
265 265 static int
266 266 pcf8574_set(struct pcf8574_unit *unitp, uchar_t byte) {
267 267 i2c_transfer_t *i2c_tran_pointer;
268 268 int err = I2C_SUCCESS;
269 269
270 270 (void) i2c_transfer_alloc(unitp->pcf8574_hdl, &i2c_tran_pointer,
271 271 1, 0, I2C_SLEEP);
272 272 if (i2c_tran_pointer == NULL) {
273 273 D2CMN_ERR((CE_WARN, "%s: Failed in pcf8574_set "
274 274 "i2c_tran_pointer not allocated\n",
275 275 unitp->pcf8574_name));
276 276 return (ENOMEM);
277 277 }
278 278
279 279 i2c_tran_pointer->i2c_flags = I2C_WR;
280 280 i2c_tran_pointer->i2c_wbuf[0] = byte;
281 281
282 282 D1CMN_ERR((CE_NOTE, "%s: contains %x\n", unitp->pcf8574_name,
283 283 i2c_tran_pointer->i2c_wbuf[0]));
284 284
285 285 err = i2c_transfer(unitp->pcf8574_hdl, i2c_tran_pointer);
286 286 if (err) {
287 287 D2CMN_ERR((CE_WARN, "%s: Failed in the pcf8574_set"
288 288 " i2c_transfer routine\n",
289 289 unitp->pcf8574_name));
290 290 i2c_transfer_free(unitp->pcf8574_hdl, i2c_tran_pointer);
291 291 return (err);
292 292 }
293 293 i2c_transfer_free(unitp->pcf8574_hdl, i2c_tran_pointer);
294 294 return (err);
295 295 }
296 296
297 297 static int
298 298 pcf8574_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
299 299 cred_t *credp, int *rvalp)
300 300 {
301 301 _NOTE(ARGUNUSED(credp, rvalp))
302 302 struct pcf8574_unit *unitp;
303 303 int instance;
304 304 int err = 0;
305 305 i2c_bit_t ioctl_bit;
306 306 i2c_port_t ioctl_port;
307 307 uchar_t byte;
308 308
309 309 if (arg == NULL) {
310 310 D2CMN_ERR((CE_WARN, "PCF8574: ioctl: arg passed in to ioctl "
311 311 "= NULL\n"));
312 312 err = EINVAL;
313 313 return (err);
314 314 }
315 315
316 316 instance = getminor(dev);
317 317 unitp = (struct pcf8574_unit *)
318 318 ddi_get_soft_state(pcf8574soft_statep, instance);
319 319 if (unitp == NULL) {
320 320 cmn_err(CE_WARN, "PCF8574: ioctl: unitp not filled\n");
321 321 return (ENOMEM);
322 322 }
323 323
324 324 mutex_enter(&unitp->pcf8574_mutex);
325 325
326 326 switch (cmd) {
327 327 case I2C_GET_PORT:
328 328 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_port,
329 329 sizeof (i2c_port_t), mode) != DDI_SUCCESS) {
330 330 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_PORT"
331 331 " ddi_copyin routine\n",
332 332 unitp->pcf8574_name));
333 333 err = EFAULT;
334 334 break;
335 335 }
336 336
337 337 err = pcf8574_get(unitp, &byte);
338 338 if (err != I2C_SUCCESS) {
339 339 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_PORT"
340 340 " pcf8574_get routine\n",
341 341 unitp->pcf8574_name));
342 342 break;
343 343 }
344 344
345 345 ioctl_port.value = byte;
346 346 if (ddi_copyout((caddr_t)&ioctl_port, (caddr_t)arg,
347 347 sizeof (i2c_port_t), mode) != DDI_SUCCESS) {
348 348 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_GET_PORT "
349 349 "ddi_copyout routine\n",
350 350 unitp->pcf8574_name));
351 351 err = EFAULT;
352 352 }
353 353
354 354 D1CMN_ERR((CE_NOTE, "%s: contains %x\n", unitp->pcf8574_name,
355 355 byte));
356 356 break;
357 357
358 358 case I2C_SET_PORT:
359 359 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_port,
360 360 sizeof (uint8_t), mode) != DDI_SUCCESS) {
361 361 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_PORT"
362 362 "ddi_cpoyin routine\n",
363 363 unitp->pcf8574_name));
364 364 err = EFAULT;
365 365 break;
366 366 }
367 367
368 368 err = pcf8574_set(unitp, ioctl_port.value);
369 369 if (err != I2C_SUCCESS) {
370 370 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_PORT"
371 371 " pcf8574_set routine\n",
372 372 unitp->pcf8574_name));
373 373 break;
374 374 }
375 375 break;
376 376
377 377 case I2C_GET_BIT:
378 378 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_bit,
379 379 sizeof (i2c_bit_t), mode) != DDI_SUCCESS) {
380 380 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_BIT"
381 381 " ddi_copyin routine\n",
382 382 unitp->pcf8574_name));
383 383 err = EFAULT;
384 384 break;
385 385 }
386 386
387 387 if (ioctl_bit.bit_num > 7) {
388 388 D2CMN_ERR((CE_WARN, "%s: In I2C_GET_BIT bit num"
389 389 " was not between 0 and 7\n",
390 390 unitp->pcf8574_name));
391 391 err = EIO;
392 392 break;
393 393 }
394 394
395 395 err = pcf8574_get(unitp, &byte);
396 396 if (err != I2C_SUCCESS) {
397 397 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_BIT"
398 398 " pcf8574_get routine\n",
399 399 unitp->pcf8574_name));
400 400 break;
401 401 }
402 402
403 403 D1CMN_ERR((CE_NOTE, "%s: byte returned from device is %x\n",
404 404 unitp->pcf8574_name, byte));
405 405 ioctl_bit.bit_value = (boolean_t)PCF8574_BIT_READ_MASK(byte,
406 406 ioctl_bit.bit_num);
407 407 D1CMN_ERR((CE_NOTE, "%s: byte now contains %x\n",
408 408 unitp->pcf8574_name, byte));
409 409
410 410 if (ddi_copyout((caddr_t)&ioctl_bit, (caddr_t)arg,
411 411 sizeof (i2c_bit_t), mode) != DDI_SUCCESS) {
412 412 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_GET_BIT"
413 413 " ddi_copyout routine\n",
414 414 unitp->pcf8574_name));
415 415 err = EFAULT;
416 416 }
417 417 break;
418 418
419 419 case I2C_SET_BIT:
420 420 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_bit,
421 421 sizeof (i2c_bit_t), mode) != DDI_SUCCESS) {
422 422 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_SET_BIT"
423 423 " ddi_copyin routine\n",
424 424 unitp->pcf8574_name));
425 425 err = EFAULT;
426 426 break;
427 427 }
428 428
429 429 if (ioctl_bit.bit_num > 7) {
430 430 D2CMN_ERR((CE_WARN, "%s: I2C_SET_BIT: bit_num sent"
431 431 " in was not between 0 and 7",
432 432 unitp->pcf8574_name));
433 433 err = EIO;
434 434 break;
435 435 }
436 436
437 437 err = pcf8574_get(unitp, &byte);
438 438 if (err != I2C_SUCCESS) {
439 439 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_BIT"
440 440 " pcf8574_get routine\n",
441 441 unitp->pcf8574_name));
442 442 break;
443 443 }
444 444
445 445 D1CMN_ERR((CE_NOTE, "%s: byte returned from device is %x\n",
446 446 unitp->pcf8574_name, byte));
447 447 byte = PCF8574_BIT_WRITE_MASK(byte, ioctl_bit.bit_num,
448 448 ioctl_bit.bit_value);
449 449 D1CMN_ERR((CE_NOTE, "%s: byte after shifting is %x\n",
450 450 unitp->pcf8574_name, byte));
451 451
452 452 err = pcf8574_set(unitp, byte);
453 453 if (err != I2C_SUCCESS) {
454 454 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_BIT"
455 455 " pcf8574_set routine\n",
456 456 unitp->pcf8574_name));
457 457 break;
458 458 }
459 459 break;
460 460
461 461 default:
462 462 D2CMN_ERR((CE_WARN, "%s: Invalid IOCTL cmd: %x\n",
463 463 unitp->pcf8574_name, cmd));
464 464 err = EINVAL;
465 465 }
466 466
467 467 mutex_exit(&unitp->pcf8574_mutex);
468 468 return (err);
469 469 }
470 470
471 471 static int
472 472 pcf8574_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
473 473 {
474 474 switch (cmd) {
475 475 case DDI_ATTACH:
476 476 return (pcf8574_do_attach(dip));
477 477 case DDI_RESUME:
478 478 return (pcf8574_do_resume());
479 479 default:
480 480 return (DDI_FAILURE);
481 481 }
482 482 }
483 483
484 484 static int
485 485 pcf8574_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
486 486 {
487 487 switch (cmd) {
488 488 case DDI_DETACH:
489 489 return (pcf8574_do_detach(dip));
490 490 case DDI_SUSPEND:
491 491 return (pcf8574_do_suspend());
492 492 default:
493 493 return (DDI_FAILURE);
494 494 }
495 495 }
496 496
497 497 static int
498 498 pcf8574_do_attach(dev_info_t *dip)
499 499 {
500 500 struct pcf8574_unit *unitp;
501 501 int instance, err;
502 502 uint_t len;
503 503 int *regs;
504 504
505 505 instance = ddi_get_instance(dip);
506 506
507 507 if (ddi_soft_state_zalloc(pcf8574soft_statep, instance) != 0) {
508 508 cmn_err(CE_WARN, "%s%d: failed to zalloc softstate\n",
509 509 ddi_get_name(dip), instance);
510 510 return (DDI_FAILURE);
511 511 }
512 512
513 513 unitp = ddi_get_soft_state(pcf8574soft_statep, instance);
514 514
515 515 if (unitp == NULL) {
516 516 cmn_err(CE_WARN, "%s%d: unitp not filled\n",
517 517 ddi_get_name(dip), instance);
518 518 return (ENOMEM);
519 519 }
520 520
521 521 (void) snprintf(unitp->pcf8574_name, sizeof (unitp->pcf8574_name),
522 522 "%s%d", ddi_node_name(dip), instance);
523 523
524 524
525 525 if (ddi_create_minor_node(dip, "pcf8574", S_IFCHR, instance,
526 526 "ddi_i2c:ioexp", NULL) == DDI_FAILURE) {
527 527 cmn_err(CE_WARN, "%s ddi_create_minor_node failed for "
528 528 "%s\n", unitp->pcf8574_name, "pcf8574");
529 529 ddi_soft_state_free(pcf8574soft_statep, instance);
530 530
531 531 return (DDI_FAILURE);
532 532 }
533 533
534 534 if (i2c_client_register(dip, &unitp->pcf8574_hdl) != I2C_SUCCESS) {
535 535 ddi_remove_minor_node(dip, NULL);
536 536 ddi_soft_state_free(pcf8574soft_statep, instance);
537 537
538 538 return (DDI_FAILURE);
539 539 }
540 540
541 541 err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
542 542 DDI_PROP_DONTPASS,
543 543 "reg", (int **)®s, &len);
544 544 if (err != DDI_PROP_SUCCESS) {
545 545 return (DDI_FAILURE);
↓ open down ↓ |
545 lines elided |
↑ open up ↑ |
546 546 }
547 547
548 548 /*
549 549 * regs[0] contains the bus number and regs[1] contains the device
550 550 * address of the i2c device. 0x7c is the device address of the
551 551 * i2c device from which the key switch position is read.
552 552 */
553 553 if (regs[0] == 0 && regs[1] == 0x7c) {
554 554 abort_seq_handler = littleneck_abort_seq_handler;
555 555 keypoll_timeout_hz =
556 - drv_usectohz(LNECK_KEY_POLL_INTVL * MICROSEC);
556 + drv_sectohz(LNECK_KEY_POLL_INTVL);
557 557 littleneck_ks_poll(unitp);
558 558 }
559 559
560 560 ddi_prop_free(regs);
561 561
562 562 mutex_init(&unitp->pcf8574_mutex, NULL, MUTEX_DRIVER, NULL);
563 563
564 564 return (DDI_SUCCESS);
565 565 }
566 566
567 567 static int
568 568 pcf8574_do_resume()
569 569 {
570 570 int ret = DDI_SUCCESS;
571 571
572 572 return (ret);
573 573 }
574 574
575 575 static int
576 576 pcf8574_do_suspend()
577 577 {
578 578 int ret = DDI_SUCCESS;
579 579
580 580 return (ret);
581 581 }
582 582
583 583 static int
584 584 pcf8574_do_detach(dev_info_t *dip)
585 585 {
586 586 struct pcf8574_unit *unitp;
587 587 int instance;
588 588
589 589 instance = ddi_get_instance(dip);
590 590
591 591 unitp = ddi_get_soft_state(pcf8574soft_statep, instance);
592 592
593 593 if (unitp == NULL) {
594 594 cmn_err(CE_WARN, "%s%d: unitp not filled\n",
595 595 ddi_get_name(dip), instance);
596 596 return (ENOMEM);
597 597 }
598 598
599 599 (void) untimeout(keypoll_timeout_id);
600 600
601 601 i2c_client_unregister(unitp->pcf8574_hdl);
602 602
603 603 ddi_remove_minor_node(dip, NULL);
604 604
605 605 mutex_destroy(&unitp->pcf8574_mutex);
606 606
607 607 ddi_soft_state_free(pcf8574soft_statep, instance);
608 608
609 609 return (DDI_SUCCESS);
610 610
611 611 }
612 612
613 613 static void
614 614 littleneck_ks_poll(void *arg)
615 615 {
616 616 struct pcf8574_unit *unitp = (struct pcf8574_unit *)arg;
617 617 uint8_t byte;
618 618
619 619 mutex_enter(&unitp->pcf8574_mutex);
620 620
621 621 if (pcf8574_get(unitp, &byte) != I2C_SUCCESS) {
622 622 D2CMN_ERR((CE_WARN, "%s: Failed in littleneck_ks_poll"
623 623 " pcf8574_get routine\n", unitp->pcf8574_name));
624 624 mutex_exit(&unitp->pcf8574_mutex);
625 625 return;
626 626 }
627 627
628 628 /*
629 629 * 5th bit in the byte is the key LOCKED position
630 630 */
631 631 key_locked_bit = (boolean_t)PCF8574_BIT_READ_MASK(byte,
632 632 LNECK_KEY_POLL_BIT);
633 633
634 634 keypoll_timeout_id = (timeout(littleneck_ks_poll,
635 635 (caddr_t)unitp, keypoll_timeout_hz));
636 636
637 637 mutex_exit(&unitp->pcf8574_mutex);
638 638 }
639 639
640 640 static void
641 641 littleneck_abort_seq_handler(char *msg)
642 642 {
643 643
644 644 if (key_locked_bit == 0)
645 645 cmn_err(CE_CONT, "KEY in LOCKED position, "
646 646 "ignoring debug enter sequence\n");
647 647 else {
648 648 D1CMN_ERR((CE_CONT, "debug enter sequence \n"));
649 649 debug_enter(msg);
650 650 }
651 651 }
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX