/* * SMBUS API FUNCTIONS * * Called from ig4iic_pci_attach/detach() */ int ig4iic_attach(ig4iic_softc_t *sc) { int error; uint32_t v; v = reg_read(sc, IG4_REG_COMP_TYPE); v = reg_read(sc, IG4_REG_COMP_PARAM1); v = reg_read(sc, IG4_REG_GENERAL); if ((v & IG4_GENERAL_SWMODE) == 0) { v |= IG4_GENERAL_SWMODE; reg_write(sc, IG4_REG_GENERAL, v); v = reg_read(sc, IG4_REG_GENERAL); } v = reg_read(sc, IG4_REG_SW_LTR_VALUE); v = reg_read(sc, IG4_REG_AUTO_LTR_VALUE); v = reg_read(sc, IG4_REG_COMP_VER); if (v != IG4_COMP_VER) { error = ENXIO; goto done; } v = reg_read(sc, IG4_REG_SS_SCL_HCNT); v = reg_read(sc, IG4_REG_SS_SCL_LCNT); v = reg_read(sc, IG4_REG_FS_SCL_HCNT); v = reg_read(sc, IG4_REG_FS_SCL_LCNT); v = reg_read(sc, IG4_REG_SDA_HOLD); v = reg_read(sc, IG4_REG_SS_SCL_HCNT); reg_write(sc, IG4_REG_FS_SCL_HCNT, v); v = reg_read(sc, IG4_REG_SS_SCL_LCNT); reg_write(sc, IG4_REG_FS_SCL_LCNT, v); /* * Program based on a 25000 Hz clock. This is a bit of a * hack (obviously). The defaults are 400 and 470 for standard * and 60 and 130 for fast. The defaults for standard fail * utterly (presumably cause an abort) because the clock time * is ~18.8ms by default. This brings it down to ~4ms (for now). */ reg_write(sc, IG4_REG_SS_SCL_HCNT, 100); reg_write(sc, IG4_REG_SS_SCL_LCNT, 125); reg_write(sc, IG4_REG_FS_SCL_HCNT, 100); reg_write(sc, IG4_REG_FS_SCL_LCNT, 125); /* * Use a threshold of 1 so we get interrupted on each character, * allowing us to use mtx_sleep() in our poll code. Not perfect * but this is better than using DELAY() for receiving data. * * See ig4_var.h for details on interrupt handler synchronization. */ reg_write(sc, IG4_REG_RX_TL, 1); reg_write(sc, IG4_REG_CTL, IG4_CTL_MASTER | IG4_CTL_SLAVE_DISABLE | IG4_CTL_RESTARTEN | IG4_CTL_SPEED_STD); sc->smb = device_add_child(sc->dev, "smbus", -1); if (sc->smb == NULL) { device_printf(sc->dev, "smbus driver not found\n"); error = ENXIO; goto done; } #if 0 /* * Don't do this, it blows up the PCI config */ reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT); reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT); #endif /* * Interrupt on STOP detect or receive character ready */ reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | IG4_INTR_RX_FULL); mtx_lock(&sc->io_lock); if (set_controller(sc, 0)) device_printf(sc->dev, "controller error during attach-1\n"); if (set_controller(sc, IG4_I2C_ENABLE)) device_printf(sc->dev, "controller error during attach-2\n"); mtx_unlock(&sc->io_lock); error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ig4iic_intr, sc, &sc->intr_handle); if (error) { device_printf(sc->dev, "Unable to setup irq: error %d\n", error); } sc->enum_hook.ich_func = ig4iic_start; sc->enum_hook.ich_arg = sc->dev; /* We have to wait until interrupts are enabled. I2C read and write * only works if the interrupts are available. */ if (config_intrhook_establish(&sc->enum_hook) != 0) error = ENOMEM; else error = 0; done: return (error); }
/** * Tests the cgroup_compare_cgroup() api under different scenarios * @param ctl1 controller 1 to be used for testing * @param ctl2 controller 1 to be used for testing * @param the test number */ void test_cgroup_compare_cgroup(int ctl1, int ctl2, int i) { int retval; struct cntl_val_t cval; cval.val_int64 = 0; cval.val_uint64 = 0; cval.val_bool = 0; strcpy(cval.val_string, "5000"); struct cgroup *cgroup1 = NULL, *cgroup2 = NULL; struct cgroup_controller *controller = NULL; char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; char wr[SIZE], extra[] = "in cgroup_compare_cgroup"; retval = cgroup_compare_cgroup(NULL, NULL); if (retval) message(i++, PASS, "compare_cgroup()", retval, info[NULLGRP]); else message(i++, FAIL, "compare_cgroup()", retval, info[NULLGRP]); cgroup1 = cgroup_new_cgroup("testgroup"); cgroup2 = cgroup_new_cgroup("testgroup"); cgroup_set_uid_gid(cgroup1, 0, 0, 0, 0); cgroup_set_uid_gid(cgroup2, 0, 0, 0, 0); retval = set_controller(ctl1, controller_name, control_file); controller = cgroup_add_controller(cgroup1, controller_name); if (controller) { retval = add_control_value(controller, control_file, wr, STRING, cval); if (retval) message(i++, FAIL, wr, retval, extra); } controller = cgroup_add_controller(cgroup2, controller_name); if (controller) { retval = add_control_value(controller, control_file, wr, STRING, cval); if (retval) message(i++, FAIL, wr, retval, extra); } retval = cgroup_compare_cgroup(cgroup1, cgroup2); if (retval) message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]); else message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]); /* Test the api by putting diff number of controllers in cgroups */ retval = set_controller(ctl2, controller_name, control_file); controller = cgroup_add_controller(cgroup2, controller_name); if (controller) { retval = add_control_value(controller, control_file, wr, STRING, cval); if (retval) message(i++, FAIL, wr, retval, extra); } retval = cgroup_compare_cgroup(cgroup1, cgroup2); if (retval == ECGROUPNOTEQUAL) message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]); else message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]); cgroup_free(&cgroup1); cgroup_free(&cgroup2); }
/** * Tests the cgroup_get_cgroup() api under different scenarios * @param ctl1 controller 1 to be used for testing * @param ctl2 controller 1 to be used for testing * @param struct ids the permissions struct * @param the test number */ void test_cgroup_get_cgroup(int ctl1, int ctl2, struct uid_gid_t ids, int i) { struct cgroup *cgroup_filled = NULL, *cgroup_a = NULL, *cgroup_b = NULL; struct cgroup_controller *controller = NULL; char controller_name[FILENAME_MAX], control_file[FILENAME_MAX]; struct cntl_val_t cval = {0, 0, 0, "5000"}; int ret; /* * No need to test the next 3 scenarios separately for Multimnt * so testing them only under single mount */ if (fs_mounted == FS_MOUNTED) { /* 1. Test with nullcgroup first */ ret = cgroup_get_cgroup(NULL); if (ret == ECGROUPNOTALLOWED) message(i++, PASS, "get_cgroup()", ret, info[NULLGRP]); else message(i++, FAIL, "get_cgroup()", ret, info[NULLGRP]); /* 2. Test with invalid name filled cgroup(non existing) */ cgroup_filled = cgroup_new_cgroup("nogroup"); if (!cgroup_filled) message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); ret = cgroup_get_cgroup(cgroup_filled); if (ret) message(i++, PASS, "get_cgroup()", ret, info[NOTCRTDGRP]); else message(i++, FAIL, "get_cgroup()", ret, info[NOTCRTDGRP]); /* Free the allocated cgroup before reallocation */ cgroup_free(&cgroup_filled); /* 3. * Test with name filled cgroup. Ensure the group group1 exists * in the filesystem before calling this test function */ cgroup_filled = cgroup_new_cgroup("group1"); if (!cgroup_filled) message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); ret = cgroup_get_cgroup(cgroup_filled); if (!ret) message(i++, PASS, "get_cgroup()", ret, info[NOMESSAGE]); else message(i++, FAIL, "get_cgroup()", ret, info[NOMESSAGE]); } /* SINGLE & MULTI MOUNT: Create, get and compare a cgroup */ /* get cgroup_a ds and create group_a in filesystem */ cgroup_a = create_new_cgroup_ds(ctl1, "group_a", STRING, cval, ids, 0); if (fs_mounted == FS_MULTI_MOUNTED) { /* Create under another controller also */ ret = set_controller(ctl2, controller_name, control_file); controller = cgroup_add_controller(cgroup_a, controller_name); if (controller) message(i++, PASS, "cgroup_add_controller()", 0, info[NOMESSAGE]); else message(i++, FAIL, "cgroup_add_controller()", -1, info[NOMESSAGE]); } test_cgroup_create_cgroup(0, cgroup_a, "group_a", 0, 1, 1, 00); /* create group_b ds to be filled by cgroup_get_cgroup */ cgroup_b = cgroup_new_cgroup("group_a"); if (!cgroup_b) message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]); /* Fill the ds and compare the two */ ret = cgroup_get_cgroup(cgroup_b); if (!ret) { ret = cgroup_compare_cgroup(cgroup_a, cgroup_b); if (ret == 0) message(i++, PASS, "get_cgroup()", ret, info[SAMEGRP]); else message(i++, FAIL, "get_cgroup()", ret, info[NOMESSAGE]); } else { message(i++, FAIL, "get_cgroup()", ret, info[NOMESSAGE]); } /* Delete this created group from fs to leave fs clean */ if (fs_mounted == FS_MULTI_MOUNTED) test_cgroup_delete_cgroup(0, cgroup_a, "group_a", 1, 1, 0, 0); else test_cgroup_delete_cgroup(0, cgroup_a, "group_a", 0, 1, 0, 0); cgroup_free(&cgroup_a); cgroup_free(&cgroup_b); cgroup_free(&cgroup_filled); }
/* * SMBUS API FUNCTIONS * * Called from ig4iic_pci_attach/detach() */ int ig4iic_attach(ig4iic_softc_t *sc) { int error; uint32_t v; v = reg_read(sc, IG4_REG_COMP_TYPE); printf("type %08x\n", v); v = reg_read(sc, IG4_REG_COMP_PARAM1); printf("params %08x\n", v); v = reg_read(sc, IG4_REG_COMP_VER); printf("version %08x\n", v); if (v != IG4_COMP_VER) { error = ENXIO; goto done; } #if 1 v = reg_read(sc, IG4_REG_SS_SCL_HCNT); printf("SS_SCL_HCNT %08x\n", v); v = reg_read(sc, IG4_REG_SS_SCL_LCNT); printf("SS_SCL_LCNT %08x\n", v); v = reg_read(sc, IG4_REG_FS_SCL_HCNT); printf("FS_SCL_HCNT %08x\n", v); v = reg_read(sc, IG4_REG_FS_SCL_LCNT); printf("FS_SCL_LCNT %08x\n", v); v = reg_read(sc, IG4_REG_SDA_HOLD); printf("HOLD %08x\n", v); v = reg_read(sc, IG4_REG_SS_SCL_HCNT); reg_write(sc, IG4_REG_FS_SCL_HCNT, v); v = reg_read(sc, IG4_REG_SS_SCL_LCNT); reg_write(sc, IG4_REG_FS_SCL_LCNT, v); #endif /* * Program based on a 25000 Hz clock. This is a bit of a * hack (obviously). The defaults are 400 and 470 for standard * and 60 and 130 for fast. The defaults for standard fail * utterly (presumably cause an abort) because the clock time * is ~18.8ms by default. This brings it down to ~4ms (for now). */ reg_write(sc, IG4_REG_SS_SCL_HCNT, 100); reg_write(sc, IG4_REG_SS_SCL_LCNT, 125); reg_write(sc, IG4_REG_FS_SCL_HCNT, 100); reg_write(sc, IG4_REG_FS_SCL_LCNT, 125); /* * Use a threshold of 1 so we get interrupted on each character, * allowing us to use lksleep() in our poll code. Not perfect * but this is better than using DELAY() for receiving data. */ reg_write(sc, IG4_REG_RX_TL, 1); reg_write(sc, IG4_REG_CTL, IG4_CTL_MASTER | IG4_CTL_SLAVE_DISABLE | IG4_CTL_RESTARTEN | IG4_CTL_SPEED_STD); mtx_lock(&sc->mtx); sc->smb = device_add_child(sc->dev, "smbus", -1); if (sc->smb == NULL) { device_printf(sc->dev, "smbus driver not found\n"); error = ENXIO; goto done; } #if 0 /* * Don't do this, it blows up the PCI config */ reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT); reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT); #endif /* * Interrupt on STOP detect or receive character ready */ reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | IG4_INTR_RX_FULL); if (set_controller(sc, 0)) device_printf(sc->dev, "controller error during attach-1\n"); if (set_controller(sc, IG4_I2C_ENABLE)) device_printf(sc->dev, "controller error during attach-2\n"); mtx_unlock(&sc->mtx); error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, NULL, ig4iic_intr, sc, &sc->intr_handle); if (error) { device_printf(sc->dev, "Unable to setup irq: error %d\n", error); goto done; } /* Attach us to the smbus */ error = bus_generic_attach(sc->dev); mtx_lock(&sc->mtx); if (error) { device_printf(sc->dev, "failed to attach child: error %d\n", error); goto done; } sc->generic_attached = 1; done: mtx_unlock(&sc->mtx); return error; }