/*ARGSUSED*/ uint8_t isadma_get8(ddi_acc_impl_t *hdlp, uint8_t *addr) { 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; uint8_t ret = 0xff; if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ #ifdef DEBUG isadma_punt++; #endif return (ddi_get8(phdl, addr)); } #ifdef DEBUG isadma_check_waiters(isadmap); #endif mutex_enter(&isadmap->isadma_access_lock); isadma_dmawait(isadmap); /* wait until on-going dma completes */ /* 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; ret = ddi_get8(phdl, addr); /* Pass to parent */ exit: isadma_wakeup(isadmap); mutex_exit(&isadmap->isadma_access_lock); return (ret); }
/*ARGSUSED*/ uint16_t isadma_get16(ddi_acc_impl_t *hdlp, uint16_t *addr) { 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; uint16_t ret = 0xffff; if (IN_CHILD_SPACE(offset)) { /* Pass to parent */ #ifdef DEBUG isadma_punt++; #endif return (ddi_get16(phdl, addr)); } #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); /* Read the low byte, then high byte */ ret = ddi_get8(phdl, (uint8_t *)addr); ret = (ddi_get8(phdl, (uint8_t *)addr) << 8) | ret; exit: isadma_wakeup(isadmap); mutex_exit(&isadmap->isadma_access_lock); return (ret); }
/* * Wait until the keyboard is fully up, maybe. * We may be the first person to talk to the keyboard, in which case * it's patiently waiting to say "AA" to us to tell us it's up. * In theory it sends the AA in 300ms < n < 9s, but it's a pretty * good bet that we've already spent that long getting to that point, * so we'll only wait long enough for the communications electronics to * run. */ static void kb8042_wait_poweron(struct kb8042 *kb8042) { int cnt; int ready; unsigned char byt; /* wait for up to 250 ms for a response */ for (cnt = 0; cnt < 250; cnt++) { ready = ddi_get8(kb8042->handle, kb8042->addr + I8042_INT_INPUT_AVAIL); if (ready != 0) break; drv_usecwait(1000); } /* * If there's something pending, read and discard it. If not, * assume things are OK anyway - maybe somebody else ate it * already. (On a PC, the BIOS almost certainly did.) */ if (ready != 0) { byt = ddi_get8(kb8042->handle, kb8042->addr + I8042_INT_INPUT_DATA); #if defined(KD_DEBUG) if (kb8042_low_level_debug) prom_printf(" <K:%x ", byt); #endif } }
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); }
static void rge_chip_peek_reg(rge_t *rgep, rge_peekpoke_t *ppd) { uint64_t regval; void *regaddr; RGE_TRACE(("rge_chip_peek_reg($%p, $%p)", (void *)rgep, (void *)ppd)); regaddr = PIO_ADDR(rgep, ppd->pp_acc_offset); switch (ppd->pp_acc_size) { case 1: regval = ddi_get8(rgep->io_handle, regaddr); break; case 2: regval = ddi_get16(rgep->io_handle, regaddr); break; case 4: regval = ddi_get32(rgep->io_handle, regaddr); break; case 8: regval = ddi_get64(rgep->io_handle, regaddr); break; } ppd->pp_acc_data = regval; }
static boolean_t kb8042_send_and_expect(struct kb8042 *kb8042, uint8_t send, uint8_t expect, boolean_t polled, int timeout, int *error, uint8_t *got) { int port = (polled == B_TRUE) ? I8042_POLL_INPUT_DATA : I8042_INT_INPUT_DATA; uint8_t datab; int err; boolean_t rval; kb8042_send_to_keyboard(kb8042, send, polled); if (kb8042_is_input_avail(kb8042, timeout, polled)) { err = 0; datab = ddi_get8(kb8042->handle, kb8042->addr + port); rval = ((datab == expect) ? B_TRUE : B_FALSE); } else { err = EAGAIN; rval = B_FALSE; } if (error != NULL) *error = err; if (got != NULL) *got = datab; return (rval); }
/* * Device configuration registers. */ uint8_t virtio_read_device_config_1(struct virtio_softc *sc, unsigned int index) { ASSERT(sc->sc_config_offset); return ddi_get8(sc->sc_ioh, (uint8_t *)(sc->sc_io_addr + sc->sc_config_offset + index)); }
uint_t virtio_intx_dispatch(caddr_t arg1, caddr_t arg2) { struct virtio_softc *sc = (void *)arg1; struct virtio_handler_container *vhc = (void *)arg2; uint8_t isr_status; int i; isr_status = ddi_get8(sc->sc_ioh, (uint8_t *)(sc->sc_io_addr + VIRTIO_CONFIG_ISR_STATUS)); if (!isr_status) return (DDI_INTR_UNCLAIMED); if ((isr_status & VIRTIO_CONFIG_ISR_CONFIG_CHANGE) && vhc->config_handler.vh_func) { vhc->config_handler.vh_func((void *)sc, vhc->config_handler.vh_priv); } /* Notify all handlers */ for (i = 0; i < vhc->nhandlers; i++) { vhc->vq_handlers[i].vh_func((void *)sc, vhc->vq_handlers[i].vh_priv); } return (DDI_INTR_CLAIMED); }
/* * 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 int mptsas_raidphydsk_page_0_cb(mptsas_t *mpt, caddr_t page_memp, ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, va_list ap) { #ifndef __lock_lint _NOTE(ARGUNUSED(ap)) #endif pMpi2RaidPhysDiskPage0_t diskpage; int rval = DDI_SUCCESS; uint16_t *devhdl; uint8_t *state; if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) return (DDI_FAILURE); if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { mptsas_log(mpt, CE_WARN, "mptsas_raidphydsk_page0_cb " "config: IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, iocloginfo); rval = DDI_FAILURE; return (rval); } devhdl = va_arg(ap, uint16_t *); state = va_arg(ap, uint8_t *); diskpage = (pMpi2RaidPhysDiskPage0_t)page_memp; *devhdl = ddi_get16(accessp, &diskpage->DevHandle); *state = ddi_get8(accessp, &diskpage->PhysDiskState); return (rval); }
static int mptsas_raidvol_page_1_cb(mptsas_t *mpt, caddr_t page_memp, ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo, va_list ap) { #ifndef __lock_lint _NOTE(ARGUNUSED(ap)) #endif pMpi2RaidVolPage1_t raidpage; int rval = DDI_SUCCESS, i; uint8_t *sas_addr = NULL; uint8_t tmp_sas_wwn[SAS_WWN_BYTE_SIZE]; uint64_t *sas_wwn; if (iocstatus != MPI2_IOCSTATUS_SUCCESS) { mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page_1_cb " "config: IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus, iocloginfo); rval = DDI_FAILURE; return (rval); } sas_wwn = va_arg(ap, uint64_t *); raidpage = (pMpi2RaidVolPage1_t)page_memp; sas_addr = (uint8_t *)(&raidpage->WWID); for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) { tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i); } bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE); *sas_wwn = LE_64(*sas_wwn); return (rval); }
static uint8_t rge_reg_get8(rge_t *rgep, uintptr_t regno) { RGE_TRACE(("rge_reg_get8($%p, 0x%lx)", (void *)rgep, regno)); return (ddi_get8(rgep->io_handle, REG8(rgep, regno))); }
static int kb8042_read_scanset(struct kb8042 *kb8042, boolean_t polled) { int scanset = -1; int port = (polled == B_TRUE) ? I8042_POLL_INPUT_DATA : I8042_INT_INPUT_DATA; int err; uint8_t got; kb8042_clear_input_buffer(kb8042, B_TRUE); /* * Send a "change scan code set" command to the keyboard. * It should respond with an ACK. */ if (kb8042_send_and_expect(kb8042, KB_SET_SCAN, KB_ACK, polled, MAX_WAIT_USECS, &err, &got) != B_TRUE) { goto fail_read_scanset; } /* * Send a 0. The keyboard should ACK the 0, then it send the scan code * set in use. */ if (kb8042_send_and_expect(kb8042, 0, KB_ACK, polled, MAX_WAIT_USECS, &err, &got) != B_TRUE) { goto fail_read_scanset; } /* * The next input byte from the keyboard should be the scan code * set in use, though some keyboards like to send a few more acks * just for fun, so blow past those to get the keyboard scan code. */ while (kb8042_is_input_avail(kb8042, MAX_WAIT_USECS, B_TRUE) && (scanset = ddi_get8(kb8042->handle, kb8042->addr + port)) == KB_ACK) ; #ifdef KD_DEBUG cmn_err(CE_NOTE, "!Scan code set from keyboard is `%d'.", scanset); #endif return (scanset); fail_read_scanset: #ifdef KD_DEBUG if (err == 0) cmn_err(CE_NOTE, "Could not read current scan set from " "keyboard: %s. (Expected 0x%x, but got 0x%x).", kb8042_error_string(err), KB_ACK, got); else cmn_err(CE_NOTE, "Could not read current scan set from " "keyboard: %s.", kb8042_error_string(err)); #endif return (-1); }
/* * Called from interrupt handler when keyboard interrupt occurs. */ static uint_t kb8042_intr(caddr_t arg) { uchar_t scancode; /* raw scan code */ int rc; struct kb8042 *kb8042 = (struct kb8042 *)arg; rc = DDI_INTR_UNCLAIMED; if (kb8042->init_state == KB8042_UNINITIALIZED) return (DDI_INTR_UNCLAIMED); /* don't care if drv_setparm succeeds */ (void) drv_setparm(SYSRINT, 1); while (ddi_get8(kb8042->handle, kb8042->addr + I8042_INT_INPUT_AVAIL) != 0) { rc = DDI_INTR_CLAIMED; scancode = ddi_get8(kb8042->handle, kb8042->addr + I8042_INT_INPUT_DATA); #if defined(KD_DEBUG) if (kb8042_low_level_debug) prom_printf(" <K:%x ", scancode); #endif mutex_enter(&kb8042->w_hw_mutex); if (kb8042_state_machine(kb8042, scancode, B_FALSE) != STATE_NORMAL) { mutex_exit(&kb8042->w_hw_mutex); continue; } mutex_exit(&kb8042->w_hw_mutex); kb8042_received_byte(kb8042, scancode); } return (rc); }
static void kb8042_clear_input_buffer(struct kb8042 *kb8042, boolean_t polled) { int port = (polled == B_TRUE) ? I8042_POLL_INPUT_DATA : I8042_INT_INPUT_DATA; while (kb8042_is_input_avail(kb8042, MIN_DELAY_USECS, polled)) { (void) ddi_get8(kb8042->handle, kb8042->addr + port); } }
/** * Virtio Pci get (read) routine. * * @param pDevice Pointer to the Virtio device instance. * @param off Offset into the PCI config space. * @param pv Where to store the read data. * @param cb Size of the buffer in bytes. */ static void VirtioPciGet(PVIRTIODEVICE pDevice, off_t off, void *pv, size_t cb) { LogFlowFunc((VIRTIOLOGNAME ":VirtioPciGet pDevice=%p off=%u pv=%p cb=%u\n", pDevice, off, pv, cb)); virtio_pci_t *pPciData = pDevice->pvHyper; AssertReturnVoid(pPciData); uint8_t *pb = pv; for (size_t i = 0; i < cb; i++, pb++) *pb = ddi_get8(pPciData->hIO, (uint8_t *)(pPciData->addrIOBase + VIRTIO_PCI_CONFIG + off + i)); }
uint8_t pci_config_get8(ddi_acc_handle_t handle, off_t offset) { caddr_t cfgaddr; ddi_acc_hdl_t *hp; hp = impl_acc_hdl_get(handle); cfgaddr = hp->ah_addr + offset; return (ddi_get8(handle, (uint8_t *)cfgaddr)); }
static uint8_t sio_get_reg(struct rmc_comm_state *rcs, uint_t reg) { uint8_t val; if (rcs->sd_state.sio_handle && !rcs->sd_state.sio_fault) val = ddi_get8(rcs->sd_state.sio_handle, rcs->sd_state.sio_regs + reg); else val = DUMMY_VALUE; DPRINTF(rcs, DSER, (CE_CONT, "$%02x<-REG[%d]", val, reg)); return (val); }
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); }
/* * Read from the PCF8574 chip. * byteaddress = chip type base address | chip offset address. */ int ehc_read_pcf8574(struct ehc_envcunit *ehcp, int byteaddress, uint8_t *buf, int size) { int i; int status; uint8_t discard; ASSERT((byteaddress & 0x1) == 0); ASSERT(MUTEX_HELD(&ehcp->umutex)); /* * Put the bus into the start condition */ if ((status = ehc_start_pcf8584(ehcp, EHC_BYTE_READ | byteaddress)) != EHC_SUCCESS) { if (status == EHC_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); } for (i = 0; i < size - 1; i++) { if ((status = ehc_read_pcf8584(ehcp, &buf[i])) != EHC_SUCCESS) { return (EHC_FAILURE); } } /* * Handle the part of the bus protocol which comes * after a read. */ if (ehc_after_read_pcf8584(ehcp, &buf[i]) != EHC_SUCCESS) { return (EHC_FAILURE); } return (EHC_SUCCESS); }
static int ehc_read_pcf8584(struct ehc_envcunit *ehcp, uint8_t *data) { uint8_t poll_status; int i = 0; /* Read the byte of interest */ *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_read_pcf8584(): read of S1 failed"); return (EHC_FAILURE); } if (poll_status & EHC_S1_BER) { DCMN2_ERR(CE_WARN, "ehc_read_pcf8584(): Bus error"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } if (poll_status & EHC_S1_LAB) { DCMN2_ERR(CE_WARN, "ehc_read_pcf8584(): Lost Arbitration"); ehc_init_pcf8584(ehcp); return (EHC_FAILURE); } return (EHC_SUCCESS); }
static boolean_t kb8042_is_input_avail(struct kb8042 *kb8042, int timeout_usec, boolean_t polled) { int i; int port = (polled == B_TRUE) ? I8042_POLL_INPUT_AVAIL : I8042_INT_INPUT_AVAIL; int reps = timeout_usec / USECS_PER_WAIT; for (i = 0; i < reps; i++) { if (ddi_get8(kb8042->handle, kb8042->addr + port) != 0) return (B_TRUE); if (i < (reps - 1)) drv_usecwait(USECS_PER_WAIT); } return (B_FALSE); }
static void mouse8042_reset_timeout(void *argp) { struct mouse_state *state = (struct mouse_state *)argp; mblk_t *mp; mutex_enter(&state->reset_mutex); /* * If the interrupt handler hasn't completed the reset handling * (reset_state would be IDLE or FAILED in that case), then * drop the 8042 lock, and send a faked retry reply upstream, * then enable the queue for further message processing. */ if (state->reset_state != MSE_RESET_IDLE && state->reset_state != MSE_RESET_FAILED) { state->reset_tid = 0; state->reset_state = MSE_RESET_IDLE; cv_signal(&state->reset_cv); (void) ddi_get8(state->ms_handle, state->ms_addr + I8042_UNLOCK); mp = state->reply_mp; *mp->b_wptr++ = MSERESEND; state->reply_mp = NULL; if (state->ms_rqp != NULL) putnext(state->ms_rqp, mp); else freemsg(mp); ASSERT(state->ms_wqp != NULL); enableok(state->ms_wqp); qenable(state->ms_wqp); } mutex_exit(&state->reset_mutex); }
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); }
/* * 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); } }
/* * 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); }
/* 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); }
uint8_t ipw2200_csr_get8(struct ipw2200_softc *sc, uint32_t off) { return (ddi_get8(sc->sc_ioh, (uint8_t *)(sc->sc_regs + off))); }
/* * 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); }
int gfxp_vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd, gfxp_vgatext_softc_ptr_t ptr) { struct vgatext_softc *softc = (struct vgatext_softc *)ptr; int unit = ddi_get_instance(devi); int error; char *parent_type = NULL; int reg_rnumber; off_t reg_offset; off_t mem_offset; char *cons; int pci_pcie_bus = 0; int value; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: vgatext_resume(softc); return (DDI_SUCCESS); default: return (DDI_FAILURE); } /* DDI_ATTACH */ softc->devi = devi; /* Copy and init DEVI */ softc->polledio.arg = (struct vis_polledio_arg *)softc; softc->polledio.display = vgatext_polled_display; softc->polledio.copy = vgatext_polled_copy; softc->polledio.cursor = vgatext_polled_cursor; mutex_init(&(softc->lock), NULL, MUTEX_DRIVER, NULL); error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi), DDI_PROP_DONTPASS, "device_type", &parent_type); if (error != DDI_SUCCESS) { cmn_err(CE_WARN, MYNAME ": can't determine parent type."); goto fail; } /* Not enable AGP and DRM by default */ if (STREQ(parent_type, "isa") || STREQ(parent_type, "eisa")) { reg_rnumber = vgatext_get_isa_reg_index(devi, 1, VGA_REG_ADDR, ®_offset); if (reg_rnumber < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for registers"); error = DDI_FAILURE; goto fail; } softc->fb_regno = vgatext_get_isa_reg_index(devi, 0, VGA_MEM_ADDR, &mem_offset); if (softc->fb_regno < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for memory"); error = DDI_FAILURE; goto fail; } } else if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) { pci_pcie_bus = 1; reg_rnumber = vgatext_get_pci_reg_index(devi, PCI_REG_ADDR_M|PCI_REG_REL_M, PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR, ®_offset); if (reg_rnumber < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for registers"); error = DDI_FAILURE; goto fail; } softc->fb_regno = vgatext_get_pci_reg_index(devi, PCI_REG_ADDR_M|PCI_REG_REL_M, PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR, &mem_offset); if (softc->fb_regno < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for memory"); error = DDI_FAILURE; goto fail; } } else { cmn_err(CE_WARN, MYNAME ": unknown parent type \"%s\".", parent_type); error = DDI_FAILURE; goto fail; } ddi_prop_free(parent_type); parent_type = NULL; error = ddi_regs_map_setup(devi, reg_rnumber, (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE, &dev_attr, &softc->regs.handle); if (error != DDI_SUCCESS) goto fail; softc->regs.mapped = B_TRUE; softc->fb_size = VGA_MEM_SIZE; error = ddi_regs_map_setup(devi, softc->fb_regno, (caddr_t *)&softc->fb.addr, mem_offset, softc->fb_size, &dev_attr, &softc->fb.handle); if (error != DDI_SUCCESS) goto fail; softc->fb.mapped = B_TRUE; if (ddi_get8(softc->regs.handle, softc->regs.addr + VGA_MISC_R) & VGA_MISC_IOA_SEL) softc->text_base = (caddr_t)softc->fb.addr + VGA_COLOR_BASE; else softc->text_base = (caddr_t)softc->fb.addr + VGA_MONO_BASE; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) { if (strcmp(cons, "graphics") == 0) { happyface_boot = 1; vgatext_silent = 1; softc->current_base = softc->shadow; } else { softc->current_base = softc->text_base; } ddi_prop_free(cons); } else { softc->current_base = softc->text_base; } error = ddi_prop_create(makedevice(DDI_MAJOR_T_UNKNOWN, unit), devi, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0); if (error != DDI_SUCCESS) goto fail; gfxp_check_for_console(devi, softc, pci_pcie_bus); value = GFXP_IS_CONSOLE(softc) ? 1 : 0; if (ddi_prop_update_int(DDI_DEV_T_NONE, devi, "primary-controller", value) != DDI_SUCCESS) { cmn_err(CE_WARN, "Can not %s primary-controller " "property for driver", value ? "set" : "clear"); } /* only do this if not in graphics mode */ if ((vgatext_silent == 0) && (GFXP_IS_CONSOLE(softc))) { vgatext_init(softc); vgatext_save_colormap(softc); } return (DDI_SUCCESS); fail: if (parent_type != NULL) ddi_prop_free(parent_type); (void) gfxp_vgatext_detach(devi, DDI_DETACH, (void *)softc); return (error); }