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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 29 #include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */ 30 #include <sys/modctl.h> /* for modldrv */ 31 #include <sys/open.h> /* for open params. */ 32 #include <sys/types.h> 33 #include <sys/kmem.h> 34 #include <sys/sunddi.h> 35 #include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */ 36 #include <sys/ddi.h> 37 #include <sys/file.h> 38 #include <sys/note.h> 39 40 #include <sys/i2c/clients/ssc100_impl.h> 41 42 static void *ssc100soft_statep; 43 44 static int ssc100_do_attach(dev_info_t *); 45 static int ssc100_do_detach(dev_info_t *); 46 static int ssc100_do_resume(void); 47 static int ssc100_do_suspend(void); 48 static int ssc100_get(struct ssc100_unit *, uchar_t *); 49 static int ssc100_set(struct ssc100_unit *, uchar_t); 50 static int ssc100_get_reg(struct ssc100_unit *, uchar_t *, uchar_t); 51 static int ssc100_common(struct ssc100_unit *, uchar_t *, uchar_t, int8_t); 52 static int ssc100_read(dev_t, struct uio *, cred_t *); 53 static int ssc100_write(dev_t, struct uio *, cred_t *); 54 static int ssc100_io(dev_t, struct uio *, int); 55 56 /* 57 * cb ops (only need ioctl) 58 */ 59 static int ssc100_open(dev_t *, int, int, cred_t *); 60 static int ssc100_close(dev_t, int, int, cred_t *); 61 static int ssc100_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 62 63 static struct cb_ops ssc100_cbops = { 64 ssc100_open, /* open */ 65 ssc100_close, /* close */ 66 nodev, /* strategy */ 67 nodev, /* print */ 68 nodev, /* dump */ 69 ssc100_read, /* read */ 70 ssc100_write, /* write */ 71 ssc100_ioctl, /* ioctl */ 72 nodev, /* devmap */ 73 nodev, /* mmap */ 74 nodev, /* segmap */ 75 nochpoll, /* poll */ 76 ddi_prop_op, /* cb_prop_op */ 77 NULL, /* streamtab */ 78 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 79 CB_REV, /* rev */ 80 nodev, /* int (*cb_aread)() */ 81 nodev /* int (*cb_awrite)() */ 82 }; 83 84 /* 85 * dev ops 86 */ 87 static int ssc100_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 88 static int ssc100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 89 90 static struct dev_ops ssc100_ops = { 91 DEVO_REV, 92 0, 93 ddi_getinfo_1to1, 94 nulldev, 95 nulldev, 96 ssc100_attach, 97 ssc100_detach, 98 nodev, 99 &ssc100_cbops, 100 NULL 101 }; 102 103 extern struct mod_ops mod_driverops; 104 105 static struct modldrv ssc100_modldrv = { 106 &mod_driverops, /* type of module - driver */ 107 "SSC100 i2c device driver: v%I%", 108 &ssc100_ops 109 }; 110 111 static struct modlinkage ssc100_modlinkage = { 112 MODREV_1, 113 &ssc100_modldrv, 114 0 115 }; 116 117 118 int 119 _init(void) 120 { 121 int error; 122 123 error = mod_install(&ssc100_modlinkage); 124 125 if (!error) 126 (void) ddi_soft_state_init(&ssc100soft_statep, 127 sizeof (struct ssc100_unit), 1); 128 return (error); 129 } 130 131 int 132 _fini(void) 133 { 134 int error; 135 136 error = mod_remove(&ssc100_modlinkage); 137 if (!error) 138 ddi_soft_state_fini(&ssc100soft_statep); 139 140 return (error); 141 } 142 143 int 144 _info(struct modinfo *modinfop) 145 { 146 return (mod_info(&ssc100_modlinkage, modinfop)); 147 } 148 149 static int 150 ssc100_open(dev_t *devp, int flags, int otyp, cred_t *credp) 151 { 152 _NOTE(ARGUNUSED(credp)) 153 154 struct ssc100_unit *unitp; 155 int instance; 156 int error = 0; 157 158 instance = getminor(*devp); 159 160 if (instance < 0) { 161 return (ENXIO); 162 } 163 164 unitp = (struct ssc100_unit *) 165 ddi_get_soft_state(ssc100soft_statep, instance); 166 167 if (unitp == NULL) { 168 return (ENXIO); 169 } 170 171 if (otyp != OTYP_CHR) { 172 return (EINVAL); 173 } 174 175 mutex_enter(&unitp->ssc100_mutex); 176 177 if (flags & FEXCL) { 178 if (unitp->ssc100_oflag != 0) { 179 error = EBUSY; 180 } else { 181 unitp->ssc100_oflag = FEXCL; 182 } 183 } else { 184 if (unitp->ssc100_oflag == FEXCL) { 185 error = EBUSY; 186 } else { 187 unitp->ssc100_oflag = FOPEN; 188 } 189 } 190 191 mutex_exit(&unitp->ssc100_mutex); 192 193 return (error); 194 } 195 196 static int 197 ssc100_close(dev_t dev, int flags, int otyp, cred_t *credp) 198 { 199 _NOTE(ARGUNUSED(flags, otyp, credp)) 200 201 struct ssc100_unit *unitp; 202 int instance; 203 204 instance = getminor(dev); 205 206 if (instance < 0) { 207 return (ENXIO); 208 } 209 unitp = (struct ssc100_unit *) 210 ddi_get_soft_state(ssc100soft_statep, instance); 211 212 if (unitp == NULL) { 213 return (ENXIO); 214 } 215 216 mutex_enter(&unitp->ssc100_mutex); 217 218 unitp->ssc100_oflag = 0; 219 220 mutex_exit(&unitp->ssc100_mutex); 221 return (DDI_SUCCESS); 222 } 223 224 static int 225 ssc100_common(struct ssc100_unit *unitp, uchar_t *byte, uchar_t input, 226 int8_t flag) 227 { 228 i2c_transfer_t *i2c_tran_pointer; 229 int err = I2C_SUCCESS; 230 231 (void) i2c_transfer_alloc(unitp->ssc100_hdl, &i2c_tran_pointer, 232 1, 1, I2C_SLEEP); 233 if (i2c_tran_pointer == NULL) { 234 D2CMN_ERR((CE_WARN, "%s: Failed in SSC100_COMMON " 235 "i2c_tran_pointer not allocated", 236 unitp->ssc100_name)); 237 return (ENOMEM); 238 } 239 240 i2c_tran_pointer->i2c_flags = flag; 241 if (flag != I2C_RD) { 242 i2c_tran_pointer->i2c_wbuf[0] = input; 243 } 244 245 err = i2c_transfer(unitp->ssc100_hdl, i2c_tran_pointer); 246 if (err) { 247 D2CMN_ERR((CE_WARN, "%s: Failed in SSC100_COMMON " 248 "i2c_transfer routine", unitp->ssc100_name)); 249 } else if (flag != I2C_WR) { 250 *byte = i2c_tran_pointer->i2c_rbuf[0]; 251 } 252 253 i2c_transfer_free(unitp->ssc100_hdl, i2c_tran_pointer); 254 return (err); 255 } 256 257 static int 258 ssc100_get_reg(struct ssc100_unit *unitp, uchar_t *byte, uchar_t reg) 259 { 260 int err = I2C_SUCCESS; 261 262 err = ssc100_common(unitp, byte, reg, I2C_WR_RD); 263 if (err) { 264 D2CMN_ERR((CE_WARN, "%s: Failed in SSC100_GET_REG " 265 "i2c_common routine", unitp->ssc100_name)); 266 } 267 return (err); 268 } 269 270 static int 271 ssc100_get(struct ssc100_unit *unitp, uchar_t *byte) 272 { 273 int err = I2C_SUCCESS; 274 275 err = ssc100_common(unitp, byte, 0, I2C_RD); 276 if (err) { 277 D2CMN_ERR((CE_WARN, "%s: Failed in SSC100_GET " 278 "i2c_common routine", unitp->ssc100_name)); 279 } 280 return (err); 281 } 282 283 static int 284 ssc100_set(struct ssc100_unit *unitp, uchar_t byte) 285 { 286 int err = I2C_SUCCESS; 287 288 err = ssc100_common(unitp, NULL, byte, I2C_WR); 289 if (err) { 290 D2CMN_ERR((CE_WARN, "%s: Failed in SSC100_SET " 291 "i2c_common routine", unitp->ssc100_name)); 292 } 293 return (err); 294 } 295 296 static int 297 ssc100_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 298 cred_t *credp, int *rvalp) 299 { 300 _NOTE(ARGUNUSED(credp, rvalp)) 301 302 struct ssc100_unit *unitp; 303 int instance; 304 int err = 0; 305 i2c_bit_t ioctl_bit; 306 i2c_port_t ioctl_port; 307 i2c_reg_t ioctl_reg; 308 uchar_t byte; 309 310 if (arg == NULL) { 311 D2CMN_ERR((CE_WARN, "SSC100: ioctl: arg passed in to ioctl " 312 "= NULL")); 313 err = EINVAL; 314 return (err); 315 } 316 317 instance = getminor(dev); 318 unitp = (struct ssc100_unit *) 319 ddi_get_soft_state(ssc100soft_statep, instance); 320 if (unitp == NULL) { 321 cmn_err(CE_WARN, "SSC100: ioctl: unitp not filled"); 322 return (ENOMEM); 323 } 324 325 mutex_enter(&unitp->ssc100_mutex); 326 327 switch (cmd) { 328 case I2C_GET_PORT: 329 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_port, 330 sizeof (i2c_port_t), mode) != DDI_SUCCESS) { 331 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_PORT" 332 " ddi_copyin routine", unitp->ssc100_name)); 333 err = EFAULT; 334 break; 335 } 336 337 err = ssc100_get(unitp, &byte); 338 if (err != I2C_SUCCESS) { 339 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_PORT" 340 " ssc100_get routine", unitp->ssc100_name)); 341 break; 342 } 343 344 ioctl_port.value = byte; 345 if (ddi_copyout((caddr_t)&ioctl_port, (caddr_t)arg, 346 sizeof (i2c_port_t), mode) != DDI_SUCCESS) { 347 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_GET_PORT " 348 "ddi_copyout routine", unitp->ssc100_name)); 349 err = EFAULT; 350 } 351 352 D1CMN_ERR((CE_NOTE, "%s: contains %x", unitp->ssc100_name, 353 byte)); 354 break; 355 356 case I2C_SET_PORT: 357 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_port, 358 sizeof (uint8_t), mode) != DDI_SUCCESS) { 359 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_PORT" 360 "ddi_cpoyin routine", unitp->ssc100_name)); 361 err = EFAULT; 362 break; 363 } 364 365 err = ssc100_set(unitp, ioctl_port.value); 366 if (err != I2C_SUCCESS) { 367 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_PORT" 368 " ssc100_set routine", unitp->ssc100_name)); 369 break; 370 } 371 break; 372 373 case I2C_GET_BIT: 374 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_bit, 375 sizeof (i2c_bit_t), mode) != DDI_SUCCESS) { 376 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_BIT" 377 " ddi_copyin routine", unitp->ssc100_name)); 378 err = EFAULT; 379 break; 380 } 381 382 if ((ioctl_bit.bit_num < 0) && (ioctl_bit.bit_num > 7)) { 383 D2CMN_ERR((CE_WARN, "%s: In I2C_GET_BIT bit num" 384 " was not between 0 and 7", 385 unitp->ssc100_name)); 386 err = EIO; 387 break; 388 } 389 390 err = ssc100_get(unitp, &byte); 391 if (err != I2C_SUCCESS) { 392 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_GET_BIT" 393 " ssc100_get routine", unitp->ssc100_name)); 394 break; 395 } 396 397 D1CMN_ERR((CE_NOTE, "%s: byte returned from device is %x", 398 unitp->ssc100_name, byte)); 399 ioctl_bit.bit_value = (boolean_t)SSC100_BIT_READ_MASK(byte, 400 ioctl_bit.bit_num); 401 D1CMN_ERR((CE_NOTE, "%s: byte now contains %x", 402 unitp->ssc100_name, byte)); 403 404 if (ddi_copyout((caddr_t)&ioctl_bit, (caddr_t)arg, 405 sizeof (i2c_bit_t), mode) != DDI_SUCCESS) { 406 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_GET_BIT" 407 " ddi_copyout routine", unitp->ssc100_name)); 408 err = EFAULT; 409 } 410 break; 411 412 case I2C_SET_BIT: 413 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_bit, 414 sizeof (i2c_bit_t), mode) != DDI_SUCCESS) { 415 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_SET_BIT" 416 " ddi_copyin routine", unitp->ssc100_name)); 417 err = EFAULT; 418 break; 419 } 420 421 if ((ioctl_bit.bit_num < 0) && (ioctl_bit.bit_num > 7)) { 422 D2CMN_ERR((CE_WARN, "%s: I2C_SET_BIT: bit_num sent" 423 " in was not between 0 and 7", 424 unitp->ssc100_name)); 425 err = EIO; 426 break; 427 } 428 429 err = ssc100_get(unitp, &byte); 430 if (err != I2C_SUCCESS) { 431 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_BIT" 432 " ssc100_get routine", unitp->ssc100_name)); 433 break; 434 } 435 436 D1CMN_ERR((CE_NOTE, "%s: byte returned from device is %x", 437 unitp->ssc100_name, byte)); 438 byte = SSC100_BIT_WRITE_MASK(byte, ioctl_bit.bit_num, 439 ioctl_bit.bit_value); 440 D1CMN_ERR((CE_NOTE, "%s: byte after shifting is %x", 441 unitp->ssc100_name, byte)); 442 443 err = ssc100_set(unitp, byte); 444 if (err != I2C_SUCCESS) { 445 D2CMN_ERR((CE_WARN, "%s: Failed in the I2C_SET_BIT" 446 " ssc100_set routine", unitp->ssc100_name)); 447 break; 448 } 449 break; 450 451 case I2C_GET_REG: 452 if (ddi_copyin((caddr_t)arg, (caddr_t)&ioctl_reg, 453 sizeof (i2c_reg_t), mode) != DDI_SUCCESS) { 454 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_GET_REG " 455 "ddi_copyin routine", unitp->ssc100_name)); 456 err = EFAULT; 457 break; 458 } 459 460 err = ssc100_get_reg(unitp, &byte, ioctl_reg.reg_num); 461 462 ioctl_reg.reg_value = byte; 463 if (ddi_copyout((caddr_t)&ioctl_reg, (caddr_t)arg, 464 sizeof (i2c_reg_t), mode) != DDI_SUCCESS) { 465 D2CMN_ERR((CE_WARN, "%s: Failed in I2C_GET_REG " 466 "ddi_copyout routine", unitp->ssc100_name)); 467 err = EFAULT; 468 } 469 break; 470 471 default: 472 D2CMN_ERR((CE_WARN, "%s: Invalid IOCTL cmd: %x", 473 unitp->ssc100_name, cmd)); 474 err = EINVAL; 475 } 476 477 mutex_exit(&unitp->ssc100_mutex); 478 return (err); 479 } 480 481 static int 482 ssc100_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 483 { 484 switch (cmd) { 485 case DDI_ATTACH: 486 return (ssc100_do_attach(dip)); 487 case DDI_RESUME: 488 return (ssc100_do_resume()); 489 default: 490 return (DDI_FAILURE); 491 } 492 } 493 494 static int 495 ssc100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 496 { 497 switch (cmd) { 498 case DDI_DETACH: 499 return (ssc100_do_detach(dip)); 500 case DDI_SUSPEND: 501 return (ssc100_do_suspend()); 502 default: 503 return (DDI_FAILURE); 504 } 505 } 506 507 static int 508 ssc100_do_attach(dev_info_t *dip) 509 { 510 struct ssc100_unit *unitp; 511 int instance; 512 513 instance = ddi_get_instance(dip); 514 515 if (ddi_soft_state_zalloc(ssc100soft_statep, instance) != 0) { 516 cmn_err(CE_WARN, "%s%d: failed to zalloc softstate", 517 ddi_get_name(dip), instance); 518 return (DDI_FAILURE); 519 } 520 521 unitp = ddi_get_soft_state(ssc100soft_statep, instance); 522 523 if (unitp == NULL) { 524 cmn_err(CE_WARN, "%s%d: unitp not filled", 525 ddi_get_name(dip), instance); 526 return (ENOMEM); 527 } 528 529 (void) snprintf(unitp->ssc100_name, sizeof (unitp->ssc100_name), 530 "%s%d", ddi_node_name(dip), instance); 531 532 if (ddi_create_minor_node(dip, "ssc100", S_IFCHR, instance, 533 "ddi_i2c:ioexp", NULL) == DDI_FAILURE) { 534 cmn_err(CE_WARN, "%s ddi_create_minor_node failed for " 535 "%s", unitp->ssc100_name, "ssc100"); 536 ddi_soft_state_free(ssc100soft_statep, instance); 537 538 return (DDI_FAILURE); 539 } 540 541 /* 542 * If we had different sizes in the future, this could be read 543 * from a property. 544 */ 545 unitp->ssc100_size = SSC100_SIZE; 546 547 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, 548 DDI_PROP_CANSLEEP, "size", 549 (caddr_t)&unitp->ssc100_size, sizeof (unitp->ssc100_size)); 550 551 if (i2c_client_register(dip, &unitp->ssc100_hdl) != I2C_SUCCESS) { 552 ddi_remove_minor_node(dip, NULL); 553 ddi_soft_state_free(ssc100soft_statep, instance); 554 555 return (DDI_FAILURE); 556 } 557 558 mutex_init(&unitp->ssc100_mutex, NULL, MUTEX_DRIVER, NULL); 559 560 return (DDI_SUCCESS); 561 } 562 563 static int 564 ssc100_do_resume() 565 { 566 int ret = DDI_SUCCESS; 567 568 return (ret); 569 } 570 571 static int 572 ssc100_do_suspend() 573 { 574 int ret = DDI_SUCCESS; 575 576 return (ret); 577 } 578 579 static int 580 ssc100_do_detach(dev_info_t *dip) 581 { 582 struct ssc100_unit *unitp; 583 int instance; 584 585 instance = ddi_get_instance(dip); 586 587 unitp = ddi_get_soft_state(ssc100soft_statep, instance); 588 589 i2c_client_unregister(unitp->ssc100_hdl); 590 591 ddi_remove_minor_node(dip, NULL); 592 593 mutex_destroy(&unitp->ssc100_mutex); 594 595 ddi_soft_state_free(ssc100soft_statep, instance); 596 597 return (DDI_SUCCESS); 598 599 } 600 601 static int 602 ssc100_read(dev_t dev, struct uio *uiop, cred_t *cred_p) 603 { 604 _NOTE(ARGUNUSED(cred_p)) 605 606 return (ssc100_io(dev, uiop, B_READ)); 607 } 608 609 static int 610 ssc100_write(dev_t dev, struct uio *uiop, cred_t *cred_p) 611 { 612 _NOTE(ARGUNUSED(cred_p)) 613 614 return (ssc100_io(dev, uiop, B_WRITE)); 615 } 616 617 static int 618 ssc100_io(dev_t dev, struct uio *uiop, int rw) 619 { 620 struct ssc100_unit *unitp; 621 int instance = getminor(dev); 622 int ssc100_addr; 623 int bytes_to_rw; 624 int err = 0; 625 int current_xfer_len; 626 i2c_transfer_t *i2ctp = NULL; 627 628 if (instance < 0) { 629 return (ENXIO); 630 } 631 632 unitp = (struct ssc100_unit *) 633 ddi_get_soft_state(ssc100soft_statep, instance); 634 635 636 if (unitp == NULL) { 637 return (ENXIO); 638 } 639 640 if (uiop->uio_offset >= unitp->ssc100_size) { 641 /* 642 * Exceeded ssc100 size. 643 */ 644 if (rw == B_WRITE) { 645 646 return (ENOSPC); 647 } 648 return (0); 649 } 650 651 ssc100_addr = uiop->uio_offset; 652 653 if (uiop->uio_resid == 0) { 654 return (0); 655 } 656 657 bytes_to_rw = min(uiop->uio_resid, 658 unitp->ssc100_size - uiop->uio_offset); 659 current_xfer_len = bytes_to_rw; 660 661 if (rw == B_WRITE) { 662 (void) i2c_transfer_alloc(unitp->ssc100_hdl, &i2ctp, 663 current_xfer_len+1, 0, I2C_SLEEP); 664 if (i2ctp == NULL) { 665 D2CMN_ERR((CE_WARN, "%s: Failed in ssc100_io WRITE " 666 "i2c_tran_pointer not allocated", 667 unitp->ssc100_name)); 668 return (ENOMEM); 669 } 670 i2ctp->i2c_version = I2C_XFER_REV; 671 i2ctp->i2c_flags = I2C_WR; 672 i2ctp->i2c_wbuf[0] = (uchar_t)ssc100_addr; 673 if ((err = uiomove(&i2ctp->i2c_wbuf[1], current_xfer_len, 674 UIO_WRITE, uiop)) != 0) { 675 D2CMN_ERR((CE_WARN, "%s: Failed in ssc100_io WRITE " 676 "uiomove failed", unitp->ssc100_name)); 677 goto end; 678 } 679 680 if ((err = i2c_transfer(unitp->ssc100_hdl, i2ctp)) != 681 I2C_SUCCESS) { 682 D2CMN_ERR((CE_WARN, "%s: Failed in ssc100_io WRITE " 683 "i2c_transfer failed", unitp->ssc100_name)); 684 goto end; 685 } 686 } else { 687 /* 688 * SSC100 read. We need to first write out the address 689 * that we wish to read. 690 */ 691 (void) i2c_transfer_alloc(unitp->ssc100_hdl, &i2ctp, 1, 692 current_xfer_len, I2C_SLEEP); 693 if (i2ctp == NULL) { 694 D2CMN_ERR((CE_WARN, "%s: Failed in ssc100_io READ " 695 "i2c_tran_pointer not allocated", 696 unitp->ssc100_name)); 697 return (ENOMEM); 698 } 699 i2ctp->i2c_version = I2C_XFER_REV; 700 i2ctp->i2c_wbuf[0] = (uchar_t)ssc100_addr; 701 i2ctp->i2c_flags = I2C_WR_RD; 702 703 if ((err = i2c_transfer(unitp->ssc100_hdl, i2ctp)) != 704 I2C_SUCCESS) { 705 D2CMN_ERR((CE_WARN, "%s: Failed in ssc100_io READ " 706 "i2c_transfer failed", unitp->ssc100_name)); 707 goto end; 708 } 709 710 if ((err = uiomove(i2ctp->i2c_rbuf, current_xfer_len, 711 UIO_READ, uiop)) != 0) { 712 D2CMN_ERR((CE_WARN, "%s: Failed in ssc100_io READ " 713 "uiomove failed", unitp->ssc100_name)); 714 goto end; 715 } 716 } 717 718 end: 719 i2c_transfer_free(unitp->ssc100_hdl, i2ctp); 720 return (err); 721 } 722