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, NULL) == 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, NULL) == 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, 529 uchar_t device_reg, 530 caddr_t arg, 531 int mode) 532 { 533 int err = 0; 534 i2c_transfer_t *i2ctp; 535 int16_t temp; 536 537 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 2, 0, I2C_SLEEP); 538 i2ctp->i2c_version = I2C_XFER_REV; 539 i2ctp->i2c_flags = I2C_WR; 540 i2ctp->i2c_wbuf[0] = device_reg; 541 542 if (ddi_copyin(arg, (caddr_t)&temp, sizeof (int16_t), mode) != 543 DDI_SUCCESS) { 544 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 545 546 return (EFAULT); 547 } 548 549 i2ctp->i2c_wbuf[1] = (int8_t)temp; 550 551 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 552 err = EIO; 553 } 554 555 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 556 557 return (err); 558 } 559 560 int 561 get_temp_limit(struct max1617_unit *unitp, 562 uchar_t reg, 563 caddr_t arg, 564 int mode) 565 { 566 int err = 0; 567 i2c_transfer_t *i2ctp; 568 int16_t temp16; 569 570 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 1, 1, I2C_SLEEP); 571 i2ctp->i2c_version = I2C_XFER_REV; 572 i2ctp->i2c_flags = I2C_WR_RD; 573 i2ctp->i2c_wbuf[0] = reg; 574 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 575 /* 576 * This double cast is required so that the sign is preserved 577 * when expanding the 8 bit value to 16. 578 */ 579 temp16 = (int16_t)((int8_t)i2ctp->i2c_rbuf[0]); 580 if (ddi_copyout((caddr_t)&temp16, arg, sizeof (int16_t), 581 mode) != DDI_SUCCESS) { 582 err = EFAULT; 583 } 584 } else { 585 err = EIO; 586 } 587 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 588 589 return (err); 590 } 591 592 static int 593 max1617_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 594 cred_t *credp, int *rvalp) 595 { 596 _NOTE(ARGUNUSED(credp, rvalp)) 597 struct max1617_unit *unitp; 598 int err = 0; 599 i2c_transfer_t *i2ctp; 600 int fcn = MAX1617_MINOR_TO_FCN(getminor(dev)); 601 int instance = MAX1617_MINOR_TO_INST(getminor(dev)); 602 uchar_t reg; 603 604 unitp = (struct max1617_unit *) 605 ddi_get_soft_state(max1617_soft_statep, instance); 606 607 if (max1617_debug) { 608 printf("max1617_ioctl: fcn=%d instance=%d\n", fcn, instance); 609 } 610 611 /* 612 * Serialize here, in order to block transacations during CPR. 613 * This is not a bottle neck since i2c_transfer would serialize 614 * anyway. 615 */ 616 mutex_enter(&unitp->max1617_mutex); 617 while (unitp->max1617_flags == MAX1617_BUSY) { 618 if (cv_wait_sig(&unitp->max1617_cv, 619 &unitp->max1617_mutex) <= 0) { 620 mutex_exit(&unitp->max1617_mutex); 621 return (EINTR); 622 } 623 } 624 unitp->max1617_flags = MAX1617_BUSY; 625 mutex_exit(&unitp->max1617_mutex); 626 627 switch (cmd) { 628 629 /* 630 * I2C_GET_TEMPERATURE reads a temperature from the device and 631 * copies a single byte representing the celcius temp 632 * to user space. 633 */ 634 case I2C_GET_TEMPERATURE: 635 switch (fcn) { 636 case MAX1617_AMB_TEMP: 637 reg = MAX1617_LOCAL_TEMP_REG; 638 break; 639 case MAX1617_CPU_TEMP: 640 reg = MAX1617_REMOTE_TEMP_REG; 641 break; 642 default: 643 err = EINVAL; 644 goto done; 645 } 646 647 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 648 1, 1, I2C_SLEEP); 649 i2ctp->i2c_version = I2C_XFER_REV; 650 i2ctp->i2c_flags = I2C_WR_RD; 651 i2ctp->i2c_wbuf[0] = reg; 652 653 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 654 655 /* 656 * This double cast is needed so that the sign bit 657 * is preserved when casting from unsigned char to 658 * signed 16 bit value. 659 */ 660 int16_t temp = (int16_t)((int8_t)i2ctp->i2c_rbuf[0]); 661 if (ddi_copyout((caddr_t)&temp, (caddr_t)arg, 662 sizeof (int16_t), mode) != DDI_SUCCESS) { 663 err = EFAULT; 664 } 665 } else { 666 err = EIO; 667 } 668 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 669 break; 670 671 case MAX1617_GET_STATUS: 672 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 673 1, 1, I2C_SLEEP); 674 i2ctp->i2c_version = I2C_XFER_REV; 675 i2ctp->i2c_flags = I2C_WR_RD; 676 i2ctp->i2c_wbuf[0] = MAX1617_STATUS_REG; 677 678 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 679 if (ddi_copyout((caddr_t)i2ctp->i2c_rbuf, (caddr_t)arg, 680 sizeof (uint8_t), mode) != DDI_SUCCESS) { 681 err = EFAULT; 682 } 683 } else { 684 err = EIO; 685 } 686 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 687 break; 688 case MAX1617_GET_CONFIG: 689 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 1, 1, 690 I2C_SLEEP); 691 i2ctp->i2c_version = I2C_XFER_REV; 692 i2ctp->i2c_flags = I2C_WR_RD; 693 i2ctp->i2c_wbuf[0] = MAX1617_CONFIG_REG; 694 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 695 if (ddi_copyout((caddr_t)i2ctp->i2c_rbuf, (caddr_t)arg, 696 sizeof (uint8_t), mode) != DDI_SUCCESS) { 697 err = EFAULT; 698 } 699 } else { 700 err = EIO; 701 } 702 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 703 break; 704 case MAX1617_GET_CONV_RATE: 705 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 706 1, 1, I2C_SLEEP); 707 i2ctp->i2c_version = I2C_XFER_REV; 708 i2ctp->i2c_flags = I2C_WR_RD; 709 i2ctp->i2c_wbuf[0] = MAX1617_CONV_RATE_REG; 710 if (i2c_transfer(unitp->max1617_hdl, i2ctp) == I2C_SUCCESS) { 711 if (ddi_copyout((caddr_t)i2ctp->i2c_rbuf, (caddr_t)arg, 712 sizeof (uint8_t), mode) != DDI_SUCCESS) { 713 err = EFAULT; 714 } 715 } else { 716 err = EIO; 717 } 718 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 719 break; 720 721 case MAX1617_GET_HIGH_LIMIT: 722 switch (fcn) { 723 case MAX1617_AMB_TEMP: 724 err = get_temp_limit(unitp, MAX1617_LOCALTEMP_HIGH_REG, 725 (caddr_t)arg, mode); 726 break; 727 case MAX1617_CPU_TEMP: 728 err = get_temp_limit(unitp, MAX1617_REMOTETEMP_HIGH_REG, 729 (caddr_t)arg, mode); 730 break; 731 default: 732 err = EINVAL; 733 break; 734 } 735 break; 736 737 case MAX1617_GET_LOW_LIMIT: 738 739 switch (fcn) { 740 case MAX1617_AMB_TEMP: 741 err = get_temp_limit(unitp, MAX1617_LOCALTEMP_LOW_REG, 742 (caddr_t)arg, mode); 743 break; 744 case MAX1617_CPU_TEMP: 745 err = get_temp_limit(unitp, MAX1617_REMOTETEMP_LOW_REG, 746 (caddr_t)arg, mode); 747 break; 748 default: 749 err = EINVAL; 750 } 751 break; 752 753 case MAX1617_SET_CONV_RATE: 754 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 755 2, 0, I2C_SLEEP); 756 i2ctp->i2c_version = I2C_XFER_REV; 757 i2ctp->i2c_flags = I2C_WR; 758 i2ctp->i2c_wbuf[0] = MAX1617_CONV_RATE_WR_REG; 759 if (ddi_copyin((caddr_t)arg, (caddr_t)&i2ctp->i2c_wbuf[1], 760 sizeof (uint8_t), mode) != DDI_SUCCESS) { 761 err = EFAULT; 762 break; 763 } 764 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 765 err = EIO; 766 } 767 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 768 break; 769 770 case MAX1617_SET_CONFIG: 771 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 772 2, 0, I2C_SLEEP); 773 i2ctp->i2c_version = I2C_XFER_REV; 774 i2ctp->i2c_flags = I2C_WR; 775 i2ctp->i2c_wbuf[0] = MAX1617_CONFIG_WR_REG; 776 if (ddi_copyin((caddr_t)arg, (caddr_t)&i2ctp->i2c_wbuf[1], 777 sizeof (uint8_t), mode) != DDI_SUCCESS) { 778 err = EFAULT; 779 break; 780 } 781 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 782 err = EIO; 783 } 784 785 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 786 break; 787 788 case MAX1617_SET_HIGH_LIMIT: 789 switch (fcn) { 790 case MAX1617_AMB_TEMP: 791 err = set_temp_limit(unitp, 792 MAX1617_LOCALTEMP_HIGH_WR_REG, (caddr_t)arg, mode); 793 break; 794 case MAX1617_CPU_TEMP: 795 err = set_temp_limit(unitp, 796 MAX1617_REMOTETEMP_HIGH_WR_REG, (caddr_t)arg, mode); 797 break; 798 default: 799 err = EINVAL; 800 } 801 break; 802 803 case MAX1617_SET_LOW_LIMIT: 804 switch (fcn) { 805 case MAX1617_AMB_TEMP: 806 err = set_temp_limit(unitp, 807 MAX1617_LOCALTEMP_LOW_WR_REG, (caddr_t)arg, mode); 808 break; 809 case MAX1617_CPU_TEMP: 810 err = set_temp_limit(unitp, 811 MAX1617_REMOTETEMP_LOW_WR_REG, (caddr_t)arg, mode); 812 break; 813 default: 814 err = EINVAL; 815 } 816 break; 817 818 case MAX1617_ONE_SHOT_CMD: 819 (void) i2c_transfer_alloc(unitp->max1617_hdl, &i2ctp, 1, 0, 820 I2C_SLEEP); 821 i2ctp->i2c_version = I2C_XFER_REV; 822 i2ctp->i2c_flags = I2C_WR; 823 i2ctp->i2c_wbuf[0] = MAX1617_ONE_SHOT_CMD_REG; 824 if (i2c_transfer(unitp->max1617_hdl, i2ctp) != I2C_SUCCESS) { 825 err = EIO; 826 } 827 828 i2c_transfer_free(unitp->max1617_hdl, i2ctp); 829 break; 830 831 default: 832 err = EINVAL; 833 } 834 835 done: 836 837 mutex_enter(&unitp->max1617_mutex); 838 unitp->max1617_flags = 0; 839 cv_signal(&unitp->max1617_cv); 840 mutex_exit(&unitp->max1617_mutex); 841 842 return (err); 843 } 844