예제 #1
0
/** Initialize a new ddf driver instance of i8042 driver
 *
 * @param[in] device DDF instance of the device to initialize.
 *
 * @return Error code.
 *
 */
static int i8042_dev_add(ddf_dev_t *device)
{
	if (!device)
		return EINVAL;
	
	uintptr_t io_regs = 0;
	size_t io_size = 0;
	int kbd = 0;
	int mouse = 0;
	
	int ret = get_my_registers(device, &io_regs, &io_size, &kbd, &mouse);
	CHECK_RET_RETURN(ret, "Failed to get registers: %s.",
	    str_error(ret));
	ddf_msg(LVL_DEBUG, "I/O regs at %p (size %zuB), IRQ kbd %d, IRQ mouse %d.",
	    (void *) io_regs, io_size, kbd, mouse);
	
	i8042_t *i8042 = ddf_dev_data_alloc(device, sizeof(i8042_t));
	ret = (i8042 == NULL) ? ENOMEM : EOK;
	CHECK_RET_RETURN(ret, "Failed to allocate i8042 driver instance.");
	
	ret = i8042_init(i8042, (void *) io_regs, io_size, kbd, mouse, device);
	CHECK_RET_RETURN(ret, "Failed to initialize i8042 driver: %s.",
	    str_error(ret));
	
	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
	return EOK;
}
예제 #2
0
파일: devdrv.c 프로젝트: jvesely/helenos
const char *usb_device_get_name(usb_device_t *usb_dev)
{
	assert(usb_dev);
	if (usb_dev->ddf_dev)
		return ddf_dev_get_name(usb_dev->ddf_dev);
	return NULL;
}
예제 #3
0
static int amdm37x_dispc_dev_add(ddf_dev_t *dev)
{
	assert(dev);
	/* Visualizer part */
	ddf_fun_t *fun = ddf_fun_create(dev, fun_exposed, "viz");
	if (!fun) {
		ddf_log_error("Failed to create visualizer function\n");
		return ENOMEM;
	}

	visualizer_t *vis = ddf_fun_data_alloc(fun, sizeof(visualizer_t));
	if (!vis) {
		ddf_log_error("Failed to allocate visualizer structure\n");
		ddf_fun_destroy(fun);
		return ENOMEM;
	}

	graph_init_visualizer(vis);
	vis->reg_svc_handle = ddf_fun_get_handle(fun);

	ddf_fun_set_ops(fun, &graph_fun_ops);
	/* Hw part */
	amdm37x_dispc_t *dispc =
	    ddf_dev_data_alloc(dev, sizeof(amdm37x_dispc_t));
	if (!dispc) {
		ddf_log_error("Failed to allocate dispc structure\n");
		ddf_fun_destroy(fun);
		return ENOMEM;
	}

	int ret = amdm37x_dispc_init(dispc, vis);
	if (ret != EOK) {
		ddf_log_error("Failed to init dispc: %s\n", str_error(ret));
		ddf_fun_destroy(fun);
		return ret;
	}

	/* Report to devman */
	ret = ddf_fun_bind(fun);
	if (ret != EOK) {
		ddf_log_error("Failed to bind function: %s\n", str_error(ret));
		amdm37x_dispc_fini(dispc);
		ddf_fun_destroy(fun);
		return ret;
	}
	ddf_fun_add_to_category(fun, "visualizer");

	ddf_log_note("Added device `%s'\n", ddf_dev_get_name(dev));
	return EOK;
}
예제 #4
0
/** Initialize a new ddf driver instance for uhci hc and hub.
 *
 * @param[in] device DDF instance of the device to initialize.
 * @return Error code.
 */
int uhci_dev_add(ddf_dev_t *device)
{
	usb_log_debug2("uhci_dev_add() called\n");
	assert(device);

	const int ret = device_setup_uhci(device);
	if (ret != EOK) {
		usb_log_error("Failed to initialize UHCI driver: %s.\n",
		    str_error(ret));
	} else {
		usb_log_info("Controlling new UHCI device '%s'.\n",
		    ddf_dev_get_name(device));
	}

	return ret;
}
예제 #5
0
/** Initialize a new ddf driver instance
 *
 * @param[in] device DDF instance of the device to initialize.
 * @return Error code.
 */
static int mouse_add(ddf_dev_t *device)
{
	if (!device)
		return EINVAL;

#define CHECK_RET_RETURN(ret, message...) \
if (ret != EOK) { \
	ddf_msg(LVL_ERROR, message); \
	return ret; \
} else (void)0

	ps2_mouse_t *mouse = ddf_dev_data_alloc(device, sizeof(ps2_mouse_t));
	int ret = (mouse == NULL) ? ENOMEM : EOK;
	CHECK_RET_RETURN(ret, "Failed to allocate mouse driver instance.");

	ret = ps2_mouse_init(mouse, device);
	CHECK_RET_RETURN(ret,
	    "Failed to initialize mouse driver: %s.", str_error(ret));

	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
	return EOK;
}
예제 #6
0
파일: main.c 프로젝트: jvesely/helenos
/** Initialize a new ddf driver instance of the driver
 *
 * @param[in] device DDF instance of the device to initialize.
 *
 * @return Error code.
 *
 */
static int at_kbd_add(ddf_dev_t *device)
{
	int rc;

	if (!device)
		return EINVAL;

	at_kbd_t *kbd = ddf_dev_data_alloc(device, sizeof(at_kbd_t));
	if (kbd == NULL) {
		ddf_msg(LVL_ERROR, "Failed to allocate AT_KBD driver instance.");
		return ENOMEM;
	}

	rc = at_kbd_init(kbd, device);
	if (rc != EOK) {
		ddf_msg(LVL_ERROR, "Failed to initialize AT_KBD driver: %s.",
		    str_error(rc));
    		return rc;
	}

	ddf_msg(LVL_NOTE, "Controlling '%s' (%" PRIun ").",
	    ddf_dev_get_name(device), ddf_dev_get_handle(device));
	return EOK;
}
예제 #7
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;
}