/** 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; }
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; }
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; }
/** 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; }
/** 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; }
/** 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; }
/** 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; }