Example #1
0
static int
ar933x_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
	int c;

	uart_lock(hwmtx);

	/* Wait for a character to come ready */
	while ((ar933x_getreg(bas, AR933X_UART_DATA_REG) &
	    AR933X_UART_DATA_RX_CSR) == 0) {
		uart_unlock(hwmtx);
		DELAY(4);
		uart_lock(hwmtx);
	}

	/* Read the top of the RX FIFO */
	c = ar933x_getreg(bas, AR933X_UART_DATA_REG) & 0xff;

	/* Remove that entry from said RX FIFO */
	ar933x_setreg(bas, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);

	uart_unlock(hwmtx);

	return (c);
}
bool
sd_erase_blocks(uint32_t address, uint16_t numBlocks)
{
  uint8_t ret, r1;
  uint32_t endAdr;

  if (sd_protected()) {
    return FALSE;
  }

  if (!uart_lock(UART_MODE_SPI)) {
    return FALSE;
  }

  ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_START_ADDR, SD_RESPONSE_SIZE_R1,
		 &address, &r1);
  if (!ret | r1) {
    uart_unlock(UART_MODE_SPI);
    return FALSE;
  }

  endAdr = (numBlocks - 1) * sd_state.BlockLen;
  endAdr += address;

  ret = _sd_send_cmd(SD_CMD_ERASE_WR_BLK_END_ADDR, SD_RESPONSE_SIZE_R1, 
		&endAdr, &r1);
  if (!ret | r1) {
    uart_unlock(UART_MODE_SPI);
    return FALSE;
  }

  ret = _sd_send_cmd(SD_CMD_ERASE, SD_RESPONSE_SIZE_R1, NULL, &r1);
  uart_unlock(UART_MODE_SPI);
  return ret;
}
Example #3
0
/*
 * Block waiting for a character.
 */
static int
at91_usart_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
	int c;

	uart_lock(hwmtx);
	while (!(RD4(bas, USART_CSR) & USART_CSR_RXRDY)) {
		uart_unlock(hwmtx);
		DELAY(4);
		uart_lock(hwmtx);
	}
	c = RD4(bas, USART_RHR) & 0xff;
	uart_unlock(hwmtx);
	return (c);
}
Example #4
0
/*
 * Write the current transmit buffer to the TX FIFO. 
 */
static int
msm_bus_transmit(struct uart_softc *sc)
{
	struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
	struct uart_bas *bas = &sc->sc_bas;
	int i;

	uart_lock(sc->sc_hwmtx);

	/* Write some data */
	for (i = 0; i < sc->sc_txdatasz; i++) {
		/* Write TX data */
		msm_putc(bas, sc->sc_txbuf[i]);
		uart_barrier(bas);
	}

	/* TX FIFO is empty now, enable TX_READY interrupt */
	u->ier |= UART_DM_TX_READY;
	SETREG(bas, UART_DM_IMR, u->ier);
	uart_barrier(bas);

	/*
	 * Inform upper layer that it is transmitting data to hardware,
	 * this will be cleared when TXIDLE interrupt occurs.
	 */
	sc->sc_txbusy = 1;
	uart_unlock(sc->sc_hwmtx);

	return (0);
}
Example #5
0
static int
s3c2410_bus_ipend(struct uart_softc *sc)
{
	uint32_t ufstat, txmask, rxmask;
	uintptr_t irq;
	int ipend = 0;

	uart_lock(sc->sc_hwmtx);
	ufstat = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UFSTAT);
	uart_unlock(sc->sc_hwmtx);

	txmask = rxmask = 0;
	switch (s3c2xx0_softc->sc_cpu) {
	case CPU_S3C2410:
		txmask = UFSTAT_TXCOUNT;
		rxmask = UFSTAT_RXCOUNT;
		break;
	case CPU_S3C2440:
		txmask = S3C2440_UFSTAT_TXCOUNT;
		rxmask = S3C2440_UFSTAT_RXCOUNT;
		break;
	}
	if ((ufstat & txmask) == 0) {
		if (sc->sc_txbusy != 0)
			ipend |= SER_INT_TXIDLE;
		irq = rman_get_start(sc->sc_ires);
		arm_mask_irq(get_sub_irq(irq, TX_OFF));
	}
	if ((ufstat & rxmask) > 0) {
		ipend |= SER_INT_RXREADY;
	}

	return (ipend);
}
Example #6
0
static int
at91_usart_bus_transmit(struct uart_softc *sc)
{
	bus_addr_t addr;
	struct at91_usart_softc *atsc;
	int err;

	err = 0;
	atsc = (struct at91_usart_softc *)sc;
	uart_lock(sc->sc_hwmtx);
	if (bus_dmamap_load(atsc->tx_tag, atsc->tx_map, sc->sc_txbuf,
	    sc->sc_txdatasz, at91_getaddr, &addr, 0) != 0) {
		err = EAGAIN;
		goto errout;
	}
	bus_dmamap_sync(atsc->tx_tag, atsc->tx_map, BUS_DMASYNC_PREWRITE);
	sc->sc_txbusy = 1;
	/*
	 * Setup the PDC to transfer the data and interrupt us when it
	 * is done.  We've already requested the interrupt.
	 */
	WR4(&sc->sc_bas, PDC_TPR, addr);
	WR4(&sc->sc_bas, PDC_TCR, sc->sc_txdatasz);
	WR4(&sc->sc_bas, PDC_PTCR, PDC_PTCR_TXTEN);
	WR4(&sc->sc_bas, USART_IER, USART_CSR_ENDTX);
errout:
	uart_unlock(sc->sc_hwmtx);
	return (err);
}
Example #7
0
UART_GETC(linux_emu, uart, waittime) {
	char c;
	uart_lock(uart, waittime, -1);
	c = getc(stdin);
	uart_unlock(uart, -1);
	return c;
}
Example #8
0
static int
exynos4210_bus_ipend(struct uart_softc *sc)
{
	uint32_t ints;
	uint32_t txempty, rxready;
	int reg;
	int ipend;

	uart_lock(sc->sc_hwmtx);
	ints = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTP);
	bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTP, ints);

	txempty = (1 << 2);
	rxready = (1 << 0);

	ipend = 0;
	if ((ints & txempty) > 0) {
		if (sc->sc_txbusy != 0)
			ipend |= SER_INT_TXIDLE;

		/* mask TX interrupt */
		reg = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh,
		    SSCOM_UINTM);
		reg |= (1 << 2);
		bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh,
		    SSCOM_UINTM, reg);
	}

	if ((ints & rxready) > 0) {
		ipend |= SER_INT_RXREADY;
	}

	uart_unlock(sc->sc_hwmtx);
	return (ipend);
}
Example #9
0
static int
msm_bus_receive(struct uart_softc *sc)
{
	struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
	struct uart_bas *bas;
	int c;

	bas = &sc->sc_bas;
	uart_lock(sc->sc_hwmtx);

	/* Initialize Receive Path and interrupt */
	SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
	SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_ENABLE);
	u->ier |= UART_DM_RXLEV;
	SETREG(bas, UART_DM_IMR, u->ier);

	/* Loop over until we are full, or no data is available */
	while (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) {
		if (uart_rx_full(sc)) {
			/* No space left in input buffer */
			sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
			break;
		}

		/* Read RX FIFO */
		c = uart_getreg(bas, UART_DM_RF(0));
		uart_barrier(bas);

		uart_rx_put(sc, c);
	}

	uart_unlock(sc->sc_hwmtx);

	return (0);
}
Example #10
0
static int
msm_bus_ipend(struct uart_softc *sc)
{
	struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
	struct uart_bas *bas = &sc->sc_bas;
	uint32_t isr;
	int ipend;

	uart_lock(sc->sc_hwmtx);

	/* Get ISR status */
	isr = GETREG(bas, UART_DM_MISR);

	ipend = 0;

	/* Uart RX starting, notify upper layer */
	if (isr & UART_DM_RXLEV) {
		u->ier &= ~UART_DM_RXLEV;
		SETREG(bas, UART_DM_IMR, u->ier);
		uart_barrier(bas);
		ipend |= SER_INT_RXREADY;
	}

	/* Stale RX interrupt */
	if (isr & UART_DM_RXSTALE) {
		/* Disable and reset it */
		SETREG(bas, UART_DM_CR, UART_DM_STALE_EVENT_DISABLE);
		SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
		uart_barrier(bas);
		ipend |= SER_INT_RXREADY;
	}

	/* TX READY interrupt */
	if (isr & UART_DM_TX_READY) {
		/* Clear  TX Ready */
		SETREG(bas, UART_DM_CR, UART_DM_CLEAR_TX_READY);

		/* Disable TX_READY */
		u->ier &= ~UART_DM_TX_READY;
		SETREG(bas, UART_DM_IMR, u->ier);
		uart_barrier(bas);

		if (sc->sc_txbusy != 0)
			ipend |= SER_INT_TXIDLE;
	}

	if (isr & UART_DM_TXLEV) {
		/* TX FIFO is empty */
		u->ier &= ~UART_DM_TXLEV;
		SETREG(bas, UART_DM_IMR, u->ier);
		uart_barrier(bas);

		if (sc->sc_txbusy != 0)
			ipend |= SER_INT_TXIDLE;
	}

	uart_unlock(sc->sc_hwmtx);
	return (ipend);
}
Example #11
0
static int
adm5120_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
	int c;

	uart_lock(hwmtx);

	while (uart_getreg(bas, UART_FR_REG) & UART_FR_RX_FIFO_EMPTY) {
		uart_unlock(hwmtx);
		DELAY(10);
		uart_lock(hwmtx);
	}

	c = uart_getreg(bas, UART_DR_REG);

	uart_unlock(hwmtx);

	return (c);
}
Example #12
0
static int
mtk_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
	int c;

	uart_lock(hwmtx);

	while (!(uart_getreg(bas, UART_LSR_REG) & UART_LSR_DR)) {
		uart_unlock(hwmtx);
		DELAY(10);
		uart_lock(hwmtx);
	}

	c = uart_getreg(bas, UART_RX_REG);

	uart_unlock(hwmtx);

	return (c);
}
Example #13
0
static int
uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
{
	int err;
	int hdr = 0;

	uart_lock(&sc->sc_mtx);
	if (sc->inbuflen == 0) {
		err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid,
		    0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0],
		    &sc->phyp_inbuf.u64[1]);
		if (err != H_SUCCESS) {
			uart_unlock(&sc->sc_mtx);
			return (-1);
		}
		hdr = 1; 
	}

	if (sc->inbuflen == 0) {
		uart_unlock(&sc->sc_mtx);
		return (0);
	}

	if (bufsize > sc->inbuflen)
		bufsize = sc->inbuflen;

	if ((sc->protocol == HVTERMPROT) && (hdr == 1)) {
		sc->inbuflen = sc->inbuflen - 4;
		/* The VTERM protocol has a 4 byte header, skip it here. */
		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4],
		    sc->inbuflen);
	}

	memcpy(buffer, sc->phyp_inbuf.str, bufsize);
	sc->inbuflen -= bufsize;
	if (sc->inbuflen > 0)
		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize],
		    sc->inbuflen);

	uart_unlock(&sc->sc_mtx);
	return (bufsize);
}
Example #14
0
/*---------------------------------------------------------------------------*/
void
rs232_print(char *cptr)
{
  /* lock UART for the print operation */
  if(uart_lock(UART_MODE_RS232)) {
    while(*cptr != 0) {
      rs232_send(*cptr);
      ++cptr;
    }
    uart_unlock(UART_MODE_RS232);
  }
}
Example #15
0
static void
msm_bus_ungrab(struct uart_softc *sc)
{
	struct msm_uart_softc *u = (struct msm_uart_softc *)sc;
	struct uart_bas *bas = &sc->sc_bas;

	/*
	 * Restore previous interrupt mask
	 */
	uart_lock(sc->sc_hwmtx);
	SETREG(bas, UART_DM_IMR, u->ier);
	uart_barrier(bas);
	uart_unlock(sc->sc_hwmtx);
}
Example #16
0
static void
msm_bus_grab(struct uart_softc *sc)
{
	struct uart_bas *bas = &sc->sc_bas;

	/*
	 * XXX: Turn off all interrupts to enter polling mode. Leave the
	 * saved mask alone. We'll restore whatever it was in ungrab.
	 */
	uart_lock(sc->sc_hwmtx);
	SETREG(bas, UART_DM_CR, UART_DM_RESET_STALE_INT);
	SETREG(bas, UART_DM_IMR, 0);
	uart_barrier(bas);
	uart_unlock(sc->sc_hwmtx);
}
Example #17
0
static void
tegra_uart_ungrab(struct uart_softc *sc)
{
	struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
	struct uart_bas *bas = &sc->sc_bas;

	/*
	 * Restore previous interrupt mask
	 */
	uart_lock(sc->sc_hwmtx);
	uart_setreg(bas, REG_FCR, ns8250->fcr);
	uart_setreg(bas, REG_IER, ns8250->ier);
	uart_barrier(bas);
	uart_unlock(sc->sc_hwmtx);
}
Example #18
0
static int
vf_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
    int c;

    uart_lock(hwmtx);

    while (!(uart_getreg(bas, UART_S1) & UART_S1_RDRF))
        ;

    c = uart_getreg(bas, UART_D);
    uart_unlock(hwmtx);

    return (c & 0xff);
}
Example #19
0
static int
s3c2410_bus_param(struct uart_softc *sc, int baudrate, int databits,
    int stopbits, int parity)
{
	int error;

	if (sc->sc_bas.rclk == 0)
		sc->sc_bas.rclk = s3c2410_pclk;
	KASSERT(sc->sc_bas.rclk != 0, ("s3c2410_init: Invalid rclk"));

	uart_lock(sc->sc_hwmtx);
	error = s3c24x0_uart_param(&sc->sc_bas, baudrate, databits, stopbits,
	    parity);
	uart_unlock(sc->sc_hwmtx);

	return (error);
}
Example #20
0
static int
uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
{
	uint16_t seqno;
	uint64_t len = 0;
	int	err;

	union {
		uint64_t u64[2];
		char bytes[16];
	} cbuf;

	uart_lock(&sc->sc_mtx);
	switch (sc->protocol) {
	case HVTERM1:
		if (bufsize > 16)
			bufsize = 16;
		memcpy(&cbuf, buffer, bufsize);
		len = bufsize;
		break;
	case HVTERMPROT:
		if (bufsize > 12)
			bufsize = 12;
		seqno = sc->outseqno++;
		cbuf.bytes[0] = VS_DATA_PACKET_HEADER;
		cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */
		cbuf.bytes[2] = (seqno >> 8) & 0xff;
		cbuf.bytes[3] = seqno & 0xff;
		memcpy(&cbuf.bytes[4], buffer, bufsize);
		len = 4 + bufsize;
		break;
	}

	do {
	    err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64[0],
			    cbuf.u64[1]);
		DELAY(100);
	} while (err == H_BUSY);

	uart_unlock(&sc->sc_mtx);

	return (bufsize);
}
Example #21
0
static int
imx_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
{
	int c;

	uart_lock(hwmtx);
	while (!(IS(bas, USR2, RDR)))
		;

	c = GETREG(bas, REG(URXD));
	uart_unlock(hwmtx);
#if defined(KDB)
	if (c & FLD(URXD, BRK)) {
		if (kdb_break())
			return (0);
	}
#endif
	return (c & 0xff);
}
Example #22
0
static void
tegra_uart_grab(struct uart_softc *sc)
{
	struct uart_bas *bas = &sc->sc_bas;
	struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
	u_char ier;

	/*
	 * turn off all interrupts to enter polling mode. Leave the
	 * saved mask alone. We'll restore whatever it was in ungrab.
	 * All pending interrupt signals are reset when IER is set to 0.
	 */
	uart_lock(sc->sc_hwmtx);
	ier = uart_getreg(bas, REG_IER);
	uart_setreg(bas, REG_IER, ier & ns8250->ier_mask);
	uart_setreg(bas, REG_FCR, 0);
	uart_barrier(bas);
	uart_unlock(sc->sc_hwmtx);
}
Example #23
0
static int
s3c2410_bus_transmit(struct uart_softc *sc)
{
	uintptr_t irq;

	uart_lock(sc->sc_hwmtx);

	for (int i = 0; i < sc->sc_txdatasz; i++) {
		s3c2410_putc(&sc->sc_bas, sc->sc_txbuf[i]);
		uart_barrier(&sc->sc_bas);
	}

	sc->sc_txbusy = 1;

	uart_unlock(sc->sc_hwmtx);

	irq = rman_get_start(sc->sc_ires);
	arm_unmask_irq(get_sub_irq(irq, TX_OFF));

	return (0);
}
Example #24
0
static int
msm_getc(struct uart_bas *bas, struct mtx *mtx)
{
	int c;

	uart_lock(mtx);

	/* Wait for a character to come ready */
	while ((uart_getreg(bas, UART_DM_SR) & UART_DM_SR_RXRDY) !=
	    UART_DM_SR_RXRDY)
		DELAY(4);

	/* Check for Overrun error. If so reset Error Status */
	if (uart_getreg(bas, UART_DM_SR) & UART_DM_SR_UART_OVERRUN)
		uart_setreg(bas, UART_DM_CR, UART_DM_RESET_ERROR_STATUS);

	/* Read char */
	c = uart_getreg(bas, UART_DM_RF(0));

	uart_unlock(mtx);

	return (c);
}
Example #25
0
static int
exynos4210_bus_transmit(struct uart_softc *sc)
{
	int i;
	int reg;

	uart_lock(sc->sc_hwmtx);

	for (i = 0; i < sc->sc_txdatasz; i++) {
		exynos4210_putc(&sc->sc_bas, sc->sc_txbuf[i]);
		uart_barrier(&sc->sc_bas);
	}

	sc->sc_txbusy = 1;

	uart_unlock(sc->sc_hwmtx);

	/* unmask TX interrupt */
	reg = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTM);
	reg &= ~(1 << 2);
	bus_space_write_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UINTM, reg);

	return (0);
}
Example #26
0
UART_PUTC(linux_emu, uart, c, waittime) {
	uart_lock(uart, waittime, -1);
	putc(c, stdout);
	uart_unlock(uart, -1);
	return 0;
}
Example #27
0
int
main(void)
{
#if WITH_SD
  int r;
#endif /* WITH_SD */

  msp430_cpu_init();	
  watchdog_stop();

  /* Platform-specific initialization. */
  msb_ports_init();
  adc_init();

  clock_init();
  rtimer_init();

  sht11_init();
  leds_init();
  leds_on(LEDS_ALL);

  irq_init();
  process_init();

  /* serial interface */
  rs232_set_input(serial_line_input_byte);
  rs232_init();
  serial_line_init();

  uart_lock(UART_MODE_RS232);
  uart_unlock(UART_MODE_RS232);
#if WITH_UIP
  slip_arch_init(BAUD2UBR(115200));
#endif


#if WITH_SD
  r = sd_initialize();
  if(r < 0) {
    printf("Failed to initialize the SD driver: %s\n", sd_error_string(r));
  } else {
    sd_offset_t capacity;
    printf("The SD driver was successfully initialized\n");
    capacity = sd_get_capacity();
    if(capacity < 0) {
      printf("Failed to get the SD card capacity: %s\n", sd_error_string(r));
    } else {
      printf("SD card capacity: %u MB\n",
	(unsigned)(capacity / (1024UL * 1024)));
    }
  }
#endif

  /* System services */
  process_start(&etimer_process, NULL);
  ctimer_init();

  node_id_restore();

  init_net();

  energest_init();
 
#if PROFILE_CONF_ON
  profile_init();
#endif /* PROFILE_CONF_ON */
 
  leds_off(LEDS_ALL);

  printf(CONTIKI_VERSION_STRING " started. Node id %u, using %s.\n", 
         node_id, rime_mac->name);

  autostart_start(autostart_processes);

  /*
   * This is the scheduler loop.
   */
  ENERGEST_ON(ENERGEST_TYPE_CPU);

  while (1) {
    int r;
#if PROFILE_CONF_ON
    profile_episode_start();
#endif /* PROFILE_CONF_ON */
    do {
      /* Reset watchdog. */
      watchdog_periodic();
      r = process_run();
    } while(r > 0);

#if PROFILE_CONF_ON
    profile_episode_end();
#endif /* PROFILE_CONF_ON */

    /*
     * Idle processing.
     */
    int s = splhigh();		/* Disable interrupts. */
    if (process_nevents() != 0) {
      splx(s);			/* Re-enable interrupts. */
    } else {
      static unsigned long irq_energest = 0;
      /* Re-enable interrupts and go to sleep atomically. */
      ENERGEST_OFF(ENERGEST_TYPE_CPU);
      ENERGEST_ON(ENERGEST_TYPE_LPM);
     /*
      * We only want to measure the processing done in IRQs when we
      * are asleep, so we discard the processing time done when we
      * were awake.
      */
      energest_type_set(ENERGEST_TYPE_IRQ, irq_energest);

      if (uart_edge) {
	_BIC_SR(LPM1_bits + GIE);
      } else {
	_BIS_SR(LPM1_bits + GIE);
      }

      /*
       * We get the current processing time for interrupts that was
       * done during the LPM and store it for next time around. 
       */
      dint();
      irq_energest = energest_type_time(ENERGEST_TYPE_IRQ);
      eint();
      ENERGEST_OFF(ENERGEST_TYPE_LPM);
      ENERGEST_ON(ENERGEST_TYPE_CPU);
#if PROFILE_CONF_ON
      profile_clear_timestamps();
#endif /* PROFILE_CONF_ON */
    }
  }

  return 0;
}
Example #28
0
static u_int
sunkbd_read_char(keyboard_t *kbd, int wait)
{
	struct sunkbd_softc *sc;
	int key, release, repeated, suncode;

	sc = (struct sunkbd_softc *)kbd;

#if defined(SUNKBD_EMULATE_ATKBD)
	if (sc->sc_mode == K_RAW && sc->sc_buffered_char[0]) {
		key = sc->sc_buffered_char[0];
		if (key & SCAN_PREFIX) {
			sc->sc_buffered_char[0] = key & ~SCAN_PREFIX;
			return ((key & SCAN_PREFIX_E0) ? 0xe0 : 0xe1);
		} else {
			sc->sc_buffered_char[0] = sc->sc_buffered_char[1];
			sc->sc_buffered_char[1] = 0;
			return (key);
		}
	}
#endif

	repeated = 0;
	if (sc->sc_repeating) {
		repeated = 1;
		sc->sc_repeating = 0;
		callout_reset(&sc->sc_repeat_callout, hz / 10,
		    sunkbd_repeat, sc);
		suncode = sc->sc_repeat_key;
		goto process_code;
	}

	for (;;) {
 next_code:
		if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0)) {
			key = sc->sc_composed_char;
			sc->sc_composed_char = 0;
			if (key > UCHAR_MAX)
				return (ERRKEY);
			return (key);
		}

		if (sc->sc_uart != NULL && !uart_rx_empty(sc->sc_uart)) {
			suncode = uart_rx_get(sc->sc_uart);
		} else if (sc->sc_polling != 0 && sc->sc_sysdev != NULL) {
			if (wait)
				suncode = uart_getc(sc->sc_sysdev);
			else if ((suncode = uart_poll(sc->sc_sysdev)) == -1)
				return (NOKEY);
		} else {
			return (NOKEY);
		}

		switch (suncode) {
		case SKBD_RSP_IDLE:
			break;
		default:
 process_code:
			++kbd->kb_count;
			key = SKBD_KEY_CHAR(suncode);
			release = suncode & SKBD_KEY_RELEASE;
			if (!repeated) {
				if (release == 0) {
					callout_reset(&sc->sc_repeat_callout,
					    hz / 2, sunkbd_repeat, sc);
					sc->sc_repeat_key = suncode;
				} else if (sc->sc_repeat_key == key) {
					callout_stop(&sc->sc_repeat_callout);
					sc->sc_repeat_key = -1;
				}
			}

#if defined(SUNKBD_EMULATE_ATKBD)
			key = sunkbd_trtab[key];
			if (key == NOTR)
				return (NOKEY);

			if (!repeated) {
				switch (key) {
				case 0x1d:	/* ctrl */
					if (release != 0)
						sc->sc_flags &= ~CTLS;
					else
						sc->sc_flags |= CTLS;
					break;
				case 0x2a:	/* left shift */
				case 0x36:	/* right shift */
					if (release != 0)
						sc->sc_flags &= ~SHIFTS;
					else
						sc->sc_flags |= SHIFTS;
					break;
				case 0x38:	/* alt */
				case 0x5d:	/* altgr */
					if (release != 0)
						sc->sc_flags &= ~ALTS;
					else
						sc->sc_flags |= ALTS;
					break;
				}
			}
			if (sc->sc_mode == K_RAW) {
				key = keycode2scancode(key, sc->sc_flags,
				    release);
				if (key & SCAN_PREFIX) {
					if (key & SCAN_PREFIX_CTL) {
						sc->sc_buffered_char[0] =
						    0x1d | (key & SCAN_RELEASE);
						sc->sc_buffered_char[1] =
						    key & ~SCAN_PREFIX;
					} else if (key & SCAN_PREFIX_SHIFT) {
						sc->sc_buffered_char[0] =
						    0x2a | (key & SCAN_RELEASE);
						sc->sc_buffered_char[1] =
						    key & ~SCAN_PREFIX_SHIFT;
					} else {
						sc->sc_buffered_char[0] =
						    key & ~SCAN_PREFIX;
						sc->sc_buffered_char[1] = 0;
					}
					return ((key & SCAN_PREFIX_E0) ?
					    0xe0 : 0xe1);
				}
				return (key);
			}
			switch (key) {
			case 0x5c:	/* print screen */
				if (sc->sc_flags & ALTS)
					key = 0x54;	/* sysrq */
				break;
			case 0x68:	/* pause/break */
				if (sc->sc_flags & CTLS)
					key = 0x6c;	/* break */
				break;
			}

			if (sc->sc_mode == K_CODE)
				return (key | release);
#else
			if (sc->sc_mode == K_RAW || sc->sc_mode == K_CODE)
				return (suncode);
#endif

#if defined(SUNKBD_EMULATE_ATKBD)
			if (key == 0x38) {	/* left alt (KP compose key) */
#else
			if (key == 0x13) {	/* left alt (KP compose key) */
#endif
				if (release != 0) {
					if (sc->sc_flags & KPCOMPOSE) {
						sc->sc_flags &= ~KPCOMPOSE;
						if (sc->sc_composed_char >
						    UCHAR_MAX)
							sc->sc_composed_char =
							    0;
					}
				} else {
					if (!(sc->sc_flags & KPCOMPOSE)) {
						sc->sc_flags |= KPCOMPOSE;
						sc->sc_composed_char = 0;
					}
				}
			}
			if (sc->sc_flags & KPCOMPOSE) {
				switch (suncode) {
				case 0x44:			/* KP 7 */
				case 0x45:			/* KP 8 */
				case 0x46:			/* KP 9 */
					sc->sc_composed_char *= 10;
					sc->sc_composed_char += suncode - 0x3d;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;
				case 0x5b:			/* KP 4 */
				case 0x5c:			/* KP 5 */
				case 0x5d:			/* KP 6 */
					sc->sc_composed_char *= 10;
					sc->sc_composed_char += suncode - 0x58;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;
				case 0x70:			/* KP 1 */
				case 0x71:			/* KP 2 */
				case 0x72:			/* KP 3 */
					sc->sc_composed_char *= 10;
					sc->sc_composed_char += suncode - 0x6f;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;
				case 0x5e:			/* KP 0 */
					sc->sc_composed_char *= 10;
					if (sc->sc_composed_char > UCHAR_MAX)
						return (ERRKEY);
					goto next_code;

				case 0x44 | SKBD_KEY_RELEASE:	/* KP 7 */
				case 0x45 | SKBD_KEY_RELEASE:	/* KP 8 */
				case 0x46 | SKBD_KEY_RELEASE:	/* KP 9 */
				case 0x5b | SKBD_KEY_RELEASE:	/* KP 4 */
				case 0x5c | SKBD_KEY_RELEASE:	/* KP 5 */
				case 0x5d | SKBD_KEY_RELEASE:	/* KP 6 */
				case 0x70 | SKBD_KEY_RELEASE:	/* KP 1 */
				case 0x71 | SKBD_KEY_RELEASE:	/* KP 2 */
				case 0x72 | SKBD_KEY_RELEASE:	/* KP 3 */
				case 0x5e | SKBD_KEY_RELEASE:	/* KP 0 */
					goto next_code;
				default:
					if (sc->sc_composed_char > 0) {
						sc->sc_flags &= ~KPCOMPOSE;
						sc->sc_composed_char = 0;
						return (ERRKEY);
					}
				}
			}

			key = genkbd_keyaction(kbd, key, release,
			    &sc->sc_state, &sc->sc_accents);
			if (key != NOKEY || repeated)
				return (key);
		}
	}
	return (0);
}

static int
sunkbd_check_char(keyboard_t *kbd)
{
	struct sunkbd_softc *sc;

	if (!KBD_IS_ACTIVE(kbd))
		return (FALSE);

	sc = (struct sunkbd_softc *)kbd;
	if (!(sc->sc_flags & KPCOMPOSE) && (sc->sc_composed_char > 0))
		return (TRUE);

	return (sunkbd_check(kbd));
}

static int
sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
{
	struct sunkbd_softc *sc;
	int c, error;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	int ival;
#endif

	sc = (struct sunkbd_softc *)kbd;
	error = 0;
	switch (cmd) {
	case KDGKBMODE:
		*(int *)data = sc->sc_mode;
		break;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	case _IO('K', 7):
		ival = IOCPARM_IVAL(data);
		data = (caddr_t)&ival;
		/* FALLTHROUGH */
#endif
	case KDSKBMODE:
		switch (*(int *)data) {
		case K_XLATE:
			if (sc->sc_mode != K_XLATE) {
				/* make lock key state and LED state match */
				sc->sc_state &= ~LOCK_MASK;
				sc->sc_state |= KBD_LED_VAL(kbd);
			}
			/* FALLTHROUGH */
		case K_RAW:
		case K_CODE:
			if (sc->sc_mode != *(int *)data) {
				sunkbd_clear_state(kbd);
				sc->sc_mode = *(int *)data;
			}
			break;
		default:
			error = EINVAL;
			break;
		}
		break;
	case KDGETLED:
		*(int *)data = KBD_LED_VAL(kbd);
		break;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	case _IO('K', 66):
		ival = IOCPARM_IVAL(data);
		data = (caddr_t)&ival;
		/* FALLTHROUGH */
#endif
	case KDSETLED:
		if (*(int *)data & ~LOCK_MASK) {
			error = EINVAL;
			break;
		}
		if (sc->sc_sysdev == NULL)
			break;
		c = 0;
		if (*(int *)data & CLKED)
			c |= SKBD_LED_CAPSLOCK;
		if (*(int *)data & NLKED)
			c |= SKBD_LED_NUMLOCK;
		if (*(int *)data & SLKED)
			c |= SKBD_LED_SCROLLLOCK;
		uart_lock(sc->sc_sysdev->hwmtx);
		sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED);
		sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, c);
		uart_unlock(sc->sc_sysdev->hwmtx);
		KBD_LED_VAL(kbd) = *(int *)data;
		break;
	case KDGKBSTATE:
		*(int *)data = sc->sc_state & LOCK_MASK;
		break;
#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5)
	case _IO('K', 20):
		ival = IOCPARM_IVAL(data);
		data = (caddr_t)&ival;
		/* FALLTHROUGH */
#endif
	case KDSKBSTATE:
		if (*(int *)data & ~LOCK_MASK) {
			error = EINVAL;
			break;
		}
		sc->sc_state &= ~LOCK_MASK;
		sc->sc_state |= *(int *)data;
		/* set LEDs and quit */
		return (sunkbd_ioctl(kbd, KDSETLED, data));
	case KDSETREPEAT:
	case KDSETRAD:
		break;
	case PIO_KEYMAP:
	case OPIO_KEYMAP:
	case PIO_KEYMAPENT:
	case PIO_DEADKEYMAP:
	default:
		return (genkbd_commonioctl(kbd, cmd, data));
	}
	return (error);
}

static int
sunkbd_lock(keyboard_t *kbd, int lock)
{

	TODO;
	return (0);
}