Exemplo n.º 1
0
/** Register child and inform user about it.
 *
 * @param parent Parent device.
 * @param message Message for the user.
 * @param name Device name.
 * @param match_id Device match id.
 * @param score Device match score.
 */
static int register_fun_verbose(ddf_dev_t *parent, const char *message,
    const char *name, const char *match_id, int match_score, ddf_fun_t **pfun)
{
	ddf_fun_t *fun;
	int rc;

	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);

	fun = ddf_fun_create(parent, fun_inner, name);
	if (fun == NULL) {
		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
		return ENOMEM;
	}

	rc = ddf_fun_add_match_id(fun, match_id, match_score);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
		    name);
		ddf_fun_destroy(fun);
		return rc;
	}

	rc = ddf_fun_bind(fun);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
		    str_error(rc));
		ddf_fun_destroy(fun);
		return rc;
	}

	*pfun = fun;

	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
	return EOK;
}
Exemplo n.º 2
0
/** Register child and inform user about it.
 *
 * @param parent Parent device.
 * @param message Message for the user.
 * @param name Device name.
 * @param match_id Device match id.
 * @param score Device match score.
 */
static int register_fun_verbose(ddf_dev_t *parent, const char *message,
    const char *name, const char *match_id, int match_score,
    int expected_rc, ddf_fun_t **pfun)
{
	ddf_fun_t *fun = NULL;
	int rc;

	ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);

	fun = ddf_fun_create(parent, fun_inner, name);
	if (fun == NULL) {
		ddf_msg(LVL_ERROR, "Failed creating function %s", name);
		rc = ENOMEM;
		goto leave;
	}

	rc = ddf_fun_add_match_id(fun, match_id, match_score);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
		    name);
		goto leave;
	}

	rc = ddf_fun_bind(fun);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
		    str_error(rc));
		goto leave;
	}

	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
	rc = EOK;

leave:
	if (rc != expected_rc) {
		fprintf(stderr,
		    NAME ": Unexpected error registering function `%s'.\n" 
		    NAME ":     Expected \"%s\" but got \"%s\".\n",
		    name, str_error(expected_rc), str_error(rc));
	}

	if ((rc != EOK) && (fun != NULL)) {
		ddf_fun_destroy(fun);
	}

	if (pfun != NULL)
		*pfun = fun;

	return rc;
}
Exemplo n.º 3
0
static bool mac_add_fun(ddf_dev_t *dev, const char *name,
    const char *str_match_id, mac_fun_t *fun_proto)
{
	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
	
	ddf_fun_t *fnode = NULL;
	int rc;
	
	/* Create new device. */
	fnode = ddf_fun_create(dev, fun_inner, name);
	if (fnode == NULL)
		goto failure;
	
	mac_fun_t *fun = ddf_fun_data_alloc(fnode, sizeof(mac_fun_t));
	*fun = *fun_proto;
	
	/* Add match ID */
	rc = ddf_fun_add_match_id(fnode, str_match_id, 100);
	if (rc != EOK)
		goto failure;
	
	/* Set provided operations to the device. */
	ddf_fun_set_ops(fnode, &mac_fun_ops);
	
	/* Register function. */
	if (ddf_fun_bind(fnode) != EOK) {
		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
		goto failure;
	}
	
	return true;
	
failure:
	if (fnode != NULL)
		ddf_fun_destroy(fnode);
	
	ddf_msg(LVL_ERROR, "Failed adding function '%s'.", name);
	
	return false;
}
Exemplo n.º 4
0
static int rootamdm37x_add_fun(ddf_dev_t *dev, const char *name,
    const char *str_match_id, const rootamdm37x_fun_t *fun)
{
	ddf_msg(LVL_DEBUG, "Adding new function '%s'.", name);
	
	/* Create new device function. */
	ddf_fun_t *fnode = ddf_fun_create(dev, fun_inner, name);
	if (fnode == NULL)
		return ENOMEM;
	
	/* Add match id */
	int ret = ddf_fun_add_match_id(fnode, str_match_id, 100);
	if (ret != EOK) {
		ddf_fun_destroy(fnode);
		return ret;
	}
	
	/* Alloc needed data */
	rootamdm37x_fun_t *rf =
	    ddf_fun_data_alloc(fnode, sizeof(rootamdm37x_fun_t));
	if (!rf) {
		ddf_fun_destroy(fnode);
		return ENOMEM;
	}
	*rf = *fun;

	/* Set provided operations to the device. */
	ddf_fun_set_ops(fnode, &rootamdm37x_fun_ops);
	
	/* Register function. */
	ret = ddf_fun_bind(fnode);
	if (ret != EOK) {
		ddf_msg(LVL_ERROR, "Failed binding function %s.", name);
		ddf_fun_destroy(fnode);
		return ret;
	}
	
	return EOK;
}
Exemplo n.º 5
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;
}