xref: /titanic_41/usr/src/uts/sun4u/montecarlo/io/pcf8591_nct.c (revision 88447a05f537aabe9a1bc3d5313f22581ec992a7)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 
28 
29 
30 /*
31  * I2C leaf driver for the PCF8591
32  */
33 
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/signal.h>
37 #include <sys/errno.h>
38 #include <sys/file.h>
39 #include <sys/termio.h>
40 #include <sys/termios.h>
41 #include <sys/cmn_err.h>
42 #include <sys/stream.h>
43 #include <sys/strsun.h>
44 #include <sys/stropts.h>
45 #include <sys/strtty.h>
46 #include <sys/debug.h>
47 #include <sys/eucioctl.h>
48 #include <sys/cred.h>
49 #include <sys/uio.h>
50 #include <sys/stat.h>
51 #include <sys/kmem.h>
52 
53 #include <sys/ddi.h>
54 #include <sys/sunddi.h>
55 #include <sys/obpdefs.h>
56 #include <sys/conf.h>
57 #include <sys/modctl.h>
58 #include <sys/stat.h>
59 #include <sys/open.h>
60 #include <sys/uio.h>
61 
62 #include <sys/i2c/misc/i2c_svc.h>
63 #include <sys/envctrl_gen.h>
64 #include <sys/netract_gen.h>
65 #include <sys/pcf8591_nct.h>
66 
67 
68 /*
69  * 		CONTROL OF CHIP
70  * PCF8591 Temp sensing control register definitions
71  *
72  * ---------------------------------------------
73  * | 0 | AOE | X | X | 0 | AIF | X | X |
74  * ---------------------------------------------
75  * AOE = Analog out enable.. not used on out implementation
76  * 5 & 4 = Analog Input Programming.. see data sheet for bits..
77  *
78  * AIF = Auto increment flag
79  * bits 1 & 0 are for the Chennel number.
80  */
81 
82 
83 #define	I2CTRANS_DATA	0
84 #define	I2CRAW_DATA	1
85 #define	TEMP_TABLE_SIZE	256
86 
87 #define	SHUTDOWN_TEMP_MIN	55
88 #define	SHUTDOWN_TEMP_MAX	85
89 
90 #ifdef DEBUG
91 #define	dbg_print(level, str) cmn_err(level, str);
92 #else
93 #define	dbg_print(level, str) {; }
94 #endif
95 
96 
97 extern int nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran);
98 static uchar_t _cpu_temps[TEMP_TABLE_SIZE + 4];	/* see attach */
99 
100 static void *pcf8591_soft_statep;
101 
102 /*
103  * cb ops (only need ioctl)
104  */
105 static int pcf8591_open(dev_t *, int, int, cred_t *);
106 static int pcf8591_close(dev_t, int, int, cred_t *);
107 static int pcf8591_read(dev_t dev, struct uio *uiop, cred_t *cred_p);
108 static int pcf8591_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
109 
110 static struct cb_ops pcf8591_cbops = {
111 	pcf8591_open,			/* open */
112 	pcf8591_close,			/* close */
113 	nodev,				/* strategy */
114 	nodev,				/* print */
115 	nodev,				/* dump */
116 	pcf8591_read,			/* read */
117 	nodev,				/* write */
118 	pcf8591_ioctl,			/* ioctl */
119 	nodev,				/* devmap */
120 	nodev,				/* mmap */
121 	nodev,				/* segmap */
122 	nochpoll,			/* poll */
123 	ddi_prop_op,			/* cb_prop_op */
124 	NULL,				/* streamtab */
125 	D_NEW | D_MP | D_HOTPLUG,	/* Driver compatibility flag */
126 	CB_REV,				/* rev */
127 	nodev,				/* int (*cb_aread)() */
128 	nodev				/* int (*cb_awrite)() */
129 };
130 
131 /*
132  * dev ops
133  */
134 static int pcf8591_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
135 		void **result);
136 static int pcf8591_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
137 static int pcf8591_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
138 
139 /* kstat routines */
140 static int pcf8591_add_kstats(struct pcf8591_unit *);
141 static void pcf8591_delete_kstats(struct pcf8591_unit *);
142 static int pcf8591_temp_kstat_update(kstat_t *, int);
143 static int pcf8591_read_chip(struct pcf8591_unit *, uint8_t, int);
144 static int pcf8591_read_props(struct pcf8591_unit *unitp);
145 
146 static struct dev_ops pcf8591_ops = {
147 	DEVO_REV,
148 	0,
149 	pcf8591_info,
150 	nulldev,
151 	nulldev,
152 	pcf8591_attach,
153 	pcf8591_detach,
154 	nodev,
155 	&pcf8591_cbops,
156 	NULL,
157 	NULL,
158 	ddi_quiesce_not_supported,	/* devo_quiesce */
159 };
160 
161 extern struct mod_ops mod_driverops;
162 
163 static struct modldrv pcf8591_modldrv = {
164 	&mod_driverops,		/* type of module - driver */
165 	"Netract pcf8591 (adio)",
166 	&pcf8591_ops,
167 };
168 
169 static struct modlinkage pcf8591_modlinkage = {
170 	MODREV_1,
171 	&pcf8591_modldrv,
172 	0
173 };
174 
175 char	_depends_on[] = "misc/i2c_svc";
176 
177 int	pcf8591_debug = 0x02;
178 static uint8_t translate_cputemp(uint8_t value);
179 
180 int
181 _init(void)
182 {
183 	register int    error;
184 
185 	error = mod_install(&pcf8591_modlinkage);
186 	if (error == 0) {
187 		(void) ddi_soft_state_init(&pcf8591_soft_statep,
188 		    sizeof (struct pcf8591_unit), PCF8591_MAX_DEVS);
189 	}
190 
191 	return (error);
192 }
193 
194 int
195 _fini(void)
196 {
197 	register int    error;
198 
199 	error = mod_remove(&pcf8591_modlinkage);
200 	if (error == 0) {
201 		ddi_soft_state_fini(&pcf8591_soft_statep);
202 	}
203 
204 	return (error);
205 }
206 
207 int
208 _info(struct modinfo *modinfop)
209 {
210 	return (mod_info(&pcf8591_modlinkage, modinfop));
211 }
212 
213 /*ARGSUSED*/
214 static int
215 pcf8591_open(dev_t *devp, int flags, int otyp, cred_t *credp)
216 {
217 	int err = 0;
218 	struct pcf8591_unit *unitp;
219 	minor_t minor = getminor(*devp);
220 
221 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
222 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
223 
224 	if (instance < 0) {
225 		return (ENXIO);
226 	}
227 
228 	unitp = (struct pcf8591_unit *)
229 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
230 
231 	if (unitp == NULL) {
232 		return (ENXIO);
233 	}
234 
235 	if (otyp != OTYP_CHR) {
236 		return (EINVAL);
237 	}
238 
239 	mutex_enter(&unitp->umutex);
240 
241 	if (flags & FEXCL) {
242 		if (unitp->pcf8591_oflag[channel] != 0) {
243 			err = EBUSY;
244 		} else {
245 			unitp->pcf8591_oflag[channel] = FEXCL;
246 		}
247 	} else {
248 		if (unitp->pcf8591_oflag[channel] == FEXCL) {
249 			err = EBUSY;
250 		} else {
251 			unitp->pcf8591_oflag[channel] = FOPEN;
252 		}
253 	}
254 
255 	mutex_exit(&unitp->umutex);
256 
257 	return (err);
258 }
259 
260 /*ARGSUSED*/
261 static int
262 pcf8591_close(dev_t devp, int flags, int otyp, cred_t *credp)
263 {
264 	struct pcf8591_unit *unitp;
265 	minor_t minor = getminor(devp);
266 
267 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
268 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
269 
270 #ifdef lint
271 	flags = flags;
272 	otyp = otyp;
273 #endif
274 
275 	if (instance < 0) {
276 		return (ENXIO);
277 	}
278 
279 	unitp = (struct pcf8591_unit *)
280 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
281 
282 	if (unitp == NULL) {
283 		return (ENXIO);
284 	}
285 
286 	mutex_enter(&unitp->umutex);
287 
288 	unitp->pcf8591_oflag[channel] = 0;
289 
290 	mutex_exit(&unitp->umutex);
291 
292 	return (DDI_SUCCESS);
293 }
294 
295 static int
296 pcf8591_io(dev_t dev, struct uio *uiop, int rw)
297 {
298 	int err = 0;
299 	struct pcf8591_unit *unitp;
300 	minor_t minor = getminor(dev);
301 
302 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
303 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
304 
305 	int		bytes_to_rw;
306 	int		translate = 0;
307 
308 	/*
309 	 * At this point we don't have a write operation to pcf8591.
310 	 */
311 	if (rw == B_WRITE) {
312 		return (EACCES);
313 	}
314 
315 	if (instance < 0) {
316 		return (ENXIO);
317 	}
318 
319 	unitp = (struct pcf8591_unit *)
320 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
321 	if (unitp == NULL) {
322 		return (ENXIO);
323 	}
324 
325 	if ((bytes_to_rw = uiop->uio_resid) > PCF8591_TRAN_SIZE) {
326 		return (EINVAL);
327 	}
328 
329 	/*
330 	 * Need to serialize all read operations, since there is a single
331 	 * i2c_transfer_t structure allocated for all read and write ops.
332 	 * We can't share the i2c bus among multiple transactions anyway,
333 	 * so this does not affect performance.
334 	 */
335 	mutex_enter(&unitp->umutex);
336 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
337 		if (cv_wait_sig(&unitp->pcf8591_cv, &unitp->umutex) <= 0) {
338 			mutex_exit(&unitp->umutex);
339 
340 			return (EINTR);
341 		}
342 	}
343 	unitp->pcf8591_flags = PCF8591_BUSY;
344 	mutex_exit(&unitp->umutex);
345 
346 	if (bytes_to_rw == 1)
347 		translate = 1;
348 	/*
349 	 * Event sequence:
350 	 * 1. set up the control register write, for now we'll always read
351 	 *    channel 0, which is the only active 8591 port on the Nordica
352 	 *    TODO: We'll need a minor node for each port that is used.
353 	 * 2. increment read count to read the throw-away byte
354 	 * 3. start the write/read of control/data registers
355 	 * 4. throw the first byte away
356 	 * 5. then return the data
357 	 */
358 
359 	unitp->i2c_tran->i2c_flags = I2C_WR_RD;
360 	unitp->i2c_tran->i2c_wlen = 1;
361 	unitp->i2c_tran->i2c_wbuf[0] = (unitp->pcf8591_inprog |
362 	    channel);
363 	/*
364 	 * read extra byte to throw away the first, (PCF8591 datasheet)
365 	 */
366 	unitp->i2c_tran->i2c_rlen = bytes_to_rw + 1;
367 
368 	if (nct_i2c_transfer(unitp->pcf8591_hdl,
369 	    unitp->i2c_tran) != I2C_SUCCESS) {
370 		err = EIO;
371 	} else {
372 		/*
373 		 * Throw away the first byte according to PCF8591 datasheet
374 		 * If translating, use the second byte.
375 		 */
376 		if (translate) {
377 			unitp->i2c_tran->i2c_rbuf[0] =
378 			    translate_cputemp(unitp->i2c_tran->i2c_rbuf[1]);
379 		} else {
380 			unitp->i2c_tran->i2c_rbuf[0] =
381 			    unitp->i2c_tran->i2c_rbuf[1];
382 			unitp->i2c_tran->i2c_rbuf[1] = 0;
383 		}
384 
385 		err = uiomove(unitp->i2c_tran->i2c_rbuf,
386 		    bytes_to_rw,
387 		    UIO_READ,
388 		    uiop);
389 	}
390 	mutex_enter(&unitp->umutex);
391 	unitp->pcf8591_flags = 0;
392 	cv_signal(&unitp->pcf8591_cv);
393 	mutex_exit(&unitp->umutex);
394 
395 	return (err);
396 }
397 
398 /*ARGSUSED*/
399 static int
400 pcf8591_read(dev_t dev, struct uio *uiop, cred_t *cred_p)
401 {
402 	return (pcf8591_io(dev, uiop, B_READ));
403 }
404 
405 static int
406 call_copyin(caddr_t arg, struct pcf8591_unit *unitp, int mode)
407 {
408 	uchar_t *wbuf;
409 	uchar_t *rbuf;
410 	i2c_transfer_t i2ct;
411 	i2c_transfer_t *i2ctp = unitp->i2c_tran;
412 
413 
414 	if (ddi_copyin((void *)arg, (caddr_t)&i2ct,
415 	    sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) {
416 		return (I2C_FAILURE);
417 	}
418 
419 	/*
420 	 * Save the read and write buffer pointers in the transfer
421 	 * structure, otherwise these will get overwritten when we
422 	 * do a bcopy. Restore once done.
423 	 */
424 
425 	wbuf = i2ctp->i2c_wbuf;
426 	rbuf = i2ctp->i2c_rbuf;
427 
428 	bcopy(&i2ct, i2ctp, sizeof (i2c_transfer_t));
429 
430 	i2ctp->i2c_wbuf = wbuf;
431 	i2ctp->i2c_rbuf = rbuf;
432 
433 	/*
434 	 * copyin the read and write buffers to the saved buffers.
435 	 */
436 
437 	if (i2ct.i2c_wlen != 0) {
438 		if (ddi_copyin(i2ct.i2c_wbuf, (caddr_t)i2ctp->i2c_wbuf,
439 		    i2ct.i2c_wlen, mode) != DDI_SUCCESS) {
440 				return (I2C_FAILURE);
441 			}
442 		}
443 
444 	return (I2C_SUCCESS);
445 }
446 
447 static int
448 call_copyout(caddr_t arg, struct pcf8591_unit *unitp, int mode)
449 {
450 	i2c_transfer_t i2ct;
451 	i2c_transfer_t *i2ctp = unitp->i2c_tran;
452 	uint16_t  i2c_actlen;
453 
454 	/*
455 	 * We will copyout the last three fields only, skipping
456 	 * the remaining ones, before copying the rbuf to the
457 	 * user buffer.
458 	 */
459 
460 	int uskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t),
461 	    kskip = sizeof (i2c_transfer_t) - 3*sizeof (int16_t);
462 
463 	/*
464 	 * First copyin the user structure to the temporary i2ct,
465 	 * so that we have the wbuf and rbuf addresses in it.
466 	 */
467 
468 	uskip = sizeof (i2c_transfer_t) - 3 * (sizeof (uint16_t));
469 
470 	/*
471 	 * copyout the last three out fields now.
472 	 */
473 
474 	if (ddi_copyout((void *)((intptr_t)i2ctp+kskip), (void *)
475 	    ((intptr_t)arg + uskip), 3*sizeof (uint16_t), mode)
476 	    != DDI_SUCCESS) {
477 		return (I2C_FAILURE);
478 		}
479 
480 	/*
481 	 * In case we have something to write, get the address of the read
482 	 * buffer.
483 	 */
484 
485 	if (i2ctp->i2c_rlen - i2ctp->i2c_r_resid > 0) {
486 
487 	if (ddi_copyin((void *)arg, &i2ct,
488 	    sizeof (i2c_transfer_t), mode) != DDI_SUCCESS) {
489 		return (I2C_FAILURE);
490 	}
491 
492 	/*
493 	 * copyout the read buffer to the saved user buffer in i2ct.
494 	 */
495 
496 		i2c_actlen = i2ctp->i2c_rlen - i2ctp->i2c_r_resid;
497 		if (ddi_copyout(i2ctp->i2c_rbuf, i2ct.i2c_rbuf,
498 		    i2c_actlen, mode) != DDI_SUCCESS) {
499 				return (I2C_FAILURE);
500 			}
501 		}
502 
503 	return (I2C_SUCCESS);
504 }
505 
506 /*
507  * The ioctls will use the same name as the Javelin ioctls. We
508  * will have a very restricted set for MC, and unlike Javelin
509  * will not have a envctrl_chip structure to return values
510  * from the driver. All we will have is a uint8_t value to
511  * get or set values from the driver. Also, unlike the Javelin,
512  * where 'index' is used to specify the input port from where
513  * temperature is collected, here different minor nodes will be
514  * created by the driver for each port, eliminating the need for
515  * 'index' - leaving us with only the value to pass.
516  */
517 
518 /*ARGSUSED*/
519 static int
520 pcf8591_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
521 		cred_t *credp, int *rvalp)
522 {
523 	int err = 0;
524 	struct pcf8591_unit *unitp;
525 	minor_t minor = getminor(dev);
526 
527 	int instance = PCF8591_MINOR_TO_DEVINST(minor);
528 	int channel = PCF8591_MINOR_TO_CHANNEL(minor);
529 
530 	unitp = (struct pcf8591_unit *)
531 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
532 
533 	mutex_enter(&unitp->umutex);
534 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
535 		if (cv_wait_sig(&unitp->pcf8591_cv, &unitp->umutex) <= 0) {
536 			mutex_exit(&unitp->umutex);
537 
538 			return (EINTR);
539 		}
540 	}
541 	unitp->pcf8591_flags = PCF8591_BUSY;
542 	mutex_exit(&unitp->umutex);
543 
544 	switch (cmd) {
545 
546 	case ENVC_IOC_GETTEMP: {
547 		/*
548 		 * Read the status byte from pcf8591 chip. The value will
549 		 * be already converted to Celcius by translate_cputemp.
550 		 */
551 		pcf8591_read_chip(unitp, channel, 1);
552 		if (ddi_copyout(unitp->i2c_tran->i2c_rbuf,
553 		    (caddr_t)arg, sizeof (uint8_t), mode) != DDI_SUCCESS) {
554 			err = EFAULT;
555 		}
556 		break;
557 	}
558 
559 	case ENVC_IOC_GETMODE: {
560 		uint8_t curr_mode = unitp->current_mode;
561 
562 		if (ddi_copyout((caddr_t)&curr_mode, (caddr_t)arg,
563 		    sizeof (uint8_t), mode) != DDI_SUCCESS) {
564 			err = EFAULT;
565 		}
566 		break;
567 	}
568 
569 	case ENVC_IOC_SETMODE: {
570 		uint8_t curr_mode;
571 		if (ddi_copyin((caddr_t)arg, (caddr_t)&curr_mode,
572 		    sizeof (uint8_t), mode) != DDI_SUCCESS) {
573 				err = EFAULT;
574 				break;
575 		}
576 		if (curr_mode == ENVCTRL_DIAG_MODE ||
577 		    curr_mode == ENVCTRL_NORMAL_MODE) {
578 			unitp->current_mode = curr_mode; /* Don't do anything */
579 		}
580 		break;
581 	}
582 
583 	/* Testing, may be removed */
584 	case I2CDEV_TRAN:
585 		if (call_copyin((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
586 			err = EFAULT;
587 			break;
588 		}
589 		if (nct_i2c_transfer(unitp->pcf8591_hdl, unitp->i2c_tran)
590 		    != I2C_SUCCESS) {
591 			err = EFAULT;
592 			break;
593 		}
594 		if (call_copyout((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
595 			err = EFAULT;
596 			break;
597 		}
598 		break;
599 
600 	/*
601 	 * TESTING TRANSLATION from "adc" "table" property
602 	 * translate thermistor index into temp Celcius
603 	 */
604 	case I2CDEV_GETTEMP: {
605 		struct i2c_transfer *tp;
606 		if (call_copyin((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
607 			err = EFAULT;
608 			break;
609 		}
610 		tp = unitp->i2c_tran;
611 		if (tp->i2c_rlen != 1) {
612 			err = EINVAL;
613 			break;
614 		}
615 		/*
616 		 * Throw away the first byte according to PCF8591 datasheet,
617 		 * so read two bytes
618 		 */
619 		tp->i2c_rlen = 2;
620 		if (nct_i2c_transfer(unitp->pcf8591_hdl, unitp->i2c_tran)
621 		    != I2C_SUCCESS) {
622 			err = EFAULT;
623 			break;
624 		}
625 #ifdef DEBUG
626 		if (pcf8591_debug & 0x0010)
627 			cmn_err(CE_NOTE,
628 			    "pcf8591_ioctl: i2c_rlen=%d; "
629 			    "i2c_rbuf[0,1]=0x%x,0x%x\n",
630 			    tp->i2c_rlen, tp->i2c_rbuf[0], tp->i2c_rbuf[1]);
631 #endif /* DEBUG */
632 		/*
633 		 * Throw away the first byte according to PCF8591 datasheet
634 		 */
635 		if ((tp->i2c_rbuf[0] = translate_cputemp(tp->i2c_rbuf[1]))
636 		    == 0) {
637 			err = EINVAL;
638 			break;
639 		}
640 		tp->i2c_rbuf[1] = 0;
641 
642 		if (call_copyout((caddr_t)arg, unitp, mode) != I2C_SUCCESS) {
643 			err = EFAULT;
644 			break;
645 		}
646 		break;
647 	}
648 
649 	case I2CDEV_GETTABLES: {
650 		break;
651 	}
652 	default:
653 		err = EINVAL;
654 	}
655 
656 	mutex_enter(&unitp->umutex);
657 	unitp->pcf8591_flags = 0;
658 	cv_signal(&unitp->pcf8591_cv);
659 	mutex_exit(&unitp->umutex);
660 
661 	return (err);
662 }
663 
664 static int
665 pcf8591_do_detach(dev_info_t *dip)
666 {
667 	register struct pcf8591_unit *unitp;
668 	int instance;
669 	uint_t attach_flag;
670 
671 	instance = ddi_get_instance(dip);
672 	unitp = ddi_get_soft_state(pcf8591_soft_statep, instance);
673 	attach_flag = unitp->attach_flag;
674 
675 	if (attach_flag & PCF8591_KSTAT_INIT) {
676 		pcf8591_delete_kstats(unitp);
677 	}
678 
679 	if (attach_flag & PCF8591_LOCK_INIT) {
680 		mutex_destroy(&unitp->umutex);
681 		cv_destroy(&unitp->pcf8591_cv);
682 	}
683 
684 	/*
685 	 * Restore the lengths of the rbuf and wbuf, which was originally
686 	 * allocated so that the appropriate amount of rbuf and wbuf are
687 	 * freed.
688 	 */
689 	if (attach_flag & PCF8591_ALLOC_TRANSFER) {
690 		unitp->i2c_tran->i2c_wlen = MAX_WLEN;
691 		unitp->i2c_tran->i2c_rlen = MAX_RLEN;
692 		i2c_transfer_free(unitp->pcf8591_hdl, unitp->i2c_tran);
693 	}
694 
695 	if (attach_flag & PCF8591_REGISTER_CLIENT) {
696 		i2c_client_unregister(unitp->pcf8591_hdl);
697 	}
698 
699 	if (attach_flag & PCF8591_MINORS_CREATED) {
700 		ddi_remove_minor_node(dip, NULL);
701 	}
702 
703 	/*
704 	 * Free the memory allocated for the properties.
705 	 */
706 	if (attach_flag & PCF8591_PROPS_READ) {
707 		ddi_prop_free(unitp->props.name);
708 		if (unitp->props.num_chans_used) {
709 			ddi_prop_free(unitp->props.channels_in_use);
710 		}
711 
712 		if (unitp->props.channels_description) {
713 			ddi_prop_free(unitp->props.channels_description);
714 		}
715 	}
716 
717 	if (attach_flag & PCF8591_SOFT_STATE_ALLOC) {
718 		ddi_soft_state_free(pcf8591_soft_statep, instance);
719 	}
720 
721 	return (DDI_SUCCESS);
722 }
723 
724 static int
725 pcf8591_do_suspend(dev_info_t *dip)
726 {
727 	int instance = ddi_get_instance(dip);
728 	struct pcf8591_unit *unitp = (struct pcf8591_unit *)
729 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
730 
731 	if (unitp == NULL) {
732 		return (ENXIO);
733 	}
734 
735 	/*
736 	 * Set the busy flag so that future transactions block
737 	 * until resume.
738 	 */
739 	mutex_enter(&unitp->umutex);
740 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
741 		if (cv_wait_sig(&unitp->pcf8591_cv,
742 		    &unitp->umutex) <= 0) {
743 			mutex_exit(&unitp->umutex);
744 
745 			return (DDI_FAILURE);
746 		}
747 	}
748 	unitp->pcf8591_flags = PCF8591_BUSY;
749 	mutex_exit(&unitp->umutex);
750 
751 	return (DDI_SUCCESS);
752 }
753 
754 static int
755 pcf8591_do_resume(dev_info_t *dip)
756 {
757 	int instance = ddi_get_instance(dip);
758 	struct pcf8591_unit *unitp = (struct pcf8591_unit *)
759 	    ddi_get_soft_state(pcf8591_soft_statep, instance);
760 	if (unitp == NULL) {
761 		return (ENXIO);
762 	}
763 
764 	mutex_enter(&unitp->umutex);
765 	unitp->pcf8591_flags = 0;
766 	cv_signal(&unitp->pcf8591_cv);
767 	mutex_exit(&unitp->umutex);
768 
769 	return (DDI_SUCCESS);
770 }
771 
772 static int
773 pcf8591_do_attach(dev_info_t *dip)
774 {
775 	register struct pcf8591_unit *unitp;
776 	int i, instance;
777 	char name[MAXNAMELEN];
778 	minor_t minor;
779 
780 	instance = ddi_get_instance(dip);
781 
782 	if (ddi_soft_state_zalloc(pcf8591_soft_statep, instance) != 0) {
783 		return (DDI_FAILURE);
784 	}
785 
786 	unitp = ddi_get_soft_state(pcf8591_soft_statep, instance);
787 
788 	if (unitp == NULL) {
789 		return (DDI_FAILURE);
790 	}
791 
792 	unitp->dip = dip;
793 
794 	unitp->attach_flag = PCF8591_SOFT_STATE_ALLOC;
795 
796 	if (pcf8591_read_props(unitp) != DDI_PROP_SUCCESS) {
797 		pcf8591_do_detach(dip);
798 
799 		return (DDI_FAILURE);
800 	}
801 
802 	unitp->attach_flag |= PCF8591_PROPS_READ;
803 
804 	/*
805 	 * Set the current operating mode to NORMAL_MODE.
806 	 */
807 	unitp->current_mode = ENVCTRL_NORMAL_MODE; /* normal mode */
808 
809 	snprintf(unitp->pcf8591_name, PCF8591_NAMELEN,
810 	    "%s%d", ddi_driver_name(dip), instance);
811 
812 	/*
813 	 * Create a minor node corresponding to channel 0 to 3
814 	 */
815 	for (i = 0; i < PCF8591_MAX_CHANS; i++) {
816 	if (i == 0) {
817 		(void) sprintf(name, "cputemp");
818 	} else {
819 		(void) sprintf(name, "%d", i);
820 	}
821 	minor = PCF8591_MINOR_NUM(instance, i);
822 	if (ddi_create_minor_node(dip, name, S_IFCHR, minor,
823 	    PCF8591_NODE_TYPE, NULL) == DDI_FAILURE) {
824 			ddi_remove_minor_node(dip, NULL);
825 			pcf8591_do_detach(dip);
826 
827 			return (DDI_FAILURE);
828 		}
829 	}
830 
831 	unitp->attach_flag |= PCF8591_MINORS_CREATED;
832 
833 	if (i2c_client_register(dip, &unitp->pcf8591_hdl)
834 	    != I2C_SUCCESS) {
835 		pcf8591_do_detach(dip);
836 
837 		return (DDI_FAILURE);
838 	}
839 
840 	unitp->attach_flag |= PCF8591_REGISTER_CLIENT;
841 
842 	/*
843 	 * We allocate a single i2c_transfer_t structure for all
844 	 * i2c transactions.
845 	 */
846 	if (i2c_transfer_alloc(unitp->pcf8591_hdl, &unitp->i2c_tran,
847 	    MAX_WLEN, MAX_RLEN, KM_SLEEP) != I2C_SUCCESS) {
848 		pcf8591_do_detach(dip);
849 
850 		return (DDI_FAILURE);
851 	}
852 
853 	unitp->attach_flag |= PCF8591_ALLOC_TRANSFER;
854 
855 	/*
856 	 * The flags will be set to I2C_WR because for all reads from
857 	 * the 8591 we need to also write the control byte.
858 	 */
859 	unitp->i2c_tran->i2c_flags = I2C_WR;
860 	unitp->i2c_tran->i2c_version = I2C_XFER_REV;
861 
862 
863 	/*
864 	 * Set the analog programming mode to default. Upper nibble
865 	 * in control byte. Four single ended inputs, output not enabled.
866 	 */
867 	unitp->pcf8591_inprog = PCF8591_4SINGLE | PCF8591_ANALOG_INPUT_EN;
868 
869 	/*
870 	 * Set the open flag for each channel to 0.
871 	 */
872 	for (i = 0; i < PCF8591_MAX_CHANS; i++) {
873 		unitp->pcf8591_oflag[i] = 0;
874 	}
875 
876 	/*
877 	 * Set the busy flag to 0.
878 	 */
879 	unitp->pcf8591_flags = 0;
880 
881 	mutex_init(&unitp->umutex, NULL, MUTEX_DRIVER, NULL);
882 	cv_init(&unitp->pcf8591_cv, NULL, CV_DRIVER, NULL);
883 
884 	unitp->attach_flag |= PCF8591_LOCK_INIT;
885 
886 	if (pcf8591_add_kstats(unitp) != DDI_SUCCESS) {
887 		pcf8591_do_detach(dip);
888 
889 		return (DDI_FAILURE);
890 	}
891 
892 	unitp->attach_flag |= PCF8591_KSTAT_INIT;
893 
894 	ddi_report_dev(dip);
895 
896 	return (DDI_SUCCESS);
897 }
898 
899 /* ARGSUSED */
900 static int
901 pcf8591_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
902 {
903 	dev_t	dev;
904 	int	instance;
905 
906 	if (infocmd == DDI_INFO_DEVT2INSTANCE) {
907 		dev = (dev_t)arg;
908 		instance = PCF8591_MINOR_TO_DEVINST(getminor(dev));
909 		*result = (void *)(uintptr_t)instance;
910 		return (DDI_SUCCESS);
911 	}
912 	return (DDI_FAILURE);
913 }
914 
915 static int
916 pcf8591_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
917 {
918 	switch (cmd) {
919 	case DDI_ATTACH:
920 		return (pcf8591_do_attach(dip));
921 	case DDI_RESUME:
922 		return (pcf8591_do_resume(dip));
923 	default:
924 		return (DDI_FAILURE);
925 	}
926 }
927 
928 static int
929 pcf8591_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
930 {
931 	switch (cmd) {
932 	case DDI_DETACH:
933 		return (pcf8591_do_detach(dip));
934 	case DDI_SUSPEND:
935 		return (pcf8591_do_suspend(dip));
936 	default:
937 		return (DDI_FAILURE);
938 	}
939 }
940 
941 static uint8_t
942 translate_cputemp(uint8_t value)
943 {
944 	return (_cpu_temps[value]);
945 }
946 
947 static int
948 pcf8591_add_kstats(struct pcf8591_unit *unitp)
949 {
950 	if ((unitp->tempksp = kstat_create(I2C_PCF8591_NAME,
951 	    unitp->instance, I2C_KSTAT_CPUTEMP, "misc",
952 	    KSTAT_TYPE_RAW, sizeof (unitp->temp_kstats),
953 	    KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) {
954 
955 		return (DDI_FAILURE);
956 	}
957 
958 	/*
959 	 * The kstat fields are already initialized in the attach routine..
960 	 */
961 
962 	unitp->tempksp->ks_update = pcf8591_temp_kstat_update;
963 	unitp->tempksp->ks_private = (void *)unitp;
964 
965 	strcpy(unitp->temp_kstats.label,
966 	    unitp->props.channels_description[0]);
967 	unitp->temp_kstats.type = ENVC_NETRACT_CPU_SENSOR;
968 
969 	kstat_install(unitp->tempksp);
970 
971 	return (DDI_SUCCESS);
972 }
973 
974 static void
975 pcf8591_delete_kstats(struct pcf8591_unit *unitp)
976 {
977 	kstat_delete(unitp->tempksp);
978 }
979 
980 static int
981 pcf8591_temp_kstat_update(kstat_t *ksp, int rw)
982 {
983 	struct pcf8591_unit *unitp;
984 	char *kstatp;
985 	int err = 0;
986 	int channel = 0;
987 	int warn_temp = 0;
988 	int shutdown_temp = 0;
989 
990 	unitp = (struct pcf8591_unit *)ksp->ks_private;
991 
992 	mutex_enter(&unitp->umutex);
993 	while (unitp->pcf8591_flags == PCF8591_BUSY) {
994 		if (cv_wait_sig(&unitp->pcf8591_cv,
995 		    &unitp->umutex) <= 0) {
996 			mutex_exit(&unitp->umutex);
997 
998 			return (EINTR);
999 		}
1000 	}
1001 
1002 	unitp->pcf8591_flags = PCF8591_BUSY;
1003 	mutex_exit(&unitp->umutex);
1004 
1005 	kstatp = (char *)ksp->ks_data;
1006 
1007 	if (rw == KSTAT_WRITE) {
1008 
1009 		/* check for the size of buffer */
1010 		if (ksp->ks_data_size != sizeof (unitp->temp_kstats)) {
1011 			err = EIO;
1012 			goto bail;
1013 		}
1014 
1015 		warn_temp = ((envctrl_temp_t *)kstatp)->warning_threshold;
1016 		shutdown_temp = ((envctrl_temp_t *)kstatp)->shutdown_threshold;
1017 
1018 		if (shutdown_temp < SHUTDOWN_TEMP_MIN || shutdown_temp >
1019 		    SHUTDOWN_TEMP_MAX) {
1020 			err = EIO;
1021 			goto bail;
1022 		}
1023 
1024 		if (warn_temp < 0 || shutdown_temp <= warn_temp) {
1025 			err = EIO;
1026 			goto bail;
1027 		}
1028 
1029 		/* write into kstat fields */
1030 		unitp->temp_kstats.warning_threshold = warn_temp;
1031 		unitp->temp_kstats.shutdown_threshold = shutdown_temp;
1032 
1033 	} else {
1034 
1035 		pcf8591_read_chip(unitp, channel, 1);
1036 		unitp->temp_kstats.value =
1037 		    unitp->i2c_tran->i2c_rbuf[0];
1038 		bcopy((caddr_t)&unitp->temp_kstats, kstatp,
1039 		    sizeof (unitp->temp_kstats));
1040 	}
1041 
1042 bail:
1043 
1044 	mutex_enter(&unitp->umutex);
1045 	unitp->pcf8591_flags = 0;
1046 	cv_signal(&unitp->pcf8591_cv);
1047 	mutex_exit(&unitp->umutex);
1048 
1049 	return (err);
1050 }
1051 
1052 static int
1053 pcf8591_read_chip(struct pcf8591_unit *unitp, uint8_t channel,
1054 int size)
1055 {
1056 	int retval = I2C_SUCCESS;
1057 
1058 	/*
1059 	 * We need to read an extra byte, since as per specification
1060 	 * the first byte read should be discarded.
1061 	 */
1062 	i2c_transfer_t *tp = unitp->i2c_tran;
1063 	tp->i2c_flags = I2C_WR_RD;
1064 	tp->i2c_rlen = size+1;
1065 	tp->i2c_wlen = 1;
1066 	tp->i2c_wbuf[0] = (unitp->pcf8591_inprog |
1067 	    channel);
1068 
1069 	retval = nct_i2c_transfer(unitp->pcf8591_hdl, tp);
1070 	if (retval == I2C_SUCCESS) {
1071 		tp->i2c_rbuf[0] = translate_cputemp(tp->i2c_rbuf[1]);
1072 	}
1073 
1074 	if (tp->i2c_rbuf[0] == 0) {
1075 		retval = I2C_FAILURE;
1076 	}
1077 
1078 	return (retval);
1079 }
1080 
1081 /*
1082  * Reads the properties of the pcf8591 device.
1083  */
1084 static int
1085 pcf8591_read_props(struct pcf8591_unit *unitp)
1086 {
1087 	dev_info_t *dip = unitp->dip;
1088 	int i, retval = 0, prop_len;
1089 	int instance = ddi_get_instance(dip);
1090 	int warning_temp, shutdown_temp;
1091 	uint32_t *prop_value = NULL;
1092 	uchar_t *creg_prop;
1093 	char *function;
1094 	uint_t		tblsz;
1095 
1096 #ifdef lint
1097 	instance = instance;
1098 #endif
1099 	/*
1100 	 * Check for the pcf8591_function property, and make sure it's
1101 	 * cputemp.
1102 	 */
1103 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1104 	    "pcf8591_function", &function) != DDI_SUCCESS) {
1105 		dbg_print(CE_WARN, "Couldn't find pcf8591_function property");
1106 
1107 		return (DDI_FAILURE);
1108 	}
1109 
1110 	if (strcmp(function, "cputemp") != 0) {
1111 		dbg_print(CE_WARN, "pcf8591_function is not cputemp");
1112 		ddi_prop_free(function);
1113 
1114 		return (DDI_FAILURE);
1115 	}
1116 
1117 	ddi_prop_free(function);
1118 
1119 	retval = ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1120 	    "name", &unitp->props.name);
1121 	if (retval != DDI_PROP_SUCCESS) {
1122 
1123 		return (retval);
1124 	}
1125 #ifdef DEBUG
1126 	else if (pcf8591_debug & 0x02)
1127 		cmn_err(CE_NOTE,
1128 		    "pcf8591_read_props:ddi_prop_lookup_string(%s): \
1129 			found  %s ", "name", unitp->props.name);
1130 #endif /* DEBUG */
1131 
1132 	retval = ddi_getlongprop(DDI_DEV_T_ANY, dip,
1133 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP,
1134 	    "reg", (caddr_t)&prop_value, &prop_len);
1135 	if (retval == DDI_PROP_SUCCESS) {
1136 		unitp->props.i2c_bus		= (uint16_t)prop_value[0];
1137 		unitp->props.slave_address	= (uint16_t)prop_value[1];
1138 		kmem_free(prop_value, prop_len);
1139 #ifdef DEBUG
1140 		if (pcf8591_debug & 0x02)
1141 			cmn_err(CE_NOTE,
1142 			    "pcf8591:ddi_getlongprop(%s) returns %d,"
1143 			    " i2c_bus,slave=0x%x,0x%x",
1144 			    "reg", retval,  unitp->props.i2c_bus,
1145 			    unitp->props.slave_address);
1146 #endif /* DEBUG */
1147 	} else {
1148 		unitp->props.i2c_bus		= (uint16_t)-1;
1149 		unitp->props.slave_address	= (uint16_t)-1;
1150 #ifdef DEBUG
1151 		cmn_err(CE_WARN,
1152 		    "pcf8591_read_props:ddi_getlongprop(%s) returns %d,"
1153 		    " default it to 0x%x:0x%X",
1154 		    "reg", retval,  unitp->props.i2c_bus,
1155 		    unitp->props.slave_address);
1156 #endif /* DEBUG */
1157 	}
1158 	ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
1159 	    "channels-in-use", &prop_len);
1160 	retval = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
1161 	    dip, DDI_PROP_DONTPASS,
1162 	    "channels-in-use",
1163 	    (uchar_t **)&unitp->props.channels_in_use,
1164 	    &unitp->props.num_chans_used);
1165 	if (retval == DDI_PROP_SUCCESS) {
1166 		unitp->props.num_chans_used /= sizeof (pcf8591_channel_t);
1167 	} else {
1168 		unitp->props.num_chans_used = 0;
1169 	}
1170 
1171 #ifdef DEBUG
1172 	if (pcf8591_debug & 0x0002)
1173 		cmn_err(CE_NOTE,
1174 		    "pcf8591_read_props:ddi_prop_lookup_byte_array(%s)"
1175 		    "returns %d\n"
1176 		    "\t\tlength=%d, #elements=%d",
1177 		    "channels-in-use", retval,
1178 		    prop_len, unitp->props.num_chans_used);
1179 #endif /* DEBUG */
1180 
1181 	retval = ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
1182 	    DDI_PROP_DONTPASS, "channels-description",
1183 	    (char ***)&unitp->props.channels_description,
1184 	    (uint_t *)&prop_len);
1185 
1186 	if (retval != DDI_PROP_SUCCESS) {
1187 		prop_len = 0;
1188 		unitp->props.channels_description = NULL;
1189 	}
1190 
1191 #ifdef DEBUG
1192 	if (pcf8591_debug & 0x0002) {
1193 		cmn_err(CE_NOTE,
1194 		    "pcf8591_read_props:ddi_prop_lookup_string_array(%s)"
1195 		    "returns %d, length=%d",
1196 		    "channels-description", retval, prop_len);
1197 		for (i = 0; i < prop_len; ++i) {
1198 			cmn_err(CE_NOTE, "channels-description[%d]=<%s>",
1199 			    i, unitp->props.channels_description[i]);
1200 		}
1201 	}
1202 #endif /* DEBUG */
1203 
1204 	/*
1205 	 * The following code was borrowed from envctrltwo.c
1206 	 * I haven't yet investigated why the copy target is index + 2
1207 	 */
1208 	retval = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
1209 	    DDI_PROP_DONTPASS, "tables", &creg_prop, (uint_t *)&prop_len);
1210 
1211 	if (retval != DDI_PROP_SUCCESS) {
1212 #ifdef DEBUG
1213 		cmn_err(CE_WARN, "%s%d: Unable to read pcf8591 tables property",
1214 		    ddi_get_name(dip), instance);
1215 #endif /* DEBUG */
1216 
1217 		return (DDI_NOT_WELL_FORMED);
1218 	}
1219 
1220 	tblsz = (sizeof (_cpu_temps) / sizeof (uchar_t));
1221 	if (prop_len <= tblsz) {
1222 		for (i = 0; i < prop_len; i++) {
1223 			_cpu_temps[i] = creg_prop[i];
1224 		}
1225 	}
1226 #ifdef DEBUG
1227 	if (pcf8591_debug & 0x0002)
1228 		cmn_err(CE_NOTE, "pcf8591_read_props: _cpu_temps size=%d; "
1229 		    "tables prop_len=%d\n", tblsz, prop_len);
1230 #endif /* DEBUG */
1231 
1232 	ddi_prop_free(creg_prop);
1233 
1234 	/*
1235 	 * Read shutdown temp and warning temp properties.
1236 	 */
1237 	warning_temp = (int)ddi_getprop(DDI_DEV_T_ANY, dip,
1238 	    DDI_PROP_DONTPASS, "warning-temp", PCF8591_WARNING_TEMP);
1239 
1240 	shutdown_temp = (int)ddi_getprop(DDI_DEV_T_ANY, dip,
1241 	    DDI_PROP_DONTPASS, "shutdown-temp", PCF8591_SHUTDOWN_TEMP);
1242 
1243 	/*
1244 	 * Fill up the warning and shutdown temp values in kstat structure.
1245 	 */
1246 	unitp->temp_kstats.warning_threshold = warning_temp;
1247 	unitp->temp_kstats.shutdown_threshold = shutdown_temp;
1248 
1249 	return (DDI_PROP_SUCCESS);
1250 }
1251