/*ARGSUSED*/ void isadma_put16(ddi_acc_impl_t *hdlp, uint16_t *addr, uint16_t value) { ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private; isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private; off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr; if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ #ifdef DEBUG isadma_punt++; #endif ddi_put16(phdl, addr, value); return; } #ifdef DEBUG isadma_check_waiters(isadmap); #endif mutex_enter(&isadmap->isadma_access_lock); isadma_dmawait(isadmap); /* wait until on-going dma completes */ /* Only Allow access to the 16 bit count and address registers */ if (!IN_16BIT_SPACE(offset)) goto exit; /* Set the sequencing register to the low byte */ ddi_put8(phdl, (uint8_t *)HDL_TO_SEQREG_ADDR(hdlp, offset), 0); /* Write the low byte, then the high byte */ ddi_put8(phdl, (uint8_t *)addr, value & 0xff); ddi_put8(phdl, (uint8_t *)addr, (value >> 8) & 0xff); exit: isadma_wakeup(isadmap); mutex_exit(&isadmap->isadma_access_lock); }
void ehc_init_pcf8584(struct ehc_envcunit *ehcp) { /* * Writing PIN bit of S1 causes software reset. * The next write to S0 will be S0' "own address". */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_PIN); /* * Write the address which the controller chip will use * (when addressed as a slave) on the I2C bus. * DAF - should own address be passed as argument? */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, EHC_S0_OWN); /* * Writing PIN bit and ES1 bit of S1 causes software * reset and selects the S2 register for writing. * Now, the next write to S0 will be the S2 clock * control register. */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_PIN | EHC_S1_ES1); /* * Write the value into register that sets internal system clock * to 12 Mhz, and the I2C bus rate (SCL) to 9 Khz. * DAF - should these be parameters? */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, EHC_S0_CLK); /* * Writing PIN bit causes software reset and the ES0 bit * selects the (S0) register for reading/writing. The ACK * bit being set causes controller to send ACK after each * byte. */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_ACK); /* * Multi-Master: Wait for a period of time equal to the * longest I2C message. This accounts for the case * where multiple controllers and, if this particular one * is "lagging", misses the BB (bus busy) condition. * DAF - What does this need? * We wait 200 ms since the longest transaction at this time * on the i2c bus is a 256 byte read from the seprom which takes * about 75 ms. Some additional buffer does no harm to the driver. */ drv_usecwait(EHC_LONGEST_MSG); }
/*ARGSUSED*/ void isadma_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value) { ddi_acc_handle_t phdl = hdlp->ahi_common.ah_platform_private; isadma_devstate_t *isadmap = hdlp->ahi_common.ah_bus_private; off_t offset = (caddr_t)addr - hdlp->ahi_common.ah_addr; if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ #ifdef DEBUG isadma_punt++; #endif ddi_put8(phdl, addr, value); return; } #ifdef DEBUG isadma_check_waiters(isadmap); #endif mutex_enter(&isadmap->isadma_access_lock); if (isadmap->isadma_ldip == hdlp->ahi_common.ah_dip) { /* owned lock? */ if (END_ISADMA(offset, value)) { isadmap->isadma_ldip = NULL; /* reset lock owner */ #ifdef DEBUG isadma_clearing_wdip++; #endif } } else { /* we don't own the lock */ /* wait until on-going dma completes */ isadma_dmawait(isadmap); if (BEGIN_ISADMA(offset, value)) { isadmap->isadma_ldip = hdlp->ahi_common.ah_dip; #ifdef DEBUG isadma_setting_wdip++; #endif } } /* No 8 bit access to 16 bit address or count registers */ if (IN_16BIT_SPACE(offset)) goto exit; /* No 8 bit access to first/last flip-flop registers */ if (IS_SEQREG(offset)) goto exit; ddi_put8(phdl, addr, value); /* Pass to parent */ exit: isadma_wakeup(isadmap); mutex_exit(&isadmap->isadma_access_lock); }
static void kb8042_send_to_keyboard(struct kb8042 *kb8042, int byte, boolean_t polled) { if (polled) { ddi_put8(kb8042->handle, kb8042->addr + I8042_POLL_OUTPUT_DATA, byte); } else { ddi_put8(kb8042->handle, kb8042->addr + I8042_INT_OUTPUT_DATA, byte); } #if defined(KD_DEBUG) if (kb8042_low_level_debug) prom_printf(" >K:%x ", byte); #endif }
/* * Generate an SBBC interrupt to the SC * Called from iosram_send_intr() * * send_intr == 0, check if EPLD register clear * for sync'ing SC/OS * send_intr == 1, send the interrupt */ int sbbc_send_intr(sbbc_softstate_t *softsp, int send_intr) { uchar_t *epld_int; volatile uchar_t epld_status; ASSERT(MUTEX_HELD(&master_iosram->iosram_lock)); if ((softsp == (sbbc_softstate_t *)NULL) || (softsp->epld_regs == (struct sbbc_epld_regs *)NULL)) return (ENXIO); /* * Check the L1 EPLD Interrupt register. If the * interrupt bit is set, theres an interrupt outstanding * (we assume) so return (EBUSY). */ epld_int = &softsp->epld_regs->epld_reg[EPLD_INTERRUPT]; epld_status = ddi_get8(softsp->sbbc_reg_handle2, epld_int); if (epld_status & INTERRUPT_ON) return (EBUSY); if (send_intr == TRUE) ddi_put8(softsp->sbbc_reg_handle2, epld_int, (epld_status | INTERRUPT_ON)); return (0); }
static void fipe_ioat_cancel(void) { uint32_t status; uint8_t *addr = fipe_ioat_ctrl.ioat_reg_addr; ddi_acc_handle_t handle = fipe_ioat_ctrl.ioat_reg_handle; /* * Reset channel. Sometimes reset is not reliable, * so check completion or abort status after reset. */ /* LINTED: constant in conditional context */ while (1) { /* Issue reset channel command. */ ddi_put8(handle, (uint8_t *)(addr + FIPE_IOAT_CHAN_CMD), 0x20); /* Query command status. */ status = ddi_get32(handle, (uint32_t *)(addr + FIPE_IOAT_CHAN_STS_LO)); if (status & 0x1) { /* Reset channel completed. */ break; } else { SMT_PAUSE(); } } /* Put channel into "not in use" state. */ ddi_put16(handle, (uint16_t *)(addr + FIPE_IOAT_CHAN_CTRL), 0); }
static void rge_chip_poke_reg(rge_t *rgep, rge_peekpoke_t *ppd) { uint64_t regval; void *regaddr; RGE_TRACE(("rge_chip_poke_reg($%p, $%p)", (void *)rgep, (void *)ppd)); regaddr = PIO_ADDR(rgep, ppd->pp_acc_offset); regval = ppd->pp_acc_data; switch (ppd->pp_acc_size) { case 1: ddi_put8(rgep->io_handle, regaddr, regval); break; case 2: ddi_put16(rgep->io_handle, regaddr, regval); break; case 4: ddi_put32(rgep->io_handle, regaddr, regval); break; case 8: ddi_put64(rgep->io_handle, regaddr, regval); break; } }
static void rge_reg_put8(rge_t *rgep, uintptr_t regno, uint8_t data) { RGE_TRACE(("rge_reg_put8($%p, 0x%lx, 0x%x)", (void *)rgep, regno, data)); ddi_put8(rgep->io_handle, REG8(rgep, regno), data); }
void virtio_write_device_config_1(struct virtio_softc *sc, unsigned int index, uint8_t value) { ASSERT(sc->sc_config_offset); ddi_put8(sc->sc_ioh, (uint8_t *)(sc->sc_io_addr + sc->sc_config_offset + index), value); }
/* * Returns 1 if the caller should stop processing messages */ static int mouse8042_process_data_msg(queue_t *q, mblk_t *mp, struct mouse_state *state) { mblk_t *bp; mblk_t *next; bp = mp; do { while (bp->b_rptr < bp->b_wptr) { /* * Detect an attempt to reset the mouse. Lock out any * further mouse writes until the reset has completed. */ if (*bp->b_rptr == MSERESET) { /* * If we couldn't allocate memory and we * we couldn't register a bufcall, * mouse8042_initiate_reset returns 0 and * has already used the message to send an * error reply back upstream, so there is no * need to deallocate or put this message back * on the queue. */ if (mouse8042_initiate_reset(q, bp, state) == 0) return (1); /* * If there's no data remaining in this block, * free this block and put the following blocks * of this message back on the queue. If putting * the rest of the message back on the queue * fails, free the the message. */ if (MBLKL(bp) == 0) { next = bp->b_cont; freeb(bp); bp = next; } if (bp != NULL) { if (!putbq(q, bp)) freemsg(bp); } return (1); } ddi_put8(state->ms_handle, state->ms_addr + I8042_INT_OUTPUT_DATA, *bp->b_rptr++); } next = bp->b_cont; freeb(bp); } while ((bp = next) != NULL); return (0); }
static int ehc_after_read_pcf8584(struct ehc_envcunit *ehcp, uint8_t *data) { uint8_t discard; uint8_t poll_status; int i = 0; /* set ACK in register S1 to 0 */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_ES0); /* * Read the "byte-before-the-last-byte" - sets PIN bit to '1' */ *data = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0); /* wait for completion of transmission */ do { drv_usecwait(1000); poll_status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_after_rd_pcf8584(): read of S1 failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_after_rd_pcf8584(): Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_after_rd_pcf8584(): Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } /* * Generate the "stop" condition. */ ehc_stop_pcf8584(ehcp); /* * Read the "last" byte. */ discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0); #ifdef lint discard = discard; #endif return (EHC_SUCCESS); }
/** * Virtio Pci set (write) routine. * * @param pDevice Pointer to the Virtio device instance. * @param off Offset into the PCI config space. * @param pv Pointer to the buffer to write from. * @param cb Size of the buffer in bytes. */ static void VirtioPciSet(PVIRTIODEVICE pDevice, off_t off, void *pv, size_t cb) { LogFlowFunc((VIRTIOLOGNAME ":VirtioPciSet pDevice=%p\n", pDevice)); virtio_pci_t *pPciData = pDevice->pvHyper; AssertReturnVoid(pPciData); uint8_t *pb = pv; for (size_t i = 0; i < cb; i++, pb++) ddi_put8(pPciData->hIO, (uint8_t *)(pPciData->addrIOBase + VIRTIO_PCI_CONFIG + off + i), *pb); }
void pci_config_putb(ddi_acc_handle_t handle, off_t offset, uint8_t value) { caddr_t cfgaddr; ddi_acc_hdl_t *hp; hp = impl_acc_hdl_get(handle); cfgaddr = hp->ah_addr + offset; ddi_put8(handle, (uint8_t *)cfgaddr, value); }
/* * Lowest-level serial I/O chip register read/write */ static void sio_put_reg(struct rmc_comm_state *rcs, uint_t reg, uint8_t val) { DPRINTF(rcs, DSER, (CE_CONT, "REG[%d]<-$%02x", reg, val)); if (rcs->sd_state.sio_handle != NULL && !rcs->sd_state.sio_fault) { /* * The chip is mapped as "I/O" (e.g. with the side-effect * bit on SPARC), therefore accesses are required to be * in-order, with no value cacheing. However, there can * still be write-behind buffering, so it is not guaranteed * that a write actually reaches the chip in a given time. * * To force the access right through to the chip, we follow * the write with another write (to the SCRATCH register) * and a read (of the value just written to the SCRATCH * register). The SCRATCH register is specifically provided * for temporary data and has no effect on the SIO's own * operation, making it ideal as a synchronising mechanism. * * If we didn't do this, it would be possible that the new * value wouldn't reach the chip (and have the *intended* * side-effects, such as disabling interrupts), for such a * long time that the processor could execute a *lot* of * instructions - including exiting the interrupt service * routine and re-enabling interrupts. This effect was * observed to lead to spurious (unclaimed) interrupts in * some circumstances. * * This will no longer be needed once "synchronous" access * handles are available (see PSARC/2000/269 and 2000/531). */ ddi_put8(rcs->sd_state.sio_handle, rcs->sd_state.sio_regs + reg, val); ddi_put8(rcs->sd_state.sio_handle, rcs->sd_state.sio_regs + SIO_SCR, val); membar_sync(); (void) ddi_get8(rcs->sd_state.sio_handle, rcs->sd_state.sio_regs + SIO_SCR); } }
void virtio_set_status(struct virtio_softc *sc, unsigned int status) { int old = 0; if (status != 0) { old = ddi_get8(sc->sc_ioh, (uint8_t *)(sc->sc_io_addr + VIRTIO_CONFIG_DEVICE_STATUS)); } ddi_put8(sc->sc_ioh, (uint8_t *)(sc->sc_io_addr + VIRTIO_CONFIG_DEVICE_STATUS), status | old); }
static int fipe_ioat_trigger(void) { uint16_t ctrl; uint32_t err; uint8_t *addr = fipe_ioat_ctrl.ioat_reg_addr; ddi_acc_handle_t handle = fipe_ioat_ctrl.ioat_reg_handle; /* Check channel in use flag. */ ctrl = ddi_get16(handle, (uint16_t *)(addr + FIPE_IOAT_CHAN_CTRL)); if (ctrl & 0x100) { /* * Channel is in use by somebody else. IOAT driver may have * been loaded, forbid fipe from accessing IOAT hardware * anymore. */ fipe_ioat_ctrl.ioat_ready = B_FALSE; fipe_ioat_ctrl.ioat_failed = B_TRUE; FIPE_KSTAT_INC(ioat_start_fail_cnt); return (-1); } else { /* Set channel in use flag. */ ddi_put16(handle, (uint16_t *)(addr + FIPE_IOAT_CHAN_CTRL), 0x100); } /* Write command address. */ ddi_put32(handle, (uint32_t *)(addr + FIPE_IOAT_CHAN_ADDR_LO), (uint32_t)fipe_ioat_ctrl.ioat_cmd_physaddr); ddi_put32(handle, (uint32_t *)(addr + FIPE_IOAT_CHAN_ADDR_HI), (uint32_t)(fipe_ioat_ctrl.ioat_cmd_physaddr >> 32)); /* Check and clear error flags. */ err = ddi_get32(handle, (uint32_t *)(addr + FIPE_IOAT_CHAN_ERR)); if (err != 0) { ddi_put32(handle, (uint32_t *)(addr + FIPE_IOAT_CHAN_ERR), err); } /* Start channel. */ ddi_put8(handle, (uint8_t *)(addr + FIPE_IOAT_CHAN_CMD), 0x1); return (0); }
static int ehc_write_pcf8584(struct ehc_envcunit *ehcp, uint8_t data) { uint8_t poll_status; int i = 0; /* send the data, EHC_S1_PIN should go to "1" immediately */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, data); /* wait for completion of transmission */ do { drv_usecwait(1000); poll_status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_write_pcf8584(): read of S1 failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_write_pcf8584(): Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_write_pcf8584(): Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LRB) { DCMN_ERR(CE_WARN, "ehc_write_pcf8584(): No slave ACK"); return (EHC_NO_SLAVE_ACK); } return (EHC_SUCCESS); }
/* * put host interface into slave/receiver mode */ static void ehc_stop_pcf8584(struct ehc_envcunit *ehcp) { ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STO | EHC_S1_ACK); }
/* * put host interface into master mode */ static int ehc_start_pcf8584(struct ehc_envcunit *ehcp, uint8_t byteaddress) { uint8_t poll_status; uint8_t discard; int i; /* wait if bus is busy */ i = 0; do { drv_usecwait(1000); poll_status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while (((poll_status & EHC_S1_NBB) == 0) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): busy bit clear failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()1: Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()1: Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } /* * This is a dummy arbitration using the lowest unused address * possible. This step allows the PCF8584 to always win arbitration * except in the case of "general call" being issued by the other * master. */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, DUMMY_WRITE_ADDR); /* generate the "start condition" and clock out the slave address */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_PIN | EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK); /* wait for completion of transmission */ i = 0; do { drv_usecwait(1000); poll_status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_start_pcf8584_5(): read of S1 failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()5: Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()5: Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } /* dummy write */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, DUMMY_WRITE_DATA); /* wait for completion of transmission */ i = 0; do { drv_usecwait(1000); poll_status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): read of S1 failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()4: Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()4: Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } /* * generate the repeated "start condition" and * clock out the slave address */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK); /* load the slave address */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, byteaddress); /* wait for completion of transmission */ i = 0; do { drv_usecwait(1000); poll_status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): read of S1 failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()2: Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()2: Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LRB) { DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): No slave ACK"); return (EHC_NO_SLAVE_ACK); } /* * If this is a read we are setting up for (as indicated by * the least significant byte being set), read * and discard the first byte off the bus - this * is the slave address. */ i = 0; if (byteaddress & EHC_BYTE_READ) { discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0); #ifdef lint discard = discard; #endif /* wait for completion of transmission */ do { drv_usecwait(1000); poll_status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while ((poll_status & EHC_S1_PIN) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_start_pcf8584(): read of S1 failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()3: Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_start_pcf8584()3: Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } } return (EHC_SUCCESS); }
/* ARGSUSED */ static int gpio_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp) { int instance = getminor(dev); struct gpio_softc *softc = getsoftc(instance); gpio_87317_op_t info; uint8_t byte; DBG(softc->gp_dip, "ioctl: instance is %d", instance, 0, 0, 0, 0); if (softc == NULL) return (ENXIO); /* Copy the command from user space. */ if (ddi_copyin((caddr_t)arg, (caddr_t)&info, sizeof (gpio_87317_op_t), mode) != 0) return (EFAULT); /* Check the command arguments. We only support port 1 in bank 0. */ if ((info.gpio_bank != 0) || (info.gpio_offset != GPIO_87317_PORT1_DATA)) { return (EINVAL); } /* Grap the instance's mutex to insure exclusive access. */ mutex_enter(&softc->gp_mutex); /* Get the contents of the GPIO register we're suppose to modify. */ byte = ddi_get8(softc->gp_handle, &softc->gp_regs[info.gpio_offset]); switch (cmd) { case GPIO_CMD_SET_BITS: DBG(softc->gp_dip, "ioctl: SET_BITS, byte is %x", byte, 0, 0, 0, 0); byte |= info.gpio_data; ddi_put8(softc->gp_handle, &softc->gp_regs[info.gpio_offset], byte); byte = ddi_get8(softc->gp_handle, &softc->gp_regs[info.gpio_offset]); DBG(softc->gp_dip, "ioctl: SET_BITS, byte is %x", byte, 0, 0, 0, 0); break; case GPIO_CMD_CLR_BITS: DBG(softc->gp_dip, "ioctl: CLR_BITS, byte is %x", byte, 0, 0, 0, 0); byte &= ~info.gpio_data; ddi_put8(softc->gp_handle, &softc->gp_regs[info.gpio_offset], byte); byte = ddi_get8(softc->gp_handle, &softc->gp_regs[info.gpio_offset]); DBG(softc->gp_dip, "ioctl: CLR_BITS, byte is %x", byte, 0, 0, 0, 0); break; case GPIO_CMD_GET: DBG(softc->gp_dip, "ioctl: GPIO_CMD_GET", 0, 0, 0, 0, 0); info.gpio_data = byte; if (ddi_copyout((caddr_t)&info, (caddr_t)arg, sizeof (gpio_87317_op_t), mode) != 0) { mutex_exit(&softc->gp_mutex); return (EFAULT); } break; case GPIO_CMD_SET: DBG(softc->gp_dip, "ioctl: GPIO_CMD_SET", 0, 0, 0, 0, 0); ddi_put8(softc->gp_handle, &softc->gp_regs[info.gpio_offset], info.gpio_data); break; default: mutex_exit(&softc->gp_mutex); return (EINVAL); } mutex_exit(&softc->gp_mutex); return (0); }
void ipw2200_csr_put8(struct ipw2200_softc *sc, uint32_t off, uint8_t val) { ddi_put8(sc->sc_ioh, (uint8_t *)(sc->sc_regs + off), val); }
/* * Read from the PCF8591 chip. */ int ehc_read_pcf8591(struct ehc_envcunit *ehcp, int byteaddress, int channel, int autoinc, int amode, int aenable, uint8_t *buf, int size) { int i; int status; register uint8_t control; uint8_t discard; ASSERT((byteaddress & 0x1) == 0); ASSERT(channel < 4); ASSERT(amode < 4); ASSERT(MUTEX_HELD(&ehcp->umutex)); /* * Write the control word to the PCF8591. * Follow the control word with a repeated START byte * rather than a STOP so that reads can follow without giving * up the bus. */ control = ((aenable << 6) | (amode << 4) | (autoinc << 2) | channel); if ((status = ehc_start_pcf8584(ehcp, byteaddress)) != EHC_SUCCESS) { if (status == EHC_NO_SLAVE_ACK) { ehc_stop_pcf8584(ehcp); } return (EHC_FAILURE); } if ((status = ehc_write_pcf8584(ehcp, control)) != EHC_SUCCESS) { if (status == EHC_NO_SLAVE_ACK) ehc_stop_pcf8584(ehcp); return (EHC_FAILURE); } /* * The following two operations, 0x45 to S1, and the byteaddress * to S0, will result in a repeated START being sent out on the bus. * Refer to Fig.8 of Philips Semiconductors PCF8584 product spec. */ ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1, EHC_S1_ES0 | EHC_S1_STA | EHC_S1_ACK); ddi_put8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0, EHC_BYTE_READ | byteaddress); i = 0; do { drv_usecwait(1000); status = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s1); i++; } while ((status & EHC_S1_PIN) && i < EHC_MAX_WAIT); if (i == EHC_MAX_WAIT) { DCMN_ERR(CE_WARN, "ehc_read_pcf8591(): read of S1 failed"); return (EHC_FAILURE); } if (status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_read_pcf8591(): Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_read_pcf8591(): Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (status & EHC_S1_LRB) { DCMN_ERR(CE_WARN, "ehc_read_pcf8591(): No slave ACK"); /* * Send the stop condition. */ ehc_stop_pcf8584(ehcp); /* * Read the last byte - discard it. */ discard = ddi_get8(ehcp->ctlr_handle, &ehcp->bus_ctl_regs->s0); #ifdef lint discard = discard; #endif return (EHC_FAILURE); } /* * Discard first read as per PCF8584 master receiver protocol. * This is normally done in the ehc_start_pcf8584() routine. */ if ((status = ehc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) { return (EHC_FAILURE); } /* Discard second read as per PCF8591 protocol */ if ((status = ehc_read_pcf8584(ehcp, &discard)) != EHC_SUCCESS) { return (EHC_FAILURE); } for (i = 0; i < size - 1; i++) { if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) { return (EHC_FAILURE); } } if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) { return (EHC_FAILURE); } return (EHC_SUCCESS); }
/* * Returns 1 if the caller should put the message (bp) back on the queue */ static int mouse8042_initiate_reset(queue_t *q, mblk_t *mp, struct mouse_state *state) { mutex_enter(&state->reset_mutex); /* * If we're in the middle of a reset, put the message back on the queue * for processing later. */ if (state->reset_state != MSE_RESET_IDLE) { /* * We noenable the queue again here in case it was backenabled * by an upper-level module. */ noenable(q); mutex_exit(&state->reset_mutex); return (1); } /* * Drop the reset state lock before allocating the response message and * grabbing the 8042 exclusive-access lock (since those operations * may take an extended period of time to complete). */ mutex_exit(&state->reset_mutex); if (state->reply_mp == NULL) state->reply_mp = allocb(2, BPRI_MED); if (state->reset_ack_mp == NULL) state->reset_ack_mp = allocb(1, BPRI_MED); if (state->reply_mp == NULL || state->reset_ack_mp == NULL) { /* * Allocation failed -- set up a bufcall to enable the queue * whenever there is enough memory to allocate the response * message. */ state->bc_id = qbufcall(q, (state->reply_mp == NULL) ? 2 : 1, BPRI_MED, (void (*)(void *))qenable, q); if (state->bc_id == 0) { /* * If the qbufcall failed, we cannot proceed, so use the * message we were sent to respond with an error. */ *mp->b_rptr = MSEERROR; mp->b_wptr = mp->b_rptr + 1; qreply(q, mp); return (0); } return (1); } else { /* Bufcall completed successfully (or wasn't needed) */ state->bc_id = 0; } /* * Gain exclusive access to the 8042 for the duration of the reset. * The unlock will occur when the reset has either completed or timed * out. */ (void) ddi_get8(state->ms_handle, state->ms_addr + I8042_LOCK); mutex_enter(&state->reset_mutex); state->reset_state = MSE_RESET_PRE; noenable(q); state->reset_tid = qtimeout(q, mouse8042_reset_timeout, state, drv_usectohz( MOUSE8042_RESET_TIMEOUT_USECS)); ddi_put8(state->ms_handle, state->ms_addr + I8042_INT_OUTPUT_DATA, MSERESET); mp->b_rptr++; mutex_exit(&state->reset_mutex); return (1); }