Example #1
0
/*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);
}
Example #2
0
/*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);
}
Example #3
0
/*
 * 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;
}
Example #6
0
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);
}
Example #7
0
/*
 * 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));
}
Example #8
0
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);
}
Example #9
0
/*
 * 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);
}
Example #10
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);
}
Example #11
0
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);
}
Example #12
0
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)));
}
Example #13
0
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);
}
Example #14
0
/*
 * 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);
}
Example #15
0
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);
	}
}
Example #16
0
/**
 * 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));
}
Example #17
0
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));
}
Example #18
0
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);
}
Example #19
0
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);
}
Example #22
0
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);
}
Example #25
0
/*
 * 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);
}
Example #27
0
/* 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,
		    &reg_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,
		    &reg_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);
}