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