Exemplo n.º 1
0
static void ns16550_irq_handler(irq_t *irq)
{
	ns16550_instance_t *instance = irq->instance;
	ns16550_t *dev = instance->ns16550;
	
	if (pio_read_8(&dev->lsr) & LSR_DATA_READY) {
		uint8_t data = pio_read_8(&dev->rbr);
		indev_push_character(instance->input, data);
	}
}
Exemplo n.º 2
0
/** Interrupt in listen state.
 *
 * Start packet reception.
 */
static void cuda_irq_listen(void)
{
	uint8_t b;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) != 0) {
		printf("cuda_irq_listen: no TREQ?!\n");
		return;
	}

	pio_read_8(&dev->sr);
	pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);
	instance->xstate = cx_receive;
}
Exemplo n.º 3
0
/** Interrupt in receive state.
 *
 * Receive next byte of packet.
 */
static void cuda_irq_receive(void)
{
	uint8_t b, data;

	data = pio_read_8(&dev->sr);
	if (instance->bidx < CUDA_RCV_BUF_SIZE)
		instance->rcv_buf[instance->bidx++] = data;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) == 0) {
		pio_write_8(&dev->b, b ^ TACK);
	} else {
		pio_write_8(&dev->b, b | TACK | TIP);
		instance->xstate = cx_rcv_end;
	}
}
Exemplo n.º 4
0
/** Interrupt in listen state.
 *
 * Start packet reception.
 */
static void cuda_irq_listen(irq_t *irq)
{
	cuda_instance_t *instance = irq->instance;
	cuda_t *dev = instance->cuda;
	uint8_t b;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) != 0) {
		log(LF_OTHER, LVL_ERROR, "cuda_irq_listen: no TREQ?!");
		return;
	}

	pio_read_8(&dev->sr);
	pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);
	instance->xstate = cx_receive;
}
Exemplo n.º 5
0
static void cuda_send_start(void)
{
	cuda_t *dev = instance->cuda;

	assert(instance->xstate == cx_listen);

	if (instance->snd_bytes == 0)
		return;

	/* Check for incoming data. */
	if ((pio_read_8(&dev->b) & TREQ) == 0)
		return;

	pio_write_8(&dev->acr, pio_read_8(&dev->acr) | SR_OUT);
	pio_write_8(&dev->sr, instance->snd_buf[0]);
	pio_write_8(&dev->b, pio_read_8(&dev->b) & ~TIP);

	instance->xstate = cx_send_start;
}
Exemplo n.º 6
0
/** Interrupt in rcv_end state.
 *
 * Terminate packet reception. Either go back to listen state or start
 * receiving another packet if CUDA has one for us.
 */
static void cuda_irq_rcv_end(void *buf, size_t *len)
{
	uint8_t b;
	
	b = pio_read_8(&dev->b);
	pio_read_8(&dev->sr);
	
	if ((b & TREQ) == 0) {
		instance->xstate = cx_receive;
		pio_write_8(&dev->b, b & ~TIP);
	} else {
		instance->xstate = cx_listen;
		cuda_send_start();
	}
	
	memcpy(buf, instance->rcv_buf, instance->bidx);
	*len = instance->bidx;
	instance->bidx = 0;
}
Exemplo n.º 7
0
static irq_ownership_t ns16550_claim(irq_t *irq)
{
	ns16550_instance_t *instance = irq->instance;
	ns16550_t *dev = instance->ns16550;
	
	if (pio_read_8(&dev->lsr) & LSR_DATA_READY)
		return IRQ_ACCEPT;
	else
		return IRQ_DECLINE;
}
Exemplo n.º 8
0
/** Interrupt in send state.
 *
 * Send next byte or terminate transmission.
 */
static void cuda_irq_send(void)
{
	if (instance->bidx < instance->snd_bytes) {
		/* Send next byte. */
		pio_write_8(&dev->sr, instance->snd_buf[instance->bidx++]);
		pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK);
		return;
	}

	/* End transfer. */
	instance->snd_bytes = 0;
	instance->bidx = 0;

	pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT);
	pio_read_8(&dev->sr);
	pio_write_8(&dev->b, pio_read_8(&dev->b) | TACK | TIP);

	instance->xstate = cx_listen;
	/* TODO: Match reply with request. */
}
Exemplo n.º 9
0
/** Interrupt in send_start state.
 *
 * Process result of sending first byte (and send second on success).
 */
static void cuda_irq_send_start(void)
{
	uint8_t b;

	b = pio_read_8(&dev->b);

	if ((b & TREQ) == 0) {
		/* Collision */
		pio_write_8(&dev->acr, pio_read_8(&dev->acr) & ~SR_OUT);
		pio_read_8(&dev->sr);
		pio_write_8(&dev->b, pio_read_8(&dev->b) | TIP | TACK);
		instance->xstate = cx_listen;
		return;
	}

	pio_write_8(&dev->sr, instance->snd_buf[1]);
	pio_write_8(&dev->b, pio_read_8(&dev->b) ^ TACK);
	instance->bidx = 2;

	instance->xstate = cx_send;
}
Exemplo n.º 10
0
static irq_ownership_t cuda_claim(irq_t *irq)
{
	cuda_instance_t *instance = irq->instance;
	cuda_t *dev = instance->cuda;
	uint8_t ifr;

	spinlock_lock(&instance->dev_lock);
	ifr = pio_read_8(&dev->ifr);
	spinlock_unlock(&instance->dev_lock);

	if ((ifr & SR_INT) == 0)
		return IRQ_DECLINE;

	return IRQ_ACCEPT;
}
Exemplo n.º 11
0
static void ega_cursor_update(outdev_t *dev, sysarg_t prev_col,
    sysarg_t prev_row, sysarg_t col, sysarg_t row, bool visible)
{
	/* Cursor position */
	uint16_t cursor = row * ega.cols + col;
	
	pio_write_8(EGA_IO_BASE, 0x0e);
	pio_write_8(EGA_IO_BASE + 1, (cursor >> 8) & 0xff);
	pio_write_8(EGA_IO_BASE, 0x0f);
	pio_write_8(EGA_IO_BASE + 1, cursor & 0xff);
	
	/* Cursor visibility */
	pio_write_8(EGA_IO_BASE, 0x0a);
	uint8_t stat = pio_read_8(EGA_IO_BASE + 1);
	
	pio_write_8(EGA_IO_BASE, 0x0a);
	
	if (visible)
		pio_write_8(EGA_IO_BASE + 1, stat & (~(1 << 5)));
	else
		pio_write_8(EGA_IO_BASE + 1, stat | (1 << 5));
}
Exemplo n.º 12
0
static void ns16550_sendb(ns16550_t *dev, uint8_t byte)
{
	while (!(pio_read_8(&dev->lsr) & LSR_TH_READY))
		;
	pio_write_8(&dev->thr, byte);
}
Exemplo n.º 13
0
/**< Clear input buffer. */
static void ns16550_clear_buffer(ns16550_t *dev)
{
	while ((pio_read_8(&dev->lsr) & LSR_DATA_READY))
		(void) pio_read_8(&dev->rbr);
}
Exemplo n.º 14
0
/** Initialize i8042 driver structure.
 *
 * @param dev       Driver structure to initialize.
 * @param regs      I/O address of registers.
 * @param reg_size  size of the reserved I/O address space.
 * @param irq_kbd   IRQ for primary port.
 * @param irq_mouse IRQ for aux port.
 * @param ddf_dev   DDF device structure of the device.
 *
 * @return Error code.
 *
 */
int i8042_init(i8042_t *dev, void *regs, size_t reg_size, int irq_kbd,
               int irq_mouse, ddf_dev_t *ddf_dev)
{
    const size_t range_count = sizeof(i8042_ranges) /
                               sizeof(irq_pio_range_t);
    irq_pio_range_t ranges[range_count];
    const size_t cmd_count = sizeof(i8042_cmds) / sizeof(irq_cmd_t);
    irq_cmd_t cmds[cmd_count];

    int rc;
    bool kbd_bound = false;
    bool aux_bound = false;

    dev->kbd_fun = NULL;
    dev->aux_fun = NULL;

    if (reg_size < sizeof(i8042_regs_t)) {
        rc = EINVAL;
        goto error;
    }

    if (pio_enable(regs, sizeof(i8042_regs_t), (void **) &dev->regs) != 0) {
        rc = EIO;
        goto error;
    }

    dev->kbd_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2a");
    if (dev->kbd_fun == NULL) {
        rc = ENOMEM;
        goto error;
    };

    rc = ddf_fun_add_match_id(dev->kbd_fun, "char/xtkbd", 90);
    if (rc != EOK)
        goto error;

    dev->aux_fun = ddf_fun_create(ddf_dev, fun_inner, "ps2b");
    if (dev->aux_fun == NULL) {
        rc = ENOMEM;
        goto error;
    }

    rc = ddf_fun_add_match_id(dev->aux_fun, "char/ps2mouse", 90);
    if (rc != EOK)
        goto error;

    ddf_fun_set_ops(dev->kbd_fun, &ops);
    ddf_fun_set_ops(dev->aux_fun, &ops);

    buffer_init(&dev->kbd_buffer, dev->kbd_data, BUFFER_SIZE);
    buffer_init(&dev->aux_buffer, dev->aux_data, BUFFER_SIZE);
    fibril_mutex_initialize(&dev->write_guard);

    rc = ddf_fun_bind(dev->kbd_fun);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed to bind keyboard function: %s.",
                ddf_fun_get_name(dev->kbd_fun));
        goto error;
    }
    kbd_bound = true;

    rc = ddf_fun_bind(dev->aux_fun);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed to bind aux function: %s.",
                ddf_fun_get_name(dev->aux_fun));
        goto error;
    }
    aux_bound = true;

    /* Disable kbd and aux */
    wait_ready(dev);
    pio_write_8(&dev->regs->status, i8042_CMD_WRITE_CMDB);
    wait_ready(dev);
    pio_write_8(&dev->regs->data, i8042_KBD_DISABLE | i8042_AUX_DISABLE);

    /* Flush all current IO */
    while (pio_read_8(&dev->regs->status) & i8042_OUTPUT_FULL)
        (void) pio_read_8(&dev->regs->data);

    memcpy(ranges, i8042_ranges, sizeof(i8042_ranges));
    ranges[0].base = (uintptr_t) regs;

    memcpy(cmds, i8042_cmds, sizeof(i8042_cmds));
    cmds[0].addr = (void *) &(((i8042_regs_t *) regs)->status);
    cmds[3].addr = (void *) &(((i8042_regs_t *) regs)->data);

    irq_code_t irq_code = {
        .rangecount = range_count,
        .ranges = ranges,
        .cmdcount = cmd_count,
        .cmds = cmds
    };

    rc = register_interrupt_handler(ddf_dev, irq_kbd, i8042_irq_handler,
                                    &irq_code);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed set handler for kbd: %s.",
                ddf_dev_get_name(ddf_dev));
        goto error;
    }

    rc = register_interrupt_handler(ddf_dev, irq_mouse, i8042_irq_handler,
                                    &irq_code);
    if (rc != EOK) {
        ddf_msg(LVL_ERROR, "Failed set handler for mouse: %s.",
                ddf_dev_get_name(ddf_dev));
        goto error;
    }

    /* Enable interrupts */
    async_sess_t *parent_sess = ddf_dev_parent_sess_get(ddf_dev);
    assert(parent_sess != NULL);

    const bool enabled = hw_res_enable_interrupt(parent_sess);
    if (!enabled) {
        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to enable interrupts: %s.",
                ddf_dev_get_name(ddf_dev));
        rc = EIO;
        goto error;
    }

    /* Enable port interrupts. */
    wait_ready(dev);
    pio_write_8(&dev->regs->status, i8042_CMD_WRITE_CMDB);
    wait_ready(dev);
    pio_write_8(&dev->regs->data, i8042_KBD_IE | i8042_KBD_TRANSLATE |
                i8042_AUX_IE);

    return EOK;
error:
    if (kbd_bound)
        ddf_fun_unbind(dev->kbd_fun);
    if (aux_bound)
        ddf_fun_unbind(dev->aux_fun);
    if (dev->kbd_fun != NULL)
        ddf_fun_destroy(dev->kbd_fun);
    if (dev->aux_fun != NULL)
        ddf_fun_destroy(dev->aux_fun);

    return rc;
}
Exemplo n.º 15
0
/** Wait until it is safe to write to the device. */
static void wait_ready(i8042_t *dev)
{
    assert(dev);
    while (pio_read_8(&dev->regs->status) & i8042_INPUT_FULL);
}
Exemplo n.º 16
0
uint8_t hda_reg8_read(uint8_t *r)
{
	return pio_read_8(r);
}