/* * register ds1307 client device with i2c services, and * allocate & initialize soft state structure. */ static int todds1307_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { static ds1307_state_t *statep = NULL; i2c_transfer_t *i2c_tp = NULL; uint8_t tempVal = (uint8_t)0; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (instance != -1) { return (DDI_FAILURE); } instance = ddi_get_instance(dip); /* * Allocate soft state structure */ if (ddi_soft_state_zalloc(ds1307_statep, instance) != DDI_SUCCESS) { return (DDI_FAILURE); } statep = ddi_get_soft_state(ds1307_statep, instance); if (statep == NULL) { return (DDI_FAILURE); } statep->dip = dip; if (i2c_client_register(dip, &statep->ds1307_i2c_hdl) != I2C_SUCCESS) { ddi_soft_state_free(ds1307_statep, instance); delay(drv_usectohz(I2C_DELAY)); return (DDI_FAILURE); } /* check and initialize the oscillator */ (void) i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 1, 1, I2C_SLEEP); i2c_tp->i2c_version = I2C_XFER_REV; i2c_tp->i2c_flags = I2C_WR_RD; i2c_tp->i2c_wbuf[0] = (uchar_t)0x00; /* Read 00h */ i2c_tp->i2c_wlen = 1; i2c_tp->i2c_rlen = 1; if ((i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); ddi_soft_state_free(ds1307_statep, instance); delay(drv_usectohz(I2C_DELAY)); return (DDI_FAILURE); } tempVal = i2c_tp->i2c_rbuf[0]; (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); if (tempVal & 0x80) { /* check Oscillator */ (void) i2c_transfer_alloc(statep->ds1307_i2c_hdl, &i2c_tp, 2, 1, I2C_SLEEP); i2c_tp->i2c_version = I2C_XFER_REV; i2c_tp->i2c_flags = I2C_WR; i2c_tp->i2c_wbuf[0] = 0x00; i2c_tp->i2c_wbuf[1] = (uchar_t)(i2c_tp->i2c_rbuf[0]& 0x7f); i2c_tp->i2c_wlen = 2; /* Enable oscillator */ if ((i2c_transfer(statep->ds1307_i2c_hdl, i2c_tp)) != I2C_SUCCESS) { (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); ddi_soft_state_free(ds1307_statep, instance); return (DDI_FAILURE); } (void) i2c_transfer_free(statep->ds1307_i2c_hdl, i2c_tp); } /* * Create a periodical handler to read TOD. */ ASSERT(statep->cycid == NULL); statep->cycid = ddi_periodic_add(todds1307_cyclic, &soft_rtc, i2c_cyclic_timeout, DDI_IPL_1); statep->state = TOD_ATTACHED; todds1307_attach_done = 1; ddi_report_dev(dip); return (DDI_SUCCESS); }
static int pca9556_attach(dev_info_t *dip) { pca9556_unit_t *pcap; int instance = ddi_get_instance(dip); char name[MAXNAMELEN]; char *device_name; minor_t minor; int i, num_ports; if (ddi_soft_state_zalloc(pca9556_soft_statep, instance) != 0) { cmn_err(CE_WARN, "%s%d failed to zalloc softstate", ddi_get_name(dip), instance); return (DDI_FAILURE); } pcap = ddi_get_soft_state(pca9556_soft_statep, instance); if (pcap == NULL) return (DDI_FAILURE); mutex_init(&pcap->pca9556_mutex, NULL, MUTEX_DRIVER, NULL); cv_init(&pcap->pca9556_cv, NULL, CV_DRIVER, NULL); (void) snprintf(pcap->pca9556_name, sizeof (pcap->pca9556_name), "%s_%d", ddi_driver_name(dip), instance); device_name = ddi_get_name(dip); if (strcmp(device_name, "i2c-pca9555") == 0) { num_ports = PCA9555_NUM_PORTS; pcap->pca9555_device = B_TRUE; } else { num_ports = PCA9556_NUM_PORTS; pcap->pca9555_device = B_FALSE; minor = INST_TO_MINOR(instance); } for (i = 0; i < num_ports; i++) { if (!(pcap->pca9555_device)) { (void) snprintf(pcap->pca9556_name, sizeof (pcap->pca9556_name), "%s_%d", ddi_driver_name(dip), instance); (void) snprintf(name, sizeof (name), "%s", pcap->pca9556_name); } else { (void) sprintf(name, "port_%d", i); minor = INST_TO_MINOR(instance) | PORT_TO_MINOR(I2C_PORT(i)); } if (ddi_create_minor_node(dip, name, S_IFCHR, minor, PCA9556_NODE_TYPE, NULL) == DDI_FAILURE) { cmn_err(CE_WARN, "%s: failed to create node for %s", pcap->pca9556_name, name); pca9556_detach(dip); return (DDI_FAILURE); } } pcap->pca9556_flags |= PCA9556_MINORFLAG; /* * Add a zero-length attribute to tell the world we support * kernel ioctls (for layered drivers) */ (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0); /* * preallocate a single buffer for all reads and writes */ if (i2c_transfer_alloc(pcap->pca9556_hdl, &pcap->pca9556_transfer, 2, 2, I2C_SLEEP) != I2C_SUCCESS) { cmn_err(CE_WARN, "%s i2c_transfer_alloc failed", pcap->pca9556_name); pca9556_detach(dip); return (DDI_FAILURE); } pcap->pca9556_flags |= PCA9556_TBUFFLAG; pcap->pca9556_transfer->i2c_version = I2C_XFER_REV; if (i2c_client_register(dip, &pcap->pca9556_hdl) != I2C_SUCCESS) { ddi_remove_minor_node(dip, NULL); cmn_err(CE_WARN, "%s i2c_client_register failed", pcap->pca9556_name); pca9556_detach(dip); return (DDI_FAILURE); } pcap->pca9556_flags |= PCA9556_REGFLAG; /* * Store the dip for future dip. */ pcap->pca9556_dip = dip; return (DDI_SUCCESS); }