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