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 * The max1617 I2C is a temp acquisition device. As implemented on some 29 * processor modules, it contains both a local and a remote temp. The 30 * local temp measures the ambient (room) temperature, while the remote 31 * sensor is connected to the processor die. There are ioctl's for retrieving 32 * temperatures, and setting temperature alarm ranges. 33 */ 34 35 #include <sys/stat.h> 36 #include <sys/modctl.h> 37 #include <sys/open.h> 38 #include <sys/types.h> 39 #include <sys/kmem.h> 40 #include <sys/ddi.h> 41 #include <sys/sunddi.h> 42 #include <sys/conf.h> 43 #include <sys/file.h> 44 #include <sys/note.h> 45 46 #include <sys/i2c/misc/i2c_svc.h> 47 #include <sys/i2c/clients/i2c_client.h> 48 #include <sys/i2c/clients/max1617.h> 49 #include <sys/i2c/clients/max1617_impl.h> 50 51 /* 52 * cb ops (only need ioctl) 53 */ 54 static int max1617_open(dev_t *, int, int, cred_t *); 55 static int max1617_close(dev_t, int, int, cred_t *); 56 static int max1617_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 57 58 /* 59 * dev ops 60 */ 61 static int max1617_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 62 void **result); 63 static int max1617_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 64 static int max1617_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 65 66 static struct cb_ops max1617_cbops = { 67 max1617_open, /* open */ 68 max1617_close, /* close */ 69 nodev, /* strategy */ 70 nodev, /* print */ 71 nodev, /* dump */ 72 nodev, /* read */ 73 nodev, /* write */ 74 max1617_ioctl, /* ioctl */ 75 nodev, /* devmap */ 76 nodev, /* mmap */ 77 nodev, /* segmap */ 78 nochpoll, /* poll */ 79 ddi_prop_op, /* cb_prop_op */ 80 NULL, /* streamtab */ 81 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 82 CB_REV, /* rev */ 83 nodev, /* int (*cb_aread)() */ 84 nodev /* int (*cb_awrite)() */ 85 }; 86 87 static struct dev_ops max1617_ops = { 88 DEVO_REV, 89 0, 90 max1617_info, 91 nulldev, 92 nulldev, 93 max1617_attach, 94 max1617_detach, 95 nodev, 96 &max1617_cbops, 97 NULL, 98 NULL, 99 ddi_quiesce_not_supported, /* devo_quiesce */ 100 }; 101 102 static struct modldrv max1617_modldrv = { 103 &mod_driverops, /* type of module - driver */ 104 "max1617 device driver", 105 &max1617_ops, 106 }; 107 108 static struct modlinkage max1617_modlinkage = { 109 MODREV_1, 110 &max1617_modldrv, 111 0 112 }; 113 114 static int max1617_debug = 0; 115 116 static void *max1617_soft_statep; 117 118 int 119 _init(void) 120 { 121 int error; 122 123 error = mod_install(&max1617_modlinkage); 124 if (error == 0) { 125 (void) ddi_soft_state_init(&max1617_soft_statep, 126 sizeof (struct max1617_unit), 1); 127 } 128 129 return (error); 130 } 131 132 int 133 _fini(void) 134 { 135 int error; 136 137 error = mod_remove(&max1617_modlinkage); 138 if (error == 0) { 139 ddi_soft_state_fini(&max1617_soft_statep); 140 } 141 142 return (error); 143 } 144 145 int 146 _info(struct modinfo *modinfop) 147 { 148 return (mod_info(&max1617_modlinkage, modinfop)); 149 } 150 151 /* ARGSUSED */ 152 static int 153 max1617_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 154 { 155 dev_t dev; 156 int instance; 157 158 if (infocmd == DDI_INFO_DEVT2INSTANCE) { 159 dev = (dev_t)arg; 160 instance = MAX1617_MINOR_TO_INST(getminor(dev)); 161 *result = (void *)(uintptr_t)instance; 162 return (DDI_SUCCESS); 163 } 164 return (DDI_FAILURE); 165 } 166 167 static int 168 max1617_do_attach(dev_info_t *dip) 169 { 170 struct max1617_unit *unitp; 171 int instance; 172 char minor_name[MAXNAMELEN]; 173 minor_t minor_number; 174 175 instance = ddi_get_instance(dip); 176 177 if (ddi_soft_state_zalloc(max1617_soft_statep, instance) != 0) { 178 cmn_err(CE_WARN, "%s%d: failed to zalloc softstate", 179 ddi_get_name(dip), instance); 180 181 return (DDI_FAILURE); 182 } 183 184 unitp = ddi_get_soft_state(max1617_soft_statep, instance); 185 186 (void) snprintf(unitp->max1617_name, sizeof (unitp->max1617_name), 187 "%s%d", ddi_node_name(dip), instance); 188 189 (void) sprintf(minor_name, "die_temp"); 190 minor_number = MAX1617_INST_TO_MINOR(instance) | 191 MAX1617_FCN_TO_MINOR(MAX1617_CPU_TEMP); 192 193 if (ddi_create_minor_node(dip, minor_name, S_IFCHR, 194 minor_number, MAX1617_NODE_TYPE, 0) == DDI_FAILURE) { 195 cmn_err(CE_WARN, "%s ddi_create_minor_node failed for minor " 196 " name '%s'", unitp->max1617_name, minor_name); 197 ddi_soft_state_free(max1617_soft_statep, instance); 198 199 return (DDI_FAILURE); 200 } 201 202 (void) sprintf(minor_name, "amb_temp"); 203 minor_number = MAX1617_INST_TO_MINOR(instance) | 204 MAX1617_FCN_TO_MINOR(MAX1617_AMB_TEMP); 205 206 if (ddi_create_minor_node(dip, minor_name, S_IFCHR, 207 minor_number, MAX1617_NODE_TYPE, 0) == DDI_FAILURE) { 208 cmn_err(CE_WARN, "%s ddi_create_minor_node failed for %s", 209 unitp->max1617_name, minor_name); 210 ddi_remove_minor_node(dip, NULL); 211 ddi_soft_state_free(max1617_soft_statep, instance); 212 213 return (DDI_FAILURE); 214 } 215 216 if (i2c_client_register(dip, &unitp->max1617_hdl) != I2C_SUCCESS) { 217 ddi_remove_minor_node(dip, NULL); 218 ddi_soft_state_free(max1617_soft_statep, instance); 219 220 return (DDI_FAILURE); 221 } 222 223 mutex_init(&unitp->max1617_mutex, NULL, MUTEX_DRIVER, NULL); 224 cv_init(&unitp->max1617_cv, NULL, CV_DRIVER, NULL); 225 226 return (DDI_SUCCESS); 227 } 228 229 static int 230 max1617_do_resume(dev_info_t *dip) 231 { 232 int ret = DDI_SUCCESS; 233 int instance = ddi_get_instance(dip); 234 i2c_transfer_t *i2ctp; 235 struct max1617_unit *unitp; 236 237 if ((unitp = ddi_get_soft_state(max1617_soft_statep, instance)) == 238 NULL) { 239 return (DDI_FAILURE); 240 } 241 242 (void) i2c_transfer_alloc(unitp->max1617_hdl, 243 &i2ctp, 2, 0, I2C_SLEEP); 244 i2ctp->i2c_version = I2C_XFER_REV; 245 i2ctp->i2c_flags = I2C_WR; 246 247 248 i2ctp->i2c_wbuf[0] = MAX1617_CONFIG_WR_REG; 249 i2ctp->i2c_wbuf[1] = unitp->max1617_cpr_state.max1617_config; 250 251 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 252 ret = DDI_FAILURE; 253 goto done; 254 } 255 256 i2ctp->i2c_wbuf[0] = MAX1617_CONV_RATE_WR_REG; 257 i2ctp->i2c_wbuf[1] = unitp->max1617_cpr_state.max1617_conv_rate; 258 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 259 ret = DDI_FAILURE; 260 goto done; 261 } 262 263 i2ctp->i2c_wbuf[0] = MAX1617_LOCALTEMP_HIGH_WR_REG; 264 i2ctp->i2c_wbuf[1] = unitp->max1617_cpr_state.max1617_lcl_hlimit; 265 266 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 267 ret = DDI_FAILURE; 268 goto done; 269 } 270 271 i2ctp->i2c_wbuf[0] = MAX1617_REMOTETEMP_HIGH_WR_REG; 272 i2ctp->i2c_wbuf[1] = unitp->max1617_cpr_state.max1617_remote_hlimit; 273 274 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 275 ret = DDI_FAILURE; 276 goto done; 277 } 278 279 i2ctp->i2c_wbuf[0] = MAX1617_LOCALTEMP_LOW_REG; 280 i2ctp->i2c_wbuf[1] = unitp->max1617_cpr_state.max1617_lcl_llimit; 281 282 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 283 ret = DDI_FAILURE; 284 goto done; 285 } 286 287 i2ctp->i2c_wbuf[0] = MAX1617_REMOTETEMP_LOW_REG; 288 i2ctp->i2c_wbuf[1] = unitp->max1617_cpr_state.max1617_remote_llimit; 289 290 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 291 ret = DDI_FAILURE; 292 goto done; 293 } 294 295 done: 296 mutex_enter(&unitp->max1617_mutex); 297 unitp->max1617_flags = 0; 298 cv_signal(&unitp->max1617_cv); 299 mutex_exit(&unitp->max1617_mutex); 300 301 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 302 return (ret); 303 } 304 305 static int 306 max1617_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 307 { 308 switch (cmd) { 309 case DDI_ATTACH: 310 311 return (max1617_do_attach(dip)); 312 case DDI_RESUME: 313 314 return (max1617_do_resume(dip)); 315 default: 316 317 return (DDI_FAILURE); 318 } 319 } 320 321 static int 322 max1617_do_detach(dev_info_t *dip) 323 { 324 struct max1617_unit *unitp; 325 int instance; 326 327 instance = ddi_get_instance(dip); 328 329 unitp = ddi_get_soft_state(max1617_soft_statep, instance); 330 331 if (unitp == NULL) { 332 return (DDI_FAILURE); 333 } 334 335 i2c_client_unregister(unitp->max1617_hdl); 336 337 ddi_remove_minor_node(dip, NULL); 338 339 mutex_destroy(&unitp->max1617_mutex); 340 cv_destroy(&unitp->max1617_cv); 341 ddi_soft_state_free(max1617_soft_statep, instance); 342 343 return (DDI_SUCCESS); 344 } 345 346 static int 347 max1617_do_suspend(dev_info_t *dip) 348 { 349 int ret = DDI_SUCCESS; 350 int instance = ddi_get_instance(dip); 351 i2c_transfer_t *i2ctp; 352 struct max1617_unit *unitp; 353 354 if ((unitp = ddi_get_soft_state(max1617_soft_statep, instance)) == 355 NULL) { 356 return (DDI_FAILURE); 357 } 358 359 (void) i2c_transfer_alloc(unitp->max1617_hdl, 360 &i2ctp, 1, 1, I2C_SLEEP); 361 362 363 /* 364 * Block new transactions during CPR 365 */ 366 mutex_enter(&unitp->max1617_mutex); 367 while (unitp->max1617_flags == MAX1617_BUSY) { 368 cv_wait(&unitp->max1617_cv, &unitp->max1617_mutex); 369 } 370 unitp->max1617_flags = MAX1617_BUSY; 371 mutex_exit(&unitp->max1617_mutex); 372 373 i2ctp->i2c_version = I2C_XFER_REV; 374 i2ctp->i2c_flags = I2C_WR_RD; 375 i2ctp->i2c_wbuf[0] = MAX1617_CONFIG_REG; 376 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 377 ret = DDI_FAILURE; 378 goto done; 379 } 380 unitp->max1617_cpr_state.max1617_config = i2ctp->i2c_rbuf[0]; 381 382 i2ctp->i2c_wbuf[0] = MAX1617_CONV_RATE_REG; 383 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 384 ret = DDI_FAILURE; 385 goto done; 386 } 387 unitp->max1617_cpr_state.max1617_conv_rate = i2ctp->i2c_rbuf[0]; 388 389 i2ctp->i2c_wbuf[0] = MAX1617_LOCALTEMP_HIGH_REG; 390 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 391 ret = DDI_FAILURE; 392 goto done; 393 } 394 unitp->max1617_cpr_state.max1617_lcl_hlimit = i2ctp->i2c_rbuf[0]; 395 396 i2ctp->i2c_wbuf[0] = MAX1617_REMOTETEMP_HIGH_REG; 397 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 398 ret = DDI_FAILURE; 399 goto done; 400 } 401 unitp->max1617_cpr_state.max1617_remote_hlimit = i2ctp->i2c_rbuf[0]; 402 403 i2ctp->i2c_wbuf[0] = MAX1617_LOCALTEMP_LOW_REG; 404 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 405 ret = DDI_FAILURE; 406 goto done; 407 } 408 unitp->max1617_cpr_state.max1617_lcl_llimit = i2ctp->i2c_rbuf[0]; 409 410 i2ctp->i2c_wbuf[0] = MAX1617_REMOTETEMP_LOW_REG; 411 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 412 ret = DDI_FAILURE; 413 goto done; 414 } 415 unitp->max1617_cpr_state.max1617_remote_llimit = i2ctp->i2c_rbuf[0]; 416 417 done: 418 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 419 420 if (ret == DDI_FAILURE) { 421 mutex_enter(&unitp->max1617_mutex); 422 unitp->max1617_flags = 0; 423 cv_broadcast(&unitp->max1617_cv); 424 mutex_exit(&unitp->max1617_mutex); 425 } 426 return (ret); 427 } 428 429 static int 430 max1617_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 431 { 432 switch (cmd) { 433 case DDI_DETACH: 434 435 return (max1617_do_detach(dip)); 436 case DDI_SUSPEND: 437 438 return (max1617_do_suspend(dip)); 439 440 default: 441 442 return (DDI_FAILURE); 443 } 444 } 445 446 static int 447 max1617_open(dev_t *devp, int flags, int otyp, cred_t *credp) 448 { 449 _NOTE(ARGUNUSED(credp)) 450 451 struct max1617_unit *unitp; 452 int instance; 453 int err = 0; 454 455 instance = MAX1617_MINOR_TO_INST(getminor(*devp)); 456 457 if (instance < 0) { 458 459 return (ENXIO); 460 } 461 462 unitp = (struct max1617_unit *) 463 ddi_get_soft_state(max1617_soft_statep, instance); 464 465 if (unitp == NULL) { 466 467 return (ENXIO); 468 } 469 470 if (otyp != OTYP_CHR) { 471 472 return (EINVAL); 473 } 474 475 mutex_enter(&unitp->max1617_mutex); 476 477 if (flags & FEXCL) { 478 if (unitp->max1617_oflag != 0) { 479 err = EBUSY; 480 } else { 481 unitp->max1617_oflag = FEXCL; 482 } 483 } else { 484 if (unitp->max1617_oflag == FEXCL) { 485 err = EBUSY; 486 } else { 487 unitp->max1617_oflag = (uint16_t)FOPEN; 488 } 489 } 490 491 done: 492 mutex_exit(&unitp->max1617_mutex); 493 494 return (err); 495 } 496 497 static int 498 max1617_close(dev_t dev, int flags, int otyp, cred_t *credp) 499 { 500 _NOTE(ARGUNUSED(flags, otyp, credp)) 501 502 struct max1617_unit *unitp; 503 int instance = MAX1617_MINOR_TO_INST(getminor(dev)); 504 505 if (instance < 0) { 506 507 return (ENXIO); 508 } 509 510 unitp = (struct max1617_unit *) 511 ddi_get_soft_state(max1617_soft_statep, instance); 512 513 if (unitp == NULL) { 514 515 return (ENXIO); 516 } 517 518 mutex_enter(&unitp->max1617_mutex); 519 520 unitp->max1617_oflag = 0; 521 522 mutex_exit(&unitp->max1617_mutex); 523 524 return (DDI_SUCCESS); 525 } 526 527 int 528 set_temp_limit(struct max1617_unit *unitp, uchar_t device_reg, caddr_t arg, 529 int mode) 530 { 531 int err = 0; 532 i2c_transfer_t *i2ctp; 533 int16_t temp; 534 535 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 2, 0, I2C_SLEEP); 536 i2ctp->i2c_version = I2C_XFER_REV; 537 i2ctp->i2c_flags = I2C_WR; 538 i2ctp->i2c_wbuf[0] = device_reg; 539 540 if (ddi_copyin(arg, (caddr_t)&temp, sizeof (int16_t), mode) != 541 DDI_SUCCESS) { 542 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 543 544 return (EFAULT); 545 } 546 547 i2ctp->i2c_wbuf[1] = (int8_t)temp; 548 549 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 550 err = EIO; 551 } 552 553 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 554 555 return (err); 556 } 557 558 int 559 get_temp_limit(struct max1617_unit *unitp, uchar_t reg, caddr_t arg, int mode) 560 { 561 int err = 0; 562 i2c_transfer_t *i2ctp; 563 int16_t temp16; 564 565 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 1, 1, I2C_SLEEP); 566 i2ctp->i2c_version = I2C_XFER_REV; 567 i2ctp->i2c_flags = I2C_WR_RD; 568 i2ctp->i2c_wbuf[0] = reg; 569 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 570 /* 571 * This double cast is required so that the sign is preserved 572 * when expanding the 8 bit value to 16. 573 */ 574 temp16 = (int16_t)((int8_t)i2ctp->i2c_rbuf[0]); 575 if (ddi_copyout((caddr_t)&temp16, arg, sizeof (int16_t), 576 mode) != DDI_SUCCESS) { 577 err = EFAULT; 578 } 579 } else { 580 err = EIO; 581 } 582 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 583 584 return (err); 585 } 586 587 static int 588 max1617_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 589 cred_t *credp, int *rvalp) 590 { 591 _NOTE(ARGUNUSED(credp, rvalp)) 592 struct max1617_unit *unitp; 593 int err = 0; 594 i2c_transfer_t *i2ctp; 595 int fcn = MAX1617_MINOR_TO_FCN(getminor(dev)); 596 int instance = MAX1617_MINOR_TO_INST(getminor(dev)); 597 uchar_t reg; 598 599 unitp = (struct max1617_unit *) 600 ddi_get_soft_state(max1617_soft_statep, instance); 601 602 if (max1617_debug) { 603 printf("max1617_ioctl: fcn=%d instance=%d\n", fcn, instance); 604 } 605 606 /* 607 * Serialize here, in order to block transacations during CPR. 608 * This is not a bottle neck since i2c_transfer would serialize 609 * anyway. 610 */ 611 mutex_enter(&unitp->max1617_mutex); 612 while (unitp->max1617_flags == MAX1617_BUSY) { 613 if (cv_wait_sig(&unitp->max1617_cv, 614 &unitp->max1617_mutex) <= 0) { 615 mutex_exit(&unitp->max1617_mutex); 616 return (EINTR); 617 } 618 } 619 unitp->max1617_flags = MAX1617_BUSY; 620 mutex_exit(&unitp->max1617_mutex); 621 622 switch (cmd) { 623 624 /* 625 * I2C_GET_TEMPERATURE reads a temperature from the device and 626 * copies a single byte representing the celcius temp 627 * to user space. 628 */ 629 case I2C_GET_TEMPERATURE: 630 switch (fcn) { 631 case MAX1617_AMB_TEMP: 632 reg = MAX1617_LOCAL_TEMP_REG; 633 break; 634 case MAX1617_CPU_TEMP: 635 reg = MAX1617_REMOTE_TEMP_REG; 636 break; 637 default: 638 err = EINVAL; 639 goto done; 640 } 641 642 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 643 1, 1, I2C_SLEEP); 644 i2ctp->i2c_version = I2C_XFER_REV; 645 i2ctp->i2c_flags = I2C_WR_RD; 646 i2ctp->i2c_wbuf[0] = reg; 647 648 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 649 650 /* 651 * This double cast is needed so that the sign bit 652 * is preserved when casting from unsigned char to 653 * signed 16 bit value. 654 */ 655 int16_t temp = (int16_t)((int8_t)i2ctp->i2c_rbuf[0]); 656 if (ddi_copyout((caddr_t)&temp, (caddr_t)arg, 657 sizeof (int16_t), mode) != DDI_SUCCESS) { 658 err = EFAULT; 659 } 660 } else { 661 err = EIO; 662 } 663 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 664 break; 665 666 case MAX1617_GET_STATUS: 667 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 668 1, 1, I2C_SLEEP); 669 i2ctp->i2c_version = I2C_XFER_REV; 670 i2ctp->i2c_flags = I2C_WR_RD; 671 i2ctp->i2c_wbuf[0] = MAX1617_STATUS_REG; 672 673 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 674 if (ddi_copyout((caddr_t)i2ctp->i2c_rbuf, (caddr_t)arg, 675 sizeof (uint8_t), mode) != DDI_SUCCESS) { 676 err = EFAULT; 677 } 678 } else { 679 err = EIO; 680 } 681 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 682 break; 683 case MAX1617_GET_CONFIG: 684 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 1, 1, 685 I2C_SLEEP); 686 i2ctp->i2c_version = I2C_XFER_REV; 687 i2ctp->i2c_flags = I2C_WR_RD; 688 i2ctp->i2c_wbuf[0] = MAX1617_CONFIG_REG; 689 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 690 if (ddi_copyout((caddr_t)i2ctp->i2c_rbuf, (caddr_t)arg, 691 sizeof (uint8_t), mode) != DDI_SUCCESS) { 692 err = EFAULT; 693 } 694 } else { 695 err = EIO; 696 } 697 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 698 break; 699 case MAX1617_GET_CONV_RATE: 700 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 701 1, 1, I2C_SLEEP); 702 i2ctp->i2c_version = I2C_XFER_REV; 703 i2ctp->i2c_flags = I2C_WR_RD; 704 i2ctp->i2c_wbuf[0] = MAX1617_CONV_RATE_REG; 705 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 706 if (ddi_copyout((caddr_t)i2ctp->i2c_rbuf, (caddr_t)arg, 707 sizeof (uint8_t), mode) != DDI_SUCCESS) { 708 err = EFAULT; 709 } 710 } else { 711 err = EIO; 712 } 713 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 714 break; 715 716 case MAX1617_GET_HIGH_LIMIT: 717 switch (fcn) { 718 case MAX1617_AMB_TEMP: 719 err = get_temp_limit(unitp, MAX1617_LOCALTEMP_HIGH_REG, 720 (caddr_t)arg, mode); 721 break; 722 case MAX1617_CPU_TEMP: 723 err = get_temp_limit(unitp, MAX1617_REMOTETEMP_HIGH_REG, 724 (caddr_t)arg, mode); 725 break; 726 default: 727 err = EINVAL; 728 break; 729 } 730 break; 731 732 case MAX1617_GET_LOW_LIMIT: 733 734 switch (fcn) { 735 case MAX1617_AMB_TEMP: 736 err = get_temp_limit(unitp, MAX1617_LOCALTEMP_LOW_REG, 737 (caddr_t)arg, mode); 738 break; 739 case MAX1617_CPU_TEMP: 740 err = get_temp_limit(unitp, MAX1617_REMOTETEMP_LOW_REG, 741 (caddr_t)arg, mode); 742 break; 743 default: 744 err = EINVAL; 745 } 746 break; 747 748 case MAX1617_SET_CONV_RATE: 749 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 750 2, 0, I2C_SLEEP); 751 i2ctp->i2c_version = I2C_XFER_REV; 752 i2ctp->i2c_flags = I2C_WR; 753 i2ctp->i2c_wbuf[0] = MAX1617_CONV_RATE_WR_REG; 754 if (ddi_copyin((caddr_t)arg, (caddr_t)&i2ctp->i2c_wbuf[1], 755 sizeof (uint8_t), mode) != DDI_SUCCESS) { 756 err = EFAULT; 757 break; 758 } 759 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 760 err = EIO; 761 } 762 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 763 break; 764 765 case MAX1617_SET_CONFIG: 766 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 767 2, 0, I2C_SLEEP); 768 i2ctp->i2c_version = I2C_XFER_REV; 769 i2ctp->i2c_flags = I2C_WR; 770 i2ctp->i2c_wbuf[0] = MAX1617_CONFIG_WR_REG; 771 if (ddi_copyin((caddr_t)arg, (caddr_t)&i2ctp->i2c_wbuf[1], 772 sizeof (uint8_t), mode) != DDI_SUCCESS) { 773 err = EFAULT; 774 break; 775 } 776 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 777 err = EIO; 778 } 779 780 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 781 break; 782 783 case MAX1617_SET_HIGH_LIMIT: 784 switch (fcn) { 785 case MAX1617_AMB_TEMP: 786 err = set_temp_limit(unitp, 787 MAX1617_LOCALTEMP_HIGH_WR_REG, (caddr_t)arg, mode); 788 break; 789 case MAX1617_CPU_TEMP: 790 err = set_temp_limit(unitp, 791 MAX1617_REMOTETEMP_HIGH_WR_REG, (caddr_t)arg, mode); 792 break; 793 default: 794 err = EINVAL; 795 } 796 break; 797 798 case MAX1617_SET_LOW_LIMIT: 799 switch (fcn) { 800 case MAX1617_AMB_TEMP: 801 err = set_temp_limit(unitp, 802 MAX1617_LOCALTEMP_LOW_WR_REG, (caddr_t)arg, mode); 803 break; 804 case MAX1617_CPU_TEMP: 805 err = set_temp_limit(unitp, 806 MAX1617_REMOTETEMP_LOW_WR_REG, (caddr_t)arg, mode); 807 break; 808 default: 809 err = EINVAL; 810 } 811 break; 812 813 case MAX1617_ONE_SHOT_CMD: 814 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 1, 0, 815 I2C_SLEEP); 816 i2ctp->i2c_version = I2C_XFER_REV; 817 i2ctp->i2c_flags = I2C_WR; 818 i2ctp->i2c_wbuf[0] = MAX1617_ONE_SHOT_CMD_REG; 819 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 820 err = EIO; 821 } 822 823 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 824 break; 825 826 default: 827 err = EINVAL; 828 } 829 830 done: 831 832 mutex_enter(&unitp->max1617_mutex); 833 unitp->max1617_flags = 0; 834 cv_signal(&unitp->max1617_cv); 835 mutex_exit(&unitp->max1617_mutex); 836 837 return (err); 838 } 839