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 }