예제 #1
0
파일: ata_pmp.c 프로젝트: vkhromov/freebsd
static void
pmpsysctlinit(void *context, int pending)
{
	struct cam_periph *periph;
	struct pmp_softc *softc;
	char tmpstr[80], tmpstr2[80];

	periph = (struct cam_periph *)context;
	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
		return;

	softc = (struct pmp_softc *)periph->softc;
	snprintf(tmpstr, sizeof(tmpstr), "CAM PMP unit %d", periph->unit_number);
	snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);

	sysctl_ctx_init(&softc->sysctl_ctx);
	softc->flags |= PMP_FLAG_SCTX_INIT;
	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
		SYSCTL_STATIC_CHILDREN(_kern_cam_pmp), OID_AUTO, tmpstr2,
		CTLFLAG_RD, 0, tmpstr);
	if (softc->sysctl_tree == NULL) {
		printf("pmpsysctlinit: unable to allocate sysctl tree\n");
		cam_periph_release(periph);
		return;
	}

	cam_periph_release(periph);
}
예제 #2
0
/*
 * Create the OS-specific port helper thread and per-port lock.
 */
void
ahci_os_start_port(struct ahci_port *ap)
{
	char name[16];

	atomic_set_int(&ap->ap_signal, AP_SIGF_INIT | AP_SIGF_THREAD_SYNC);
	lockinit(&ap->ap_lock, "ahcipo", 0, 0);
	lockinit(&ap->ap_sim_lock, "ahcicam", 0, LK_CANRECURSE);
	lockinit(&ap->ap_sig_lock, "ahport", 0, 0);
	sysctl_ctx_init(&ap->sysctl_ctx);
	ksnprintf(name, sizeof(name), "%d", ap->ap_num);
	ap->sysctl_tree = SYSCTL_ADD_NODE(&ap->sysctl_ctx,
				SYSCTL_CHILDREN(ap->ap_sc->sysctl_tree),
				OID_AUTO, name, CTLFLAG_RD, 0, "");

	if ((ap->ap_sc->sc_cap & AHCI_REG_CAP_SALP) &&
	    (ap->ap_sc->sc_cap & (AHCI_REG_CAP_PSC | AHCI_REG_CAP_SSC))) {
		SYSCTL_ADD_PROC(&ap->sysctl_ctx,
			SYSCTL_CHILDREN(ap->sysctl_tree), OID_AUTO,
			"link_pwr_mgmt", CTLTYPE_INT | CTLFLAG_RW, ap, 0,
			ahci_sysctl_link_pwr_mgmt, "I",
			"Link power management policy "
			"(0 = disabled, 1 = medium, 2 = aggressive)");
		SYSCTL_ADD_PROC(&ap->sysctl_ctx,
			SYSCTL_CHILDREN(ap->sysctl_tree), OID_AUTO,
			"link_pwr_state", CTLTYPE_STRING | CTLFLAG_RD, ap, 0,
			ahci_sysctl_link_pwr_state, "A",
			"Link power management state");

	}

	kthread_create(ahci_port_thread, ap, &ap->ap_thread,
		       "%s", PORTNAME(ap));
}
예제 #3
0
파일: canbus.c 프로젝트: JabirTech/Source
static int
canbus_attach(device_t dev)
{
	struct canbus_softc *sc = device_get_softc(dev);
	struct sysctl_oid *canbus_sysctl_tree;

	sc->io_delay_time = CANBE_IO_DELAY_TIME;

	/* I/O resource setup */
	if(alloc_ioresource(dev))
		return (ENXIO);

	/* Dynamic sysctl tree setup */
	sysctl_ctx_init(&sc->canbus_sysctl_ctx);
	canbus_sysctl_tree = SYSCTL_ADD_NODE(&sc->canbus_sysctl_ctx,
	    SYSCTL_STATIC_CHILDREN(/* tree top */), OID_AUTO,
	    "canbus", CTLFLAG_RD, 0, "CanBe I/O Bus");
	SYSCTL_ADD_INT(&sc->canbus_sysctl_ctx,
	    SYSCTL_CHILDREN(canbus_sysctl_tree), OID_AUTO, "io_delay_time",
	    CTLFLAG_RW, &sc->io_delay_time, 0, "CanBe Bus I/O delay time");

	bus_generic_probe(dev);
	bus_generic_attach(dev);

	return (0);
}
예제 #4
0
파일: vpd.c 프로젝트: JabirTech/Source
static int
vpd_attach (device_t dev)
{
	struct vpd_softc *sc;
	char unit[4];
	int error;

	sc = device_get_softc(dev);
	error = 0;

	sc->dev = dev;
	sc->rid = 0;
	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
		RF_ACTIVE);
	if (sc->res == NULL) {
		device_printf(dev, "Unable to allocate memory resource.\n");
		error = ENOMEM;
		goto bad;
	}
	sc->vpd = RES2VPD(sc->res);

	snprintf(unit, sizeof(unit), "%d", device_get_unit(sc->dev));
	snprintf(sc->MachineType, 5, "%.4s", sc->vpd->MachType);
	snprintf(sc->MachineModel, 4, "%.3s", sc->vpd->MachType+4);
	snprintf(sc->BuildID, 10, "%.9s", sc->vpd->BuildID);
	snprintf(sc->BoxSerial, 8, "%.7s", sc->vpd->BoxSerial);
	snprintf(sc->PlanarSerial, 12, "%.11s", sc->vpd->PlanarSerial);

	sysctl_ctx_init(&sc->ctx);
	SYSCTL_ADD_STRING(&sc->ctx,
		SYSCTL_STATIC_CHILDREN(_hw_vpd_machine_type), OID_AUTO,
		unit, CTLFLAG_RD|CTLFLAG_DYN, sc->MachineType, 0, NULL);
	SYSCTL_ADD_STRING(&sc->ctx,
		SYSCTL_STATIC_CHILDREN(_hw_vpd_machine_model), OID_AUTO,
		unit, CTLFLAG_RD|CTLFLAG_DYN, sc->MachineModel, 0, NULL);
	SYSCTL_ADD_STRING(&sc->ctx,
		SYSCTL_STATIC_CHILDREN(_hw_vpd_build_id), OID_AUTO,
		unit, CTLFLAG_RD|CTLFLAG_DYN, sc->BuildID, 0, NULL);
	SYSCTL_ADD_STRING(&sc->ctx,
		SYSCTL_STATIC_CHILDREN(_hw_vpd_serial_box), OID_AUTO,
		unit, CTLFLAG_RD|CTLFLAG_DYN, sc->BoxSerial, 0, NULL);
	SYSCTL_ADD_STRING(&sc->ctx,
		SYSCTL_STATIC_CHILDREN(_hw_vpd_serial_planar), OID_AUTO,
		unit, CTLFLAG_RD|CTLFLAG_DYN, sc->PlanarSerial, 0, NULL);

	device_printf(dev, "Machine Type: %.4s, Model: %.3s, Build ID: %.9s\n",
		sc->MachineType, sc->MachineModel, sc->BuildID);
	device_printf(dev, "Box Serial: %.7s, Planar Serial: %.11s\n",
		sc->BoxSerial, sc->PlanarSerial);
		
	return (0);
bad:
	if (sc->res)
		bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
	return (error);
}
예제 #5
0
static int
acpi_panasonic_attach(device_t dev)
{
	struct acpi_panasonic_softc *sc;
	struct acpi_softc *acpi_sc;
	ACPI_STATUS status;
	int i;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->handle = acpi_get_handle(dev);

	acpi_sc = acpi_device_get_parent_softc(dev);

	/* Build sysctl tree */
	sysctl_ctx_init(&sc->sysctl_ctx);
	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO,
	    "panasonic", CTLFLAG_RD, 0, "");
	for (i = 0; sysctl_table[i].name != NULL; i++) {
		SYSCTL_ADD_PROC(&sc->sysctl_ctx,
		    SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
		    sysctl_table[i].name,
		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
		    sc, i, acpi_panasonic_sysctl, "I", "");
	}

#if 0
	/* Activate hotkeys */
	status = AcpiEvaluateObject(sc->handle, "", NULL, NULL);
	if (ACPI_FAILURE(status)) {
		device_printf(dev, "enable FN keys failed\n");
		sysctl_ctx_free(&sc->sysctl_ctx);
		return (ENXIO);
	}
#endif

	/* Handle notifies */
	status = AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY,
	    acpi_panasonic_notify, sc);
	if (ACPI_FAILURE(status)) {
		device_printf(dev, "couldn't install notify handler - %s\n",
		    AcpiFormatException(status));
		sysctl_ctx_free(&sc->sysctl_ctx);
		return (ENXIO);
	}

	/* Install power profile event handler */
	sc->power_evh = EVENTHANDLER_REGISTER(power_profile_change,
	    acpi_panasonic_power_profile, sc->handle, 0);

	return (0);
}
예제 #6
0
static void
vmm_init(void)
{
	sysctl_ctx_init(&vmm_sysctl_ctx);
	vmm_sysctl_tree = SYSCTL_ADD_NODE(&vmm_sysctl_ctx,
	    SYSCTL_STATIC_CHILDREN(_hw),
	    OID_AUTO, "vmm",
	    CTLFLAG_RD, 0, "VMM options");

	if (cpu_vendor_id == CPU_VENDOR_INTEL) {
		ctl = get_ctl_intel();
	} else if (cpu_vendor_id == CPU_VENDOR_AMD) {
		ctl = get_ctl_amd();
	}

	if (ctl->init()) {
		SYSCTL_ADD_INT(&vmm_sysctl_ctx,
		    SYSCTL_CHILDREN(vmm_sysctl_tree),
		    OID_AUTO, "enable", CTLFLAG_RD,
		    &vmm_enabled, 0,
		    "enable not supported");
	} else {
		SYSCTL_ADD_STRING(&vmm_sysctl_ctx,
		    SYSCTL_CHILDREN(vmm_sysctl_tree),
		    OID_AUTO, "type", CTLFLAG_RD,
		    ctl->name, 0,
		    "Type of the VMM");
		SYSCTL_ADD_PROC(&vmm_sysctl_ctx,
		    SYSCTL_CHILDREN(vmm_sysctl_tree),
		    OID_AUTO, "enable", CTLTYPE_INT | CTLFLAG_WR,
		    NULL, sizeof vmm_enabled, sysctl_vmm_enable, "I",
		    "Control the state of the VMM");
		SYSCTL_ADD_INT(&vmm_sysctl_ctx,
		    SYSCTL_CHILDREN(vmm_sysctl_tree),
		    OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW,
		    &vmm_debug, 0,
		    "vmm debugging");

		if (ctl->enable()) {
			kprintf("VMM: vmm enable() failed\n");
		} else {
			vmm_enabled = 1;
		}

		EVENTHANDLER_REGISTER(shutdown_pre_sync, vmm_shutdown, NULL, SHUTDOWN_PRI_DEFAULT-1);
	}
}
예제 #7
0
static void
poll_comm_init(int cpuid)
{
	struct poll_comm *comm;
	char cpuid_str[16];

	comm = kmalloc(sizeof(*comm), M_DEVBUF, M_WAITOK | M_ZERO);

	if (ifpoll_stfrac < 0)
		ifpoll_stfrac = IFPOLL_STFRAC_DEFAULT;
	if (ifpoll_txfrac < 0)
		ifpoll_txfrac = IFPOLL_TXFRAC_DEFAULT;

	comm->pollhz = ifpoll_pollhz;
	comm->poll_cpuid = cpuid;
	comm->poll_stfrac = ifpoll_stfrac;
	comm->poll_txfrac = ifpoll_txfrac;

	ksnprintf(cpuid_str, sizeof(cpuid_str), "%d", cpuid);

	sysctl_ctx_init(&comm->sysctl_ctx);
	comm->sysctl_tree = SYSCTL_ADD_NODE(&comm->sysctl_ctx,
			    SYSCTL_STATIC_CHILDREN(_net_ifpoll),
			    OID_AUTO, cpuid_str, CTLFLAG_RD, 0, "");

	SYSCTL_ADD_PROC(&comm->sysctl_ctx, SYSCTL_CHILDREN(comm->sysctl_tree),
			OID_AUTO, "pollhz", CTLTYPE_INT | CTLFLAG_RW,
			comm, 0, sysctl_pollhz,
			"I", "Device polling frequency");

	if (cpuid == 0) {
		SYSCTL_ADD_PROC(&comm->sysctl_ctx,
				SYSCTL_CHILDREN(comm->sysctl_tree),
				OID_AUTO, "status_frac",
				CTLTYPE_INT | CTLFLAG_RW,
				comm, 0, sysctl_stfrac,
				"I", "# of cycles before status is polled");
	}
	SYSCTL_ADD_PROC(&comm->sysctl_ctx, SYSCTL_CHILDREN(comm->sysctl_tree),
			OID_AUTO, "tx_frac", CTLTYPE_INT | CTLFLAG_RW,
			comm, 0, sysctl_txfrac,
			"I", "# of cycles before TX is polled");

	poll_common[cpuid] = comm;
}
예제 #8
0
void
mlx5e_create_stats(struct sysctl_ctx_list *ctx,
    struct sysctl_oid_list *parent, const char *buffer,
    const char **desc, unsigned num, u64 * arg)
{
	struct sysctl_oid *node;
	unsigned x;

	sysctl_ctx_init(ctx);

	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO,
	    buffer, CTLFLAG_RD, NULL, "Statistics");
	if (node == NULL)
		return;
	for (x = 0; x != num; x++) {
		SYSCTL_ADD_UQUAD(ctx, SYSCTL_CHILDREN(node), OID_AUTO,
		    desc[2 * x], CTLFLAG_RD, arg + x, desc[2 * x + 1]);
	}
}
예제 #9
0
static int
zy7_devcfg_init_fclk_sysctl(struct zy7_devcfg_softc *sc)
{
	struct sysctl_oid *fclk_node;
	char fclk_num[4];
	int i;

	sysctl_ctx_init(&sc->sysctl_tree);
	sc->sysctl_tree_top = SYSCTL_ADD_NODE(&sc->sysctl_tree,
	    SYSCTL_STATIC_CHILDREN(_hw_fpga), OID_AUTO, "fclk",
	    CTLFLAG_RD, 0, "");
	if (sc->sysctl_tree_top == NULL) {
		sysctl_ctx_free(&sc->sysctl_tree);
		return (-1);
	}

	for (i = 0; i < FCLK_NUM; i++) {
		snprintf(fclk_num, sizeof(fclk_num), "%d", i);
		fclk_node = SYSCTL_ADD_NODE(&sc->sysctl_tree,
		    SYSCTL_CHILDREN(sc->sysctl_tree_top), OID_AUTO, fclk_num,
		    CTLFLAG_RD, 0, "");

		SYSCTL_ADD_INT(&sc->sysctl_tree,
		    SYSCTL_CHILDREN(fclk_node), OID_AUTO,
		    "actual_freq", CTLFLAG_RD, 
		    &fclk_configs[i].actual_frequency, i,
		    "Actual frequency");
		SYSCTL_ADD_PROC(&sc->sysctl_tree,
		    SYSCTL_CHILDREN(fclk_node), OID_AUTO,
		    "freq", CTLFLAG_RW | CTLTYPE_INT, 
		    &fclk_configs[i], i,
		    zy7_devcfg_fclk_sysctl_freq,
		    "I", "Configured frequency");
		SYSCTL_ADD_PROC(&sc->sysctl_tree,
		    SYSCTL_CHILDREN(fclk_node), OID_AUTO,
		    "source", CTLFLAG_RW | CTLTYPE_STRING, 
		    &fclk_configs[i], i, 
		    zy7_devcfg_fclk_sysctl_source,
		    "A", "Clock source");
	}

	return (0);
}
예제 #10
0
static int
ahci_attach (device_t dev)
{
	struct ahci_softc *sc = device_get_softc(dev);
	char name[16];
	int error;

	sc->sc_ad = ahci_lookup_device(dev);
	if (sc->sc_ad == NULL)
		return(ENXIO);

	/*
	 * Some chipsets do not properly implement the AHCI spec and may
	 * require the link speed to be specifically requested.
	 */
	if (kgetenv("hint.ahci.force150"))
		AhciForceGen = 1;
	if (kgetenv("hint.ahci.force300"))
		AhciForceGen = 2;
	if (kgetenv("hint.ahci.force600"))
		AhciForceGen = 3;

	if (kgetenv("hint.ahci.nofeatures"))
		AhciNoFeatures = -1;

	if (kgetenv("hint.ahci.forcefbss"))
		sc->sc_flags |= AHCI_F_FORCE_FBSS;

	sysctl_ctx_init(&sc->sysctl_ctx);
	ksnprintf(name, sizeof(name), "%s%d",
		device_get_name(dev), device_get_unit(dev));
	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
				SYSCTL_STATIC_CHILDREN(_hw),
				OID_AUTO, name, CTLFLAG_RD, 0, "");

	error = sc->sc_ad->ad_attach(dev);
	if (error) {
		sysctl_ctx_free(&sc->sysctl_ctx);
		sc->sysctl_tree = NULL;
	}
	return (error);
}
예제 #11
0
static void
stpoll_init(void)
{
	struct stpoll_ctx *st_ctx = &stpoll_context;
	const struct poll_comm *comm = poll_common[0];

	sysctl_ctx_init(&st_ctx->poll_sysctl_ctx);
	st_ctx->poll_sysctl_tree = SYSCTL_ADD_NODE(&st_ctx->poll_sysctl_ctx,
				   SYSCTL_CHILDREN(comm->sysctl_tree),
				   OID_AUTO, "status", CTLFLAG_RD, 0, "");

	SYSCTL_ADD_UINT(&st_ctx->poll_sysctl_ctx,
			SYSCTL_CHILDREN(st_ctx->poll_sysctl_tree),
			OID_AUTO, "handlers", CTLFLAG_RD,
			&st_ctx->poll_handlers, 0,
			"Number of registered status poll handlers");

	netmsg_init(&st_ctx->poll_netmsg, NULL, &netisr_adone_rport,
		    0, stpoll_handler);
}
예제 #12
0
static void
fhaold_init(void *foo)
{
	struct fha_params *softc;

	softc = &fhaold_softc;

	bzero(softc, sizeof(*softc));

	/*
	 * Setup the callbacks for this FHA personality.
	 */
	softc->callbacks.get_procnum = fhaold_get_procnum;
	softc->callbacks.realign = fhaold_realign;
	softc->callbacks.get_fh = fhaold_get_fh;
	softc->callbacks.is_read = fhaold_is_read;
	softc->callbacks.is_write = fhaold_is_write;
	softc->callbacks.get_offset = fhaold_get_offset;
	softc->callbacks.no_offset = fhaold_no_offset;
	softc->callbacks.set_locktype = fhaold_set_locktype;
	softc->callbacks.fhe_stats_sysctl = fheold_stats_sysctl;

	snprintf(softc->server_name, sizeof(softc->server_name),
	    FHAOLD_SERVER_NAME);

	softc->pool = &nfsrv_pool;

	/*
	 * Initialize the sysctl context list for the fha module.
	 */
	sysctl_ctx_init(&softc->sysctl_ctx);
	softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
	    SYSCTL_STATIC_CHILDREN(_vfs_nfsrv), OID_AUTO, "fha", CTLFLAG_RD,
	    0, "fha node");
	if (softc->sysctl_tree == NULL) {
		printf("%s: unable to allocate sysctl tree\n", __func__);
		return;
	}
	fha_init(softc);
}
예제 #13
0
static int
acpi_cpu_attach(device_t dev)
{
    ACPI_BUFFER		   buf;
    ACPI_OBJECT		   arg, *obj;
    ACPI_OBJECT_LIST	   arglist;
    struct pcpu		   *pcpu_data;
    struct acpi_cpu_softc *sc;
    struct acpi_softc	  *acpi_sc;
    ACPI_STATUS		   status;
    u_int		   features;
    int			   cpu_id, drv_count, i;
    driver_t 		  **drivers;
    uint32_t		   cap_set[3];

    /* UUID needed by _OSC evaluation */
    static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
				       0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
				       0x58, 0x71, 0x39, 0x53 };

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->cpu_dev = dev;
    sc->cpu_handle = acpi_get_handle(dev);
    cpu_id = (int)(intptr_t)acpi_get_private(dev);
    cpu_softc[cpu_id] = sc;
    pcpu_data = pcpu_find(cpu_id);
    pcpu_data->pc_device = dev;
    sc->cpu_pcpu = pcpu_data;
    cpu_smi_cmd = AcpiGbl_FADT.SmiCommand;
    cpu_cst_cnt = AcpiGbl_FADT.CstControl;

    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
    if (ACPI_FAILURE(status)) {
	device_printf(dev, "attach failed to get Processor obj - %s\n",
		      AcpiFormatException(status));
	return (ENXIO);
    }
    obj = (ACPI_OBJECT *)buf.Pointer;
    sc->cpu_p_blk = obj->Processor.PblkAddress;
    sc->cpu_p_blk_len = obj->Processor.PblkLength;
    sc->cpu_acpi_id = obj->Processor.ProcId;
    AcpiOsFree(obj);
    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n",
		     device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len));

    /*
     * If this is the first cpu we attach, create and initialize the generic
     * resources that will be used by all acpi cpu devices.
     */
    if (device_get_unit(dev) == 0) {
	/* Assume we won't be using generic Cx mode by default */
	cpu_cx_generic = FALSE;

	/* Install hw.acpi.cpu sysctl tree */
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&cpu_sysctl_ctx);
	cpu_sysctl_tree = SYSCTL_ADD_NODE(&cpu_sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu",
	    CTLFLAG_RD, 0, "node for CPU children");
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3 |
      ACPI_CAP_C1_IO_HALT;

#if defined(__i386__) || defined(__amd64__)
    /*
     * Ask for MWAIT modes if not disabled and interrupts work
     * reasonable with MWAIT.
     */
    if (!acpi_disabled("mwait") && cpu_mwait_usable())
	sc->cpu_features |= ACPI_CAP_SMP_C1_NATIVE | ACPI_CAP_SMP_C3_NATIVE;
#endif

    if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) {
	for (i = 0; i < drv_count; i++) {
	    if (ACPI_GET_FEATURES(drivers[i], &features) == 0)
		sc->cpu_features |= features;
	}
	free(drivers, M_TEMP);
    }

    /*
     * CPU capabilities are specified in
     * Intel Processor Vendor-Specific ACPI Interface Specification.
     */
    if (sc->cpu_features) {
	cap_set[1] = sc->cpu_features;
	status = acpi_EvaluateOSC(sc->cpu_handle, cpu_oscuuid, 1, 2, cap_set,
	    cap_set, false);
	if (ACPI_SUCCESS(status)) {
	    if (cap_set[0] != 0)
		device_printf(dev, "_OSC returned status %#x\n", cap_set[0]);
	}
	else {
	    arglist.Pointer = &arg;
	    arglist.Count = 1;
	    arg.Type = ACPI_TYPE_BUFFER;
	    arg.Buffer.Length = sizeof(cap_set);
	    arg.Buffer.Pointer = (uint8_t *)cap_set;
	    cap_set[0] = 1; /* revision */
	    cap_set[1] = 1; /* number of capabilities integers */
	    cap_set[2] = sc->cpu_features;
	    AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL);
	}
    }

    /* Probe for Cx state support. */
    acpi_cpu_cx_probe(sc);

    return (0);
}
예제 #14
0
static void mlx4_en_create_rl_res(struct mlx4_en_priv *priv,
				  int ring_id, u8 rate_index)
{
	struct mlx4_en_cq	*cq;
	struct mlx4_en_tx_ring	*tx_ring;
	struct mlx4_en_dev	*mdev = priv->mdev;
	int			err = 0;
	int			node = 0;
	int			j;


	if (priv->tx_ring[ring_id]) {
		/* Ring already exists, needs activation */
		/* Make sure drbr queue has no left overs from before */
		tx_ring = priv->tx_ring[ring_id];
		goto activate;
	}

	err = mlx4_en_create_cq(priv, &priv->tx_cq[ring_id],
		MLX4_EN_DEF_RL_TX_RING_SIZE, ring_id, TX, node);
	if (err) {
		en_err(priv, "Failed to create rate limit tx CQ, ring index %u, rate %u\n", ring_id, rate_index);
		goto err_create_cq;
	}

	err = mlx4_en_create_tx_ring(priv, &priv->tx_ring[ring_id],
		MLX4_EN_DEF_RL_TX_RING_SIZE, TXBB_SIZE, node, ring_id);
	if (err) {
		en_err(priv, "Failed to create rate limited tx ring %u, rate %u\n", ring_id, rate_index);
		goto err_create_ring;
	}

	tx_ring = priv->tx_ring[ring_id];

activate:

	sysctl_ctx_init(&tx_ring->rl_data.rl_stats_ctx);
	tx_ring->rl_data.rate_index = rate_index;

	/* Default moderation */
	cq = priv->tx_cq[ring_id];
	cq->moder_cnt = priv->tx_frames;
	cq->moder_time = priv->tx_usecs;

	mutex_lock(&mdev->state_lock);
	if (!priv->port_up) {
		/* No need activating resources, start_port will take care of that */
		tx_ring->rl_data.user_valid = true;
		mutex_unlock(&mdev->state_lock);
		return;
	}

	/* Activate resources */
	err = mlx4_en_activate_cq(priv, cq, ring_id);
	if (err) {
		en_err(priv, "Failed activating Rate Limit Tx CQ\n");
		goto err_activate_resources;
	}

	err = mlx4_en_set_cq_moder(priv, cq);
	if (err) {
		en_err(priv, "Failed setting cq moderation parameters");
		mlx4_en_deactivate_cq(priv, cq);
		goto err_activate_resources;
	}
	en_dbg(DRV, priv, "Resetting index of CQ:%d to -1\n", ring_id);
	cq->buf->wqe_index = cpu_to_be16(0xffff);

	err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
					       MLX4_EN_DEF_RL_USER_PRIO);
	if (err) {
		en_err(priv, "Failed activating rate limit TX ring\n");
		mlx4_en_deactivate_cq(priv, cq);
		goto err_activate_resources;
	}

	/* Arm CQ for TX completions */
	mlx4_en_arm_cq(priv, cq);

	/* Set initial ownership of all Tx TXBBs to SW (1) */
	for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
		*((u32 *) (tx_ring->buf + j)) = INIT_OWNER_BIT;

	/* Set ring as valid */
	tx_ring->rl_data.user_valid = true;
	mutex_unlock(&mdev->state_lock);

	priv->rate_limit_tx_ring_num++;

	/* Add rate limit statistics to sysctl if debug option was enabled */
	if (show_rl_sysctl_info)
		mlx4_en_rate_limit_sysctl_stat(priv, ring_id);
	return;

err_activate_resources:
	mlx4_en_invalidate_rl_ring(priv, ring_id);
	mlx4_en_rl_reused_index_insert(priv, ring_id);
	atomic_subtract_int(&priv->rate_limits[rate_index].ref, 1);
	mutex_unlock(&mdev->state_lock);
	return;

err_create_ring:
	if (priv->tx_cq[ring_id])
		mlx4_en_destroy_cq(priv, &priv->tx_cq[ring_id]);

err_create_cq:
	mlx4_en_rl_reused_index_insert(priv, ring_id);
	atomic_subtract_int(&priv->rate_limits[rate_index].ref, 1);
}
예제 #15
0
static void
vmbus_chan_sysctl_create(struct vmbus_channel *chan)
{
	struct sysctl_oid *ch_tree, *chid_tree, *br_tree;
	struct sysctl_ctx_list *ctx;
	uint32_t ch_id;
	char name[16];

	/*
	 * Add sysctl nodes related to this channel to this
	 * channel's sysctl ctx, so that they can be destroyed
	 * independently upon close of this channel, which can
	 * happen even if the device is not detached.
	 */
	ctx = &chan->ch_sysctl_ctx;
	sysctl_ctx_init(ctx);

	/*
	 * Create dev.NAME.UNIT.channel tree.
	 */
	ch_tree = SYSCTL_ADD_NODE(ctx,
	    SYSCTL_CHILDREN(device_get_sysctl_tree(chan->ch_dev)),
	    OID_AUTO, "channel", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
	if (ch_tree == NULL)
		return;

	/*
	 * Create dev.NAME.UNIT.channel.CHANID tree.
	 */
	if (VMBUS_CHAN_ISPRIMARY(chan))
		ch_id = chan->ch_id;
	else
		ch_id = chan->ch_prichan->ch_id;
	snprintf(name, sizeof(name), "%d", ch_id);
	chid_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ch_tree),
	    OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
	if (chid_tree == NULL)
		return;

	if (!VMBUS_CHAN_ISPRIMARY(chan)) {
		/*
		 * Create dev.NAME.UNIT.channel.CHANID.sub tree.
		 */
		ch_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(chid_tree),
		    OID_AUTO, "sub", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
		if (ch_tree == NULL)
			return;

		/*
		 * Create dev.NAME.UNIT.channel.CHANID.sub.SUBIDX tree.
		 *
		 * NOTE:
		 * chid_tree is changed to this new sysctl tree.
		 */
		snprintf(name, sizeof(name), "%d", chan->ch_subidx);
		chid_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(ch_tree),
		    OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
		if (chid_tree == NULL)
			return;

		SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
		    "chanid", CTLFLAG_RD, &chan->ch_id, 0, "channel id");
	}

	SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
	    "cpu", CTLFLAG_RD, &chan->ch_cpuid, 0, "owner CPU id");
	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
	    "mnf", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
	    chan, 0, vmbus_chan_sysctl_mnf, "I",
	    "has monitor notification facilities");

	br_tree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(chid_tree), OID_AUTO,
	    "br", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "");
	if (br_tree != NULL) {
		/*
		 * Create sysctl tree for RX bufring.
		 */
		vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_rxbr.rxbr, "rx");
		/*
		 * Create sysctl tree for TX bufring.
		 */
		vmbus_br_sysctl_create(ctx, br_tree, &chan->ch_txbr.txbr, "tx");
	}
}
예제 #16
0
static int
acpi_cpu_attach(device_t dev)
{
    struct acpi_cpux_softc *sc = device_get_softc(dev);
    ACPI_HANDLE handle;
    device_t child;
    int cpu_id, cpu_features;
    struct acpi_softc *acpi_sc;

    handle = acpi_get_handle(dev);
    cpu_id = acpi_get_magic(dev);

    acpi_sc = acpi_device_get_parent_softc(dev);
    if (cpu_id == 0) {
	sysctl_ctx_init(&sc->glob_sysctl_ctx);
	sc->glob_sysctl_tree = SYSCTL_ADD_NODE(&sc->glob_sysctl_ctx,
			       SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			       OID_AUTO, "cpu", CTLFLAG_RD, 0,
			       "node for CPU global settings");
    	if (sc->glob_sysctl_tree == NULL)
	    return ENOMEM;
    }

    sysctl_ctx_init(&sc->pcpu_sysctl_ctx);
    sc->pcpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->pcpu_sysctl_ctx,
			   SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			   OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0,
			   "node for per-CPU settings");
    if (sc->pcpu_sysctl_tree == NULL) {
	sysctl_ctx_free(&sc->glob_sysctl_ctx);
	return ENOMEM;
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    cpu_features = ACPI_PDC_MP_C1PXTX | ACPI_PDC_MP_C2C3;
    cpu_features |= acpi_cpu_md_features();

    /*
     * CPU capabilities are specified as a buffer of 32-bit integers:
     * revision, count, and one or more capabilities.
     */
    if (cpu_features) {
	ACPI_OBJECT_LIST arglist;
	uint32_t cap_set[3];
	ACPI_OBJECT arg[4];
	ACPI_STATUS status;

	/* UUID needed by _OSC evaluation */
	static uint8_t cpu_oscuuid[16] = {
	   0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
	   0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
	};

	arglist.Pointer = arg;
	arglist.Count = 4;
	arg[0].Type = ACPI_TYPE_BUFFER;
	arg[0].Buffer.Length = sizeof(cpu_oscuuid);
	arg[0].Buffer.Pointer = cpu_oscuuid;	/* UUID */
	arg[1].Type = ACPI_TYPE_INTEGER;
	arg[1].Integer.Value = 1;		/* revision */
	arg[2].Type = ACPI_TYPE_INTEGER;
	arg[2].Integer.Value = 2;		/* # of capabilities integers */
	arg[3].Type = ACPI_TYPE_BUFFER;
	arg[3].Buffer.Length = sizeof(cap_set[0]) * 2; /* capabilities buffer */
	arg[3].Buffer.Pointer = (uint8_t *)cap_set;
	cap_set[0] = 0;
	cap_set[1] = cpu_features;
	status = AcpiEvaluateObject(handle, "_OSC", &arglist, NULL);

	if (!ACPI_SUCCESS(status)) {
	    if (bootverbose)
		device_printf(dev, "_OSC failed, use _PDC\n");

	    arglist.Pointer = arg;
	    arglist.Count = 1;
	    arg[0].Type = ACPI_TYPE_BUFFER;
	    arg[0].Buffer.Length = sizeof(cap_set);
	    arg[0].Buffer.Pointer = (uint8_t *)cap_set;
	    cap_set[0] = 1; /* revision */
	    cap_set[1] = 1; /* # of capabilities integers */
	    cap_set[2] = cpu_features;
	    AcpiEvaluateObject(handle, "_PDC", &arglist, NULL);
	}
    }

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_cst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);
    sc->cpux_cst = child;

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_pst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);

    bus_generic_attach(dev);

    AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc);

    return 0;
}
예제 #17
0
/*
 * Initialize the software state of the iSCSI ULP driver.
 *
 * ENXIO means firmware didn't set up something that it was supposed to.
 */
static int
cxgbei_init(struct adapter *sc, struct cxgbei_data *ci)
{
	struct sysctl_oid *oid;
	struct sysctl_oid_list *children;
	struct ppod_region *pr;
	uint32_t r;
	int rc;

	MPASS(sc->vres.iscsi.size > 0);
	MPASS(ci != NULL);

	rc = alloc_ci_counters(ci);
	if (rc != 0)
		return (rc);

	read_pdu_limits(sc, &ci->max_tx_pdu_len, &ci->max_rx_pdu_len);

	pr = &ci->pr;
	r = t4_read_reg(sc, A_ULP_RX_ISCSI_PSZ);
	rc = t4_init_ppod_region(pr, &sc->vres.iscsi, r, "iSCSI page pods");
	if (rc != 0) {
		device_printf(sc->dev,
		    "%s: failed to initialize the iSCSI page pod region: %u.\n",
		    __func__, rc);
		free_ci_counters(ci);
		return (rc);
	}

	r = t4_read_reg(sc, A_ULP_RX_ISCSI_TAGMASK);
	r &= V_ISCSITAGMASK(M_ISCSITAGMASK);
	if (r != pr->pr_tag_mask) {
		/*
		 * Recent firmwares are supposed to set up the iSCSI tagmask
		 * but we'll do it ourselves it the computed value doesn't match
		 * what's in the register.
		 */
		device_printf(sc->dev,
		    "tagmask 0x%08x does not match computed mask 0x%08x.\n", r,
		    pr->pr_tag_mask);
		t4_set_reg_field(sc, A_ULP_RX_ISCSI_TAGMASK,
		    V_ISCSITAGMASK(M_ISCSITAGMASK), pr->pr_tag_mask);
	}

	sysctl_ctx_init(&ci->ctx);
	oid = device_get_sysctl_tree(sc->dev);	/* dev.t5nex.X */
	children = SYSCTL_CHILDREN(oid);

	oid = SYSCTL_ADD_NODE(&ci->ctx, children, OID_AUTO, "iscsi", CTLFLAG_RD,
	    NULL, "iSCSI ULP statistics");
	children = SYSCTL_CHILDREN(oid);

	SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_setup_ok",
	    CTLFLAG_RD, &ci->ddp_setup_ok,
	    "# of times DDP buffer was setup successfully.");

	SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_setup_error",
	    CTLFLAG_RD, &ci->ddp_setup_error,
	    "# of times DDP buffer setup failed.");

	SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_bytes",
	    CTLFLAG_RD, &ci->ddp_bytes, "# of bytes placed directly");

	SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "ddp_pdus",
	    CTLFLAG_RD, &ci->ddp_pdus, "# of PDUs with data placed directly.");

	SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "fl_bytes",
	    CTLFLAG_RD, &ci->fl_bytes, "# of data bytes delivered in freelist");

	SYSCTL_ADD_COUNTER_U64(&ci->ctx, children, OID_AUTO, "fl_pdus",
	    CTLFLAG_RD, &ci->fl_pdus,
	    "# of PDUs with data delivered in freelist");

	ci->ddp_threshold = 2048;
	SYSCTL_ADD_UINT(&ci->ctx, children, OID_AUTO, "ddp_threshold",
	    CTLFLAG_RW, &ci->ddp_threshold, 0, "Rx zero copy threshold");

	return (0);
}
예제 #18
0
static int
acpi_cpu_attach(device_t dev)
{
    struct acpi_cpu_softc *sc = device_get_softc(dev);
    ACPI_HANDLE handle;
    device_t child;
    int cpu_id, cpu_features;
    struct acpi_softc *acpi_sc;

    sc->cpu_dev = dev;

    handle = acpi_get_handle(dev);
    cpu_id = acpi_get_magic(dev);

    acpi_sc = acpi_device_get_parent_softc(dev);
    if (cpu_id == 0) {
	sysctl_ctx_init(&sc->glob_sysctl_ctx);
	sc->glob_sysctl_tree = SYSCTL_ADD_NODE(&sc->glob_sysctl_ctx,
			       SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			       OID_AUTO, "cpu", CTLFLAG_RD, 0,
			       "node for CPU global settings");
    	if (sc->glob_sysctl_tree == NULL)
	    return ENOMEM;
    }

    sysctl_ctx_init(&sc->pcpu_sysctl_ctx);
    sc->pcpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->pcpu_sysctl_ctx,
			   SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			   OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0,
			   "node for per-CPU settings");
    if (sc->pcpu_sysctl_tree == NULL) {
	sysctl_ctx_free(&sc->glob_sysctl_ctx);
	return ENOMEM;
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    cpu_features = ACPI_PDC_MP_C1PXTX | ACPI_PDC_MP_C2C3;
    cpu_features |= acpi_cpu_md_features();

    /*
     * CPU capabilities are specified as a buffer of 32-bit integers:
     * revision, count, and one or more capabilities.
     */
    if (cpu_features) {
	uint32_t cap_set[3];
	ACPI_STATUS status;

	cap_set[0] = 0;
	cap_set[1] = cpu_features;
	status = acpi_eval_osc(dev, handle,
	    "4077A616-290C-47BE-9EBD-D87058713953", 1, cap_set, 2);

	if (ACPI_FAILURE(status)) {
	    ACPI_OBJECT_LIST arglist;
	    ACPI_OBJECT arg[4];

	    if (bootverbose)
		device_printf(dev, "_OSC failed, using _PDC\n");

	    arglist.Pointer = arg;
	    arglist.Count = 1;
	    arg[0].Type = ACPI_TYPE_BUFFER;
	    arg[0].Buffer.Length = sizeof(cap_set);
	    arg[0].Buffer.Pointer = (uint8_t *)cap_set;
	    cap_set[0] = 1; /* revision */
	    cap_set[1] = 1; /* # of capabilities integers */
	    cap_set[2] = cpu_features;
	    AcpiEvaluateObject(handle, "_PDC", &arglist, NULL);
	}
    }

    ksnprintf(sc->cpu_sensdev.xname, sizeof(sc->cpu_sensdev.xname), "%s",
	device_get_nameunit(dev));
    sensordev_install(&sc->cpu_sensdev);

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_cst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);
    sc->cpu_cst = child;

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_pst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);
    sc->cpu_pst = child;

    bus_generic_probe(dev);
    bus_generic_attach(dev);

    AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc);

    return 0;
}
예제 #19
0
/*
 * Initializes the names of the ACPI control methods and grabs
 * the current state of all of the ACPI hotkeys into the softc.
 */
static uint8_t
acpi_fujitsu_init(struct acpi_fujitsu_softc *sc)
{
	struct acpi_softc *acpi_sc;
	int i, exists;

	ACPI_SERIAL_ASSERT(fujitsu);

	/* Setup all of the names for each control method */
	sc->_sta.name = "_STA";
	sc->gbll.name = "GBLL";
	sc->gbls.name = "GBLS";
	sc->ghks.name = "GHKS";
	sc->gmou.name = "GMOU";
	sc->gsif.name = "GSIF";
	sc->gvol.name = "GVOL";
	sc->ghks.name = "GHKS";
	sc->gsif.name = "GSIF";
	sc->rbll.name = "RBLL";
	sc->rvol.name = "RVOL";

	/* Determine what hardware functionality is available */
	acpi_fujitsu_check_hardware(sc);

	/* Build the sysctl tree */
	acpi_sc = acpi_device_get_parent_softc(sc->dev);
	sysctl_ctx_init(&sc->sysctl_ctx);
	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
	    OID_AUTO, "fujitsu", CTLFLAG_RD, 0, "");

	for (i = 0; sysctl_table[i].name != NULL; i++) {
		switch(sysctl_table[i].method) {
			case METHOD_GMOU:
				exists = sc->gmou.exists;
				break;
			case METHOD_GBLL:
				exists = sc->gbll.exists;
				break;
			case METHOD_GBLS:
				exists = sc->gbls.exists;
				break;
			case METHOD_GVOL:
			case METHOD_MUTE:
				exists = sc->gvol.exists;
				break;
			case METHOD_RVOL:
				exists = sc->rvol.exists;
				break;
			case METHOD_RBLL:
				exists = sc->rbll.exists;
				break;
			default:
				/* Allow by default */
				exists = 1;
				break;
		}
		if(!exists)
			continue;
		SYSCTL_ADD_PROC(&sc->sysctl_ctx,
		    SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO,
		    sysctl_table[i].name,
		    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
		    sc, i, acpi_fujitsu_sysctl, "I",
		    sysctl_table[i].description);
	}


	/* Set the hotkeys to their initial states */
	if (!acpi_fujitsu_update(sc)) {
		device_printf(sc->dev, "Couldn't init hotkey states\n");
		return (FALSE);
	}

	return (TRUE);
}
예제 #20
0
static int
acpi_cpu_attach(device_t dev)
{
    ACPI_BUFFER		   buf;
    ACPI_OBJECT		   arg[4], *obj;
    ACPI_OBJECT_LIST	   arglist;
    struct pcpu		   *pcpu_data;
    struct acpi_cpu_softc *sc;
    struct acpi_softc	  *acpi_sc;
    ACPI_STATUS		   status;
    u_int		   features;
    int			   cpu_id, drv_count, i;
    driver_t 		  **drivers;
    uint32_t		   cap_set[3];

    /* UUID needed by _OSC evaluation */
    static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
				       0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
				       0x58, 0x71, 0x39, 0x53 };

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->cpu_dev = dev;
    sc->cpu_handle = acpi_get_handle(dev);
    cpu_id = acpi_get_magic(dev);
    cpu_softc[cpu_id] = sc;
    pcpu_data = pcpu_find(cpu_id);
    pcpu_data->pc_device = dev;
    sc->cpu_pcpu = pcpu_data;
    cpu_smi_cmd = AcpiGbl_FADT.SmiCommand;
    cpu_cst_cnt = AcpiGbl_FADT.CstControl;

    buf.Pointer = NULL;
    buf.Length = ACPI_ALLOCATE_BUFFER;
    status = AcpiEvaluateObject(sc->cpu_handle, NULL, NULL, &buf);
    if (ACPI_FAILURE(status)) {
	device_printf(dev, "attach failed to get Processor obj - %s\n",
		      AcpiFormatException(status));
	return (ENXIO);
    }
    obj = (ACPI_OBJECT *)buf.Pointer;
    sc->cpu_p_blk = obj->Processor.PblkAddress;
    sc->cpu_p_blk_len = obj->Processor.PblkLength;
    sc->cpu_acpi_id = obj->Processor.ProcId;
    AcpiOsFree(obj);
    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n",
		     device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len));

    /*
     * If this is the first cpu we attach, create and initialize the generic
     * resources that will be used by all acpi cpu devices.
     */
    if (device_get_unit(dev) == 0) {
	/* Assume we won't be using generic Cx mode by default */
	cpu_cx_generic = FALSE;

	/* Install hw.acpi.cpu sysctl tree */
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&cpu_sysctl_ctx);
	cpu_sysctl_tree = SYSCTL_ADD_NODE(&cpu_sysctl_ctx,
	    SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu",
	    CTLFLAG_RD, 0, "node for CPU children");

	/* Queue post cpu-probing task handler */
	AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_cpu_startup, NULL);
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3;
    if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) {
	for (i = 0; i < drv_count; i++) {
	    if (ACPI_GET_FEATURES(drivers[i], &features) == 0)
		sc->cpu_features |= features;
	}
	free(drivers, M_TEMP);
    }

    /*
     * CPU capabilities are specified as a buffer of 32-bit integers:
     * revision, count, and one or more capabilities.  The revision of
     * "1" is not specified anywhere but seems to match Linux.
     */
    if (sc->cpu_features) {
	arglist.Pointer = arg;
	arglist.Count = 1;
	arg[0].Type = ACPI_TYPE_BUFFER;
	arg[0].Buffer.Length = sizeof(cap_set);
	arg[0].Buffer.Pointer = (uint8_t *)cap_set;
	cap_set[0] = 1; /* revision */
	cap_set[1] = 1; /* number of capabilities integers */
	cap_set[2] = sc->cpu_features;
	AcpiEvaluateObject(sc->cpu_handle, "_PDC", &arglist, NULL);

	/*
	 * On some systems we need to evaluate _OSC so that the ASL
	 * loads the _PSS and/or _PDC methods at runtime.
	 *
	 * TODO: evaluate failure of _OSC.
	 */
	arglist.Pointer = arg;
	arglist.Count = 4;
	arg[0].Type = ACPI_TYPE_BUFFER;
	arg[0].Buffer.Length = sizeof(cpu_oscuuid);
	arg[0].Buffer.Pointer = cpu_oscuuid;	/* UUID */
	arg[1].Type = ACPI_TYPE_INTEGER;
	arg[1].Integer.Value = 1;		/* revision */
	arg[2].Type = ACPI_TYPE_INTEGER;
	arg[2].Integer.Value = 1;		/* count */
	arg[3].Type = ACPI_TYPE_BUFFER;
	arg[3].Buffer.Length = sizeof(cap_set);	/* Capabilities buffer */
	arg[3].Buffer.Pointer = (uint8_t *)cap_set;
	cap_set[0] = 0;
	AcpiEvaluateObject(sc->cpu_handle, "_OSC", &arglist, NULL);
    }

    /* Probe for Cx state support. */
    acpi_cpu_cx_probe(sc);

    /* Finally,  call identify and probe/attach for child devices. */
    bus_generic_probe(dev);
    bus_generic_attach(dev);

    return (0);
}
static void
ue_attach_post_task(struct usb_proc_msg *_task)
{
	struct usb_ether_cfg_task *task =
	    (struct usb_ether_cfg_task *)_task;
	struct usb_ether *ue = task->ue;
	struct ifnet *ifp;
	int error;
	char num[14];			/* sufficient for 32 bits */

	/* first call driver's post attach routine */
	ue->ue_methods->ue_attach_post(ue);

	UE_UNLOCK(ue);

	ue->ue_unit = alloc_unr(ueunit);
	usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0);
	sysctl_ctx_init(&ue->ue_sysctl_ctx);

	ifp = if_alloc(IFT_ETHER);
	if (ifp == NULL) {
		device_printf(ue->ue_dev, "could not allocate ifnet\n");
		goto error;
	}

	ifp->if_softc = ue;
	if_initname(ifp, "ue", ue->ue_unit);
	ifp->if_mtu = ETHERMTU;
	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
	if (ue->ue_methods->ue_ioctl != NULL)
		ifp->if_ioctl = ue->ue_methods->ue_ioctl;
	else
		ifp->if_ioctl = uether_ioctl;
	ifp->if_start = ue_start;
	ifp->if_init = ue_init;
	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
	IFQ_SET_READY(&ifp->if_snd);
	ue->ue_ifp = ifp;

	if (ue->ue_methods->ue_mii_upd != NULL && 
	    ue->ue_methods->ue_mii_sts != NULL) {
		mtx_lock(&Giant);	/* device_xxx() depends on this */
		error = mii_phy_probe(ue->ue_dev, &ue->ue_miibus,
		    ue_ifmedia_upd, ue->ue_methods->ue_mii_sts);
		mtx_unlock(&Giant);
		if (error) {
			device_printf(ue->ue_dev, "MII without any PHY\n");
			goto error;
		}
	}

	if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev));
	ether_ifattach(ifp, ue->ue_eaddr);

	snprintf(num, sizeof(num), "%u", ue->ue_unit);
	ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx,
	    &SYSCTL_NODE_CHILDREN(_net, ue),
	    OID_AUTO, num, CTLFLAG_RD, NULL, "");
	SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx,
	    SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO,
	    "%parent", CTLFLAG_RD, ue, 0,
	    ue_sysctl_parent, "A", "parent device");

	UE_LOCK(ue);
	return;

error:
	free_unr(ueunit, ue->ue_unit);
	if (ue->ue_ifp != NULL) {
		if_free(ue->ue_ifp);
		ue->ue_ifp = NULL;
	}
	UE_LOCK(ue);
	return;
}
예제 #22
0
static int
acpi_tz_attach(device_t dev)
{
    struct acpi_tz_softc	*sc;
    struct acpi_softc		*acpi_sc;
    int				error;
    char			oidname[8];

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->tz_dev = dev;
    sc->tz_handle = acpi_get_handle(dev);
    sc->tz_requested = TZ_ACTIVE_NONE;
    sc->tz_active = TZ_ACTIVE_UNKNOWN;
    sc->tz_thflags = TZ_THFLAG_NONE;
    sc->tz_cooling_proc = NULL;
    sc->tz_cooling_proc_running = FALSE;
    sc->tz_cooling_active = FALSE;
    sc->tz_cooling_updated = FALSE;
    sc->tz_cooling_enabled = FALSE;

    /*
     * Parse the current state of the thermal zone and build control
     * structures.  We don't need to worry about interference with the
     * control thread since we haven't fully attached this device yet.
     */
    if ((error = acpi_tz_establish(sc)) != 0)
	return (error);

    /*
     * Register for any Notify events sent to this zone.
     */
    AcpiInstallNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
			     acpi_tz_notify_handler, sc);

    /*
     * Create our sysctl nodes.
     *
     * XXX we need a mechanism for adding nodes under ACPI.
     */
    if (device_get_unit(dev) == 0) {
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&acpi_tz_sysctl_ctx);
	acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx,
			      SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			      OID_AUTO, "thermal", CTLFLAG_RD, 0, "");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "min_runtime", CTLFLAG_RW,
		       &acpi_tz_min_runtime, 0,
		       "minimum cooling run time in sec");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "polling_rate", CTLFLAG_RW,
		       &acpi_tz_polling_rate, 0, "monitor polling interval in seconds");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
		       "user_override", CTLFLAG_RW, &acpi_tz_override, 0,
		       "allow override of thermal settings");
    }
    sysctl_ctx_init(&sc->tz_sysctl_ctx);
    sprintf(oidname, "tz%d", device_get_unit(dev));
    sc->tz_sysctl_tree = SYSCTL_ADD_NODE(&sc->tz_sysctl_ctx,
					 SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
					 OID_AUTO, oidname, CTLFLAG_RD, 0, "");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_temperature, 0, sysctl_handle_int,
		    "IK", "current thermal zone temperature");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "active", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_active_sysctl, "I", "cooling is active");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "passive_cooling", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_cooling_sysctl, "I",
		    "enable passive (speed reduction) cooling");

    SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		   OID_AUTO, "thermal_flags", CTLFLAG_RD,
		   &sc->tz_thflags, 0, "thermal zone flags");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.psv),
		    acpi_tz_temp_sysctl, "IK", "passive cooling temp setpoint");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.hot),
		    acpi_tz_temp_sysctl, "IK",
		    "too hot temp setpoint (suspend now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_CRT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.crt),
		    acpi_tz_temp_sysctl, "IK",
		    "critical temp setpoint (shutdown now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_ACx", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_zone.ac, sizeof(sc->tz_zone.ac),
		    sysctl_handle_opaque, "IK", "");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC1", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc1),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 1 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC2", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc2),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 2 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TSP", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tsp),
		    acpi_tz_passive_sysctl, "I",
		    "thermal sampling period for passive cooling");

    /*
     * Create thread to service all of the thermal zones.  Register
     * our power profile event handler.
     */
    sc->tz_event = EVENTHANDLER_REGISTER(power_profile_change,
	acpi_tz_power_profile, sc, 0);
    if (acpi_tz_proc == NULL) {
	error = kproc_create(acpi_tz_thread, NULL, &acpi_tz_proc,
	    RFHIGHPID, 0, "acpi_thermal");
	if (error != 0) {
	    device_printf(sc->tz_dev, "could not create thread - %d", error);
	    goto out;
	}
    }

    /*
     * Create a thread to handle passive cooling for 1st zone which
     * has _PSV, _TSP, _TC1 and _TC2.  Users can enable it for other
     * zones manually for now.
     *
     * XXX We enable only one zone to avoid multiple zones conflict
     * with each other since cpufreq currently sets all CPUs to the
     * given frequency whereas it's possible for different thermal
     * zones to specify independent settings for multiple CPUs.
     */
    if (acpi_tz_cooling_unit < 0 && acpi_tz_cooling_is_available(sc))
	sc->tz_cooling_enabled = TRUE;
    if (sc->tz_cooling_enabled) {
	error = acpi_tz_cooling_thread_start(sc);
	if (error != 0) {
	    sc->tz_cooling_enabled = FALSE;
	    goto out;
	}
	acpi_tz_cooling_unit = device_get_unit(dev);
    }

    /*
     * Flag the event handler for a manual invocation by our timeout.
     * We defer it like this so that the rest of the subsystem has time
     * to come up.  Don't bother evaluating/printing the temperature at
     * this point; on many systems it'll be bogus until the EC is running.
     */
    sc->tz_flags |= TZ_FLAG_GETPROFILE;

out:
    if (error != 0) {
	EVENTHANDLER_DEREGISTER(power_profile_change, sc->tz_event);
	AcpiRemoveNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
	    acpi_tz_notify_handler);
	sysctl_ctx_free(&sc->tz_sysctl_ctx);
    }
    return_VALUE (error);
}
예제 #23
0
/*
 * Function name:	twa_attach
 * Description:		Allocates pci resources; updates sc; adds a node to the
 *			sysctl tree to expose the driver version; makes calls
 *			(to the Common Layer) to initialize ctlr, and to
 *			attach to CAM.
 *
 * Input:		dev	-- bus device corresponding to the ctlr
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
static TW_INT32
twa_attach(device_t dev)
{
	struct twa_softc	*sc = device_get_softc(dev);
	TW_UINT32		command;
	TW_INT32		bar_num;
	TW_INT32		bar0_offset;
	TW_INT32		bar_size;
	TW_INT32		error;

	tw_osli_dbg_dprintf(3, sc, "entered");

	sc->ctlr_handle.osl_ctlr_ctxt = sc;

	/* Initialize the softc structure. */
	sc->bus_dev = dev;
	sc->device_id = pci_get_device(dev);

	/* Initialize the mutexes right here. */
	sc->io_lock = &(sc->io_lock_handle);
	mtx_init(sc->io_lock, "tw_osl_io_lock", NULL, MTX_SPIN);
	sc->q_lock = &(sc->q_lock_handle);
	mtx_init(sc->q_lock, "tw_osl_q_lock", NULL, MTX_SPIN);
	sc->sim_lock = &(sc->sim_lock_handle);
	mtx_init(sc->sim_lock, "tw_osl_sim_lock", NULL, MTX_DEF | MTX_RECURSE);

	sysctl_ctx_init(&sc->sysctl_ctxt);
	sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctxt,
		SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
		device_get_nameunit(dev), CTLFLAG_RD, 0, "");
	if (sc->sysctl_tree == NULL) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2000,
			"Cannot add sysctl tree node",
			ENXIO);
		return(ENXIO);
	}
	SYSCTL_ADD_STRING(&sc->sysctl_ctxt, SYSCTL_CHILDREN(sc->sysctl_tree),
		OID_AUTO, "driver_version", CTLFLAG_RD,
		TW_OSL_DRIVER_VERSION_STRING, 0, "TWA driver version");

	/* Make sure we are going to be able to talk to this board. */
	command = pci_read_config(dev, PCIR_COMMAND, 2);
	if ((command & PCIM_CMD_PORTEN) == 0) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2001,
			"Register window not available",
			ENXIO);
		tw_osli_free_resources(sc);
		return(ENXIO);
	}

	/* Force the busmaster enable bit on, in case the BIOS forgot. */
	command |= PCIM_CMD_BUSMASTEREN;
	pci_write_config(dev, PCIR_COMMAND, command, 2);

	/* Allocate the PCI register window. */
	if ((error = tw_cl_get_pci_bar_info(sc->device_id, TW_CL_BAR_TYPE_MEM,
		&bar_num, &bar0_offset, &bar_size))) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x201F,
			"Can't get PCI BAR info",
			error);
		tw_osli_free_resources(sc);
		return(error);
	}
	sc->reg_res_id = PCIR_BARS + bar0_offset;
	if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
				&(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
				== NULL) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2002,
			"Can't allocate register window",
			ENXIO);
		tw_osli_free_resources(sc);
		return(ENXIO);
	}
	sc->bus_tag = rman_get_bustag(sc->reg_res);
	sc->bus_handle = rman_get_bushandle(sc->reg_res);

	/* Allocate and register our interrupt. */
	sc->irq_res_id = 0;
	if ((sc->irq_res = bus_alloc_resource(sc->bus_dev, SYS_RES_IRQ,
				&(sc->irq_res_id), 0, ~0, 1,
				RF_SHAREABLE | RF_ACTIVE)) == NULL) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2003,
			"Can't allocate interrupt",
			ENXIO);
		tw_osli_free_resources(sc);
		return(ENXIO);
	}
	if ((error = twa_setup_intr(sc))) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2004,
			"Can't set up interrupt",
			error);
		tw_osli_free_resources(sc);
		return(error);
	}

	if ((error = tw_osli_alloc_mem(sc))) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2005,
			"Memory allocation failure",
			error);
		tw_osli_free_resources(sc);
		return(error);
	}

	/* Initialize the Common Layer for this controller. */
	if ((error = tw_cl_init_ctlr(&sc->ctlr_handle, sc->flags, sc->device_id,
			TW_OSLI_MAX_NUM_REQUESTS, TW_OSLI_MAX_NUM_AENS,
			sc->non_dma_mem, sc->dma_mem,
			sc->dma_mem_phys
			))) {
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2006,
			"Failed to initialize Common Layer/controller",
			error);
		tw_osli_free_resources(sc);
		return(error);
	}

	/* Create the control device. */
	sc->ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->bus_dev),
			UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
			"twa%d", device_get_unit(sc->bus_dev));
	sc->ctrl_dev->si_drv1 = sc;

	if ((error = tw_osli_cam_attach(sc))) {
		tw_osli_free_resources(sc);
		tw_osli_printf(sc, "error = %d",
			TW_CL_SEVERITY_ERROR_STRING,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2007,
			"Failed to initialize CAM",
			error);
		return(error);
	}

	sc->watchdog_index = 0;
	callout_init(&(sc->watchdog_callout[0]), CALLOUT_MPSAFE);
	callout_init(&(sc->watchdog_callout[1]), CALLOUT_MPSAFE);
	callout_reset(&(sc->watchdog_callout[0]), 5*hz, twa_watchdog, &sc->ctlr_handle);

	return(0);
}
예제 #24
0
static int
acpi_tz_attach(device_t dev)
{
    struct acpi_tz_softc	*sc;
    struct acpi_softc		*acpi_sc;
    int				error;
    char			oidname[8];

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    sc = device_get_softc(dev);
    sc->tz_dev = dev;
    sc->tz_handle = acpi_get_handle(dev);
    sc->tz_requested = TZ_ACTIVE_NONE;
    sc->tz_active = TZ_ACTIVE_UNKNOWN;
    sc->tz_thflags = TZ_THFLAG_NONE;
    sc->tz_cooling_proc = NULL;
    sc->tz_cooling_proc_running = FALSE;
    sc->tz_cooling_active = FALSE;
    sc->tz_cooling_updated = FALSE;
    sc->tz_cooling_enabled = FALSE;

    /*
     * Parse the current state of the thermal zone and build control
     * structures.  We don't need to worry about interference with the
     * control thread since we haven't fully attached this device yet.
     */
    if ((error = acpi_tz_establish(sc)) != 0)
	return (error);

    /*
     * Register for any Notify events sent to this zone.
     */
    AcpiInstallNotifyHandler(sc->tz_handle, ACPI_DEVICE_NOTIFY,
			     acpi_tz_notify_handler, sc);

    /*
     * Create our sysctl nodes.
     *
     * XXX we need a mechanism for adding nodes under ACPI.
     */
    if (device_get_unit(dev) == 0) {
	acpi_sc = acpi_device_get_parent_softc(dev);
	sysctl_ctx_init(&acpi_tz_sysctl_ctx);
	acpi_tz_sysctl_tree = SYSCTL_ADD_NODE(&acpi_tz_sysctl_ctx,
			      SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			      OID_AUTO, "thermal", CTLFLAG_RD, 0, "");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "min_runtime", CTLFLAG_RW,
		       &acpi_tz_min_runtime, 0,
		       "minimum cooling run time in sec");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
		       OID_AUTO, "polling_rate", CTLFLAG_RW,
		       &acpi_tz_polling_rate, 0, "monitor polling interval in seconds");
	SYSCTL_ADD_INT(&acpi_tz_sysctl_ctx,
		       SYSCTL_CHILDREN(acpi_tz_sysctl_tree), OID_AUTO,
		       "user_override", CTLFLAG_RW, &acpi_tz_override, 0,
		       "allow override of thermal settings");
    }
    sysctl_ctx_init(&sc->tz_sysctl_ctx);
    sprintf(oidname, "tz%d", device_get_unit(dev));
    sc->tz_sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&sc->tz_sysctl_ctx,
			 SYSCTL_CHILDREN(acpi_tz_sysctl_tree),
			 OID_AUTO, oidname, CTLFLAG_RD, 0, "", "thermal_zone");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_temperature, 0, sysctl_handle_int,
		    "IK", "current thermal zone temperature");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "active", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_active_sysctl, "I", "cooling is active");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "passive_cooling", CTLTYPE_INT | CTLFLAG_RW,
		    sc, 0, acpi_tz_cooling_sysctl, "I",
		    "enable passive (speed reduction) cooling");

    SYSCTL_ADD_INT(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		   OID_AUTO, "thermal_flags", CTLFLAG_RD,
		   &sc->tz_thflags, 0, "thermal zone flags");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_PSV", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.psv),
		    acpi_tz_temp_sysctl, "IK", "passive cooling temp setpoint");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_HOT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.hot),
		    acpi_tz_temp_sysctl, "IK",
		    "too hot temp setpoint (suspend now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_CRT", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.crt),
		    acpi_tz_temp_sysctl, "IK",
		    "critical temp setpoint (shutdown now)");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_ACx", CTLTYPE_INT | CTLFLAG_RD,
		    &sc->tz_zone.ac, sizeof(sc->tz_zone.ac),
		    sysctl_handle_opaque, "IK", "");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC1", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc1),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 1 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TC2", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tc2),
		    acpi_tz_passive_sysctl, "I",
		    "thermal constant 2 for passive cooling");
    SYSCTL_ADD_PROC(&sc->tz_sysctl_ctx, SYSCTL_CHILDREN(sc->tz_sysctl_tree),
		    OID_AUTO, "_TSP", CTLTYPE_INT | CTLFLAG_RW,
		    sc, offsetof(struct acpi_tz_softc, tz_zone.tsp),
		    acpi_tz_passive_sysctl, "I",
		    "thermal sampling period for passive cooling");

    /*
     * Register our power profile event handler.
     */
    sc->tz_event = EVENTHANDLER_REGISTER(power_profile_change,
	acpi_tz_power_profile, sc, 0);

    /*
     * Flag the event handler for a manual invocation by our timeout.
     * We defer it like this so that the rest of the subsystem has time
     * to come up.  Don't bother evaluating/printing the temperature at
     * this point; on many systems it'll be bogus until the EC is running.
     */
    sc->tz_flags |= TZ_FLAG_GETPROFILE;

    return_VALUE (0);
}
예제 #25
0
파일: twa_freebsd.c 프로젝트: MarginC/kame
/*
 * Function name:	twa_attach
 * Description:		Allocates pci resources; updates sc; adds a node to the
 *			sysctl tree to expose the driver version; makes calls
 *			to initialize ctlr, and to attach to CAM.
 *
 * Input:		dev	-- bus device corresponding to the ctlr
 * Output:		None
 * Return value:	0	-- success
 *			non-zero-- failure
 */
static int
twa_attach(device_t dev)
{
	struct twa_softc	*sc = device_get_softc(dev);
	u_int32_t		command;
	int			res_id;
	int			error;

	twa_dbg_dprint_enter(3, sc);

	/* Initialize the softc structure. */
	sc->twa_bus_dev = dev;

	sysctl_ctx_init(&sc->twa_sysctl_ctx);
	sc->twa_sysctl_tree = SYSCTL_ADD_NODE(&sc->twa_sysctl_ctx,
				SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
				device_get_nameunit(dev), CTLFLAG_RD, 0, "");
	if (sc->twa_sysctl_tree == NULL) {
		twa_printf(sc, "Cannot add sysctl tree node.\n");
		return(ENXIO);
	}
	SYSCTL_ADD_STRING(&sc->twa_sysctl_ctx, SYSCTL_CHILDREN(sc->twa_sysctl_tree),
				OID_AUTO, "driver_version", CTLFLAG_RD,
				TWA_DRIVER_VERSION_STRING, 0, "TWA driver version");

	/* Make sure we are going to be able to talk to this board. */
	command = pci_read_config(dev, PCIR_COMMAND, 2);
	if ((command & PCIM_CMD_PORTEN) == 0) {
		twa_printf(sc, "Register window not available.\n");
		return(ENXIO);
	}
	
	/* Force the busmaster enable bit on, in case the BIOS forgot. */
	command |= PCIM_CMD_BUSMASTEREN;
	pci_write_config(dev, PCIR_COMMAND, command, 2);

	/* Allocate the PCI register window. */
	res_id = TWA_IO_CONFIG_REG;
	if ((sc->twa_io_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &res_id,
					0, ~0, 1, RF_ACTIVE)) == NULL) {
		twa_printf(sc, "can't allocate register window.\n");
		twa_free(sc);
		return(ENXIO);
	}
	sc->twa_bus_tag = rman_get_bustag(sc->twa_io_res);
	sc->twa_bus_handle = rman_get_bushandle(sc->twa_io_res);

	/* Allocate and connect our interrupt. */
	res_id = 0;
	if ((sc->twa_irq_res = bus_alloc_resource(sc->twa_bus_dev, SYS_RES_IRQ,
					&res_id, 0, ~0, 1,
					RF_SHAREABLE | RF_ACTIVE)) == NULL) {
		twa_printf(sc, "Can't allocate interrupt.\n");
		twa_free(sc);
		return(ENXIO);
	}
	if (bus_setup_intr(sc->twa_bus_dev, sc->twa_irq_res, INTR_TYPE_CAM,
				twa_pci_intr, sc, &sc->twa_intr_handle)) {
		twa_printf(sc, "Can't set up interrupt.\n");
		twa_free(sc);
		return(ENXIO);
	}

	/* Initialize the driver for this controller. */
	if ((error = twa_setup(sc))) {
		twa_free(sc);
		return(error);
	}

	/* Print some information about the controller and configuration. */
	twa_describe_controller(sc);

	/* Create the control device. */
	sc->twa_ctrl_dev = make_dev(&twa_cdevsw, device_get_unit(sc->twa_bus_dev),
					UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR,
					"twa%d", device_get_unit(sc->twa_bus_dev));
	sc->twa_ctrl_dev->si_drv1 = sc;

	/*
	 * Schedule ourselves to bring the controller up once interrupts are
	 * available.  This isn't strictly necessary, since we disable
	 * interrupts while probing the controller, but it is more in keeping
	 * with common practice for other disk devices.
	 */
	sc->twa_ich.ich_func = twa_intrhook;
	sc->twa_ich.ich_arg = sc;
	if (config_intrhook_establish(&sc->twa_ich) != 0) {
		twa_printf(sc, "Can't establish configuration hook.\n");
		twa_free(sc);
		return(ENXIO);
	}

	if ((error = twa_cam_setup(sc))) {
		twa_free(sc);
		return(error);
	}
	return(0);
}
static int
acpi_battery_init(void)
{
    struct acpi_softc	*sc;
    device_t		 dev;
    int	 		 error;

    ACPI_SERIAL_ASSERT(battery);

    error = ENXIO;
    dev = devclass_get_device(devclass_find("acpi"), 0);
    if (dev == NULL)
	goto out;
    sc = device_get_softc(dev);

    error = acpi_register_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl,
	NULL);
    if (error != 0)
	goto out;
    error = acpi_register_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl,
	NULL);
    if (error != 0)
	goto out;
    error = acpi_register_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl, NULL);
    if (error != 0)
	goto out;
    error = acpi_register_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl, NULL);
    if (error != 0)
	goto out;

    sysctl_ctx_init(&acpi_battery_sysctl_ctx);
    acpi_battery_sysctl_tree = SYSCTL_ADD_NODE(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO, "battery", CTLFLAG_RD,
	0, "battery status and info");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "life", CTLTYPE_INT | CTLFLAG_RD,
	&acpi_battery_battinfo.cap, 0, acpi_battery_sysctl, "I",
	"percent capacity remaining");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "time", CTLTYPE_INT | CTLFLAG_RD,
	&acpi_battery_battinfo.min, 0, acpi_battery_sysctl, "I",
	"remaining time in minutes");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "state", CTLTYPE_INT | CTLFLAG_RD,
	&acpi_battery_battinfo.state, 0, acpi_battery_sysctl, "I",
	"current status flags");
    SYSCTL_ADD_PROC(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "units", CTLTYPE_INT | CTLFLAG_RD,
	NULL, 0, acpi_battery_units_sysctl, "I", "number of batteries");
    SYSCTL_ADD_INT(&acpi_battery_sysctl_ctx,
	SYSCTL_CHILDREN(acpi_battery_sysctl_tree),
	OID_AUTO, "info_expire", CTLFLAG_RW,
	&acpi_battery_info_expire, 0,
	"time in seconds until info is refreshed");

    acpi_batteries_initted = TRUE;

out:
    if (error != 0) {
	acpi_deregister_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl);
	acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl);
	acpi_deregister_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl);
	acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl);
    }
    return (error);
}
예제 #27
0
static void
ue_attach_post_task(struct usb_proc_msg *_task)
{
	struct usb_ether_cfg_task *task =
	    (struct usb_ether_cfg_task *)_task;
	struct usb_ether *ue = task->ue;
	struct ifnet *ifp;
	int error;
	char num[14];			/* sufficient for 32 bits */

	/* first call driver's post attach routine */
	ue->ue_methods->ue_attach_post(ue);

	UE_UNLOCK(ue);

	ue->ue_unit = alloc_unr(ueunit);
	usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0);
	sysctl_ctx_init(&ue->ue_sysctl_ctx);

	error = 0;
	CURVNET_SET_QUIET(vnet0);
	ifp = if_alloc(IFT_ETHER);
	if (ifp == NULL) {
		device_printf(ue->ue_dev, "could not allocate ifnet\n");
		goto fail;
	}

	ifp->if_softc = ue;
	if_initname(ifp, "ue", ue->ue_unit);
	if (ue->ue_methods->ue_attach_post_sub != NULL) {
		ue->ue_ifp = ifp;
		error = ue->ue_methods->ue_attach_post_sub(ue);
	} else {
		ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
		if (ue->ue_methods->ue_ioctl != NULL)
			ifp->if_ioctl = ue->ue_methods->ue_ioctl;
		else
			ifp->if_ioctl = uether_ioctl;
		ifp->if_start = ue_start;
		ifp->if_init = ue_init;
		IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
		ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
		IFQ_SET_READY(&ifp->if_snd);
		ue->ue_ifp = ifp;

		if (ue->ue_methods->ue_mii_upd != NULL &&
		    ue->ue_methods->ue_mii_sts != NULL) {
			/* device_xxx() depends on this */
			mtx_lock(&Giant);
			error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
			    ue_ifmedia_upd, ue->ue_methods->ue_mii_sts,
			    BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0);
			mtx_unlock(&Giant);
		}
	}

	if (error) {
		device_printf(ue->ue_dev, "attaching PHYs failed\n");
		goto fail;
	}

	if_printf(ifp, "<USB Ethernet> on %s\n", device_get_nameunit(ue->ue_dev));
	ether_ifattach(ifp, ue->ue_eaddr);
	/* Tell upper layer we support VLAN oversized frames. */
	if (ifp->if_capabilities & IFCAP_VLAN_MTU)
		ifp->if_hdrlen = sizeof(struct ether_vlan_header);

	CURVNET_RESTORE();

	snprintf(num, sizeof(num), "%u", ue->ue_unit);
	ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx,
	    &SYSCTL_NODE_CHILDREN(_net, ue),
	    OID_AUTO, num, CTLFLAG_RD, NULL, "");
	SYSCTL_ADD_PROC(&ue->ue_sysctl_ctx,
	    SYSCTL_CHILDREN(ue->ue_sysctl_oid), OID_AUTO,
	    "%parent", CTLTYPE_STRING | CTLFLAG_RD, ue, 0,
	    ue_sysctl_parent, "A", "parent device");

	UE_LOCK(ue);
	return;

fail:
	CURVNET_RESTORE();
	free_unr(ueunit, ue->ue_unit);
	if (ue->ue_ifp != NULL) {
		if_free(ue->ue_ifp);
		ue->ue_ifp = NULL;
	}
	UE_LOCK(ue);
	return;
}
예제 #28
0
static int
bcm2835_cpufreq_attach(device_t dev)
{
	struct bcm2835_cpufreq_softc *sc;
	struct sysctl_oid *oid;

	/* set self dev */
	sc = device_get_softc(dev);
	sc->dev = dev;

	/* initial values */
	sc->arm_max_freq = -1;
	sc->arm_min_freq = -1;
	sc->core_max_freq = -1;
	sc->core_min_freq = -1;
	sc->sdram_max_freq = -1;
	sc->sdram_min_freq = -1;
	sc->max_voltage_core = 0;
	sc->min_voltage_core = 0;

	/* setup sysctl at first device */
	if (device_get_unit(dev) == 0) {
		sysctl_ctx_init(&bcm2835_sysctl_ctx);
		/* create node for hw.cpufreq */
		oid = SYSCTL_ADD_NODE(&bcm2835_sysctl_ctx,
		    SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "cpufreq",
		    CTLFLAG_RD, NULL, "");

		/* Frequency (Hz) */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "arm_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_arm_freq, "IU",
		    "ARM frequency (Hz)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "core_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_core_freq, "IU",
		    "Core frequency (Hz)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "sdram_freq", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_sdram_freq, "IU",
		    "SDRAM frequency (Hz)");

		/* Turbo state */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "turbo", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_turbo, "IU",
		    "Disables dynamic clocking");

		/* Voltage (offset from 1.2V in units of 0.025V) */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_core", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
		    sysctl_bcm2835_cpufreq_voltage_core, "I",
		    "ARM/GPU core voltage"
		    "(offset from 1.2V in units of 0.025V)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram", CTLTYPE_INT | CTLFLAG_WR, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram, "I",
		    "SDRAM voltage (offset from 1.2V in units of 0.025V)");

		/* Voltage individual SDRAM */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram_c", CTLTYPE_INT | CTLFLAG_RW, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram_c, "I",
		    "SDRAM controller voltage"
		    "(offset from 1.2V in units of 0.025V)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram_i", CTLTYPE_INT | CTLFLAG_RW, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram_i, "I",
		    "SDRAM I/O voltage (offset from 1.2V in units of 0.025V)");
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "voltage_sdram_p", CTLTYPE_INT | CTLFLAG_RW, sc,
		    0, sysctl_bcm2835_cpufreq_voltage_sdram_p, "I",
		    "SDRAM phy voltage (offset from 1.2V in units of 0.025V)");

		/* Temperature */
		SYSCTL_ADD_PROC(&bcm2835_sysctl_ctx, SYSCTL_CHILDREN(oid),
		    OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
		    sysctl_bcm2835_cpufreq_temperature, "I",
		    "SoC temperature (thousandths of a degree C)");
	}

	/* ARM->VC lock */
	sema_init(&vc_sema, 1, "vcsema");

	/* register callback for using mbox when interrupts are enabled */
	sc->init_hook.ich_func = bcm2835_cpufreq_init;
	sc->init_hook.ich_arg = sc;

	if (config_intrhook_establish(&sc->init_hook) != 0) {
		device_printf(dev, "config_intrhook_establish failed\n");
		return (ENOMEM);
	}

	/* this device is controlled by cpufreq(4) */
	cpufreq_register(dev);

	return (0);
}
예제 #29
0
/*
 * Initialize per-cpu polling(4) context.  Called from kern_clock.c:
 */
void
init_device_poll_pcpu(int cpuid)
{
	struct pollctx *pctx;
	char cpuid_str[3];

	if (cpuid >= POLLCTX_MAX)
		return;

	if ((CPUMASK(cpuid) & poll_cpumask0) == 0)
		return;

	if (poll_burst_max < MIN_POLL_BURST_MAX)
		poll_burst_max = MIN_POLL_BURST_MAX;
	else if (poll_burst_max > MAX_POLL_BURST_MAX)
		poll_burst_max = MAX_POLL_BURST_MAX;

	if (poll_each_burst > poll_burst_max)
		poll_each_burst = poll_burst_max;

	poll_cpumask |= CPUMASK(cpuid);

	pctx = kmalloc(sizeof(*pctx), M_DEVBUF, M_WAITOK | M_ZERO);

	pctx->poll_each_burst = poll_each_burst;
	pctx->poll_burst_max = poll_burst_max;
	pctx->user_frac = 50;
	pctx->reg_frac = 20;
	pctx->polling_enabled = polling_enabled;
	pctx->pollhz = pollhz;
	pctx->poll_cpuid = cpuid;
	poll_reset_state(pctx);

	netmsg_init(&pctx->poll_netmsg, NULL, &netisr_adone_rport,
		    0, netisr_poll);
#ifdef INVARIANTS
	pctx->poll_netmsg.lmsg.u.ms_resultp = pctx;
#endif

	netmsg_init(&pctx->poll_more_netmsg, NULL, &netisr_adone_rport,
		    0, netisr_pollmore);
#ifdef INVARIANTS
	pctx->poll_more_netmsg.lmsg.u.ms_resultp = pctx;
#endif

	KASSERT(cpuid < POLLCTX_MAX, ("cpu id must < %d", cpuid));
	poll_context[cpuid] = pctx;

	if (poll_defcpu < 0) {
		poll_defcpu = cpuid;

		/*
		 * Initialize global sysctl nodes, for compat
		 */
		poll_add_sysctl(NULL, SYSCTL_STATIC_CHILDREN(_kern_polling),
				pctx);
	}

	/*
	 * Initialize per-cpu sysctl nodes
	 */
	ksnprintf(cpuid_str, sizeof(cpuid_str), "%d", pctx->poll_cpuid);

	sysctl_ctx_init(&pctx->poll_sysctl_ctx);
	pctx->poll_sysctl_tree = SYSCTL_ADD_NODE(&pctx->poll_sysctl_ctx,
				 SYSCTL_STATIC_CHILDREN(_kern_polling),
				 OID_AUTO, cpuid_str, CTLFLAG_RD, 0, "");
	poll_add_sysctl(&pctx->poll_sysctl_ctx,
			SYSCTL_CHILDREN(pctx->poll_sysctl_tree), pctx);

	/*
	 * Initialize systimer
	 */
	systimer_init_periodic_nq(&pctx->pollclock, pollclock, pctx, 1);
}
예제 #30
0
static int
tws_attach(device_t dev)
{
    struct tws_softc *sc = device_get_softc(dev);
    u_int32_t bar;
    int error=0,i;

    /* no tracing yet */
    /* Look up our softc and initialize its fields. */
    sc->tws_dev = dev;
    sc->device_id = pci_get_device(dev);
    sc->subvendor_id = pci_get_subvendor(dev);
    sc->subdevice_id = pci_get_subdevice(dev);

    /* Intialize mutexes */
    mtx_init( &sc->q_lock, "tws_q_lock", NULL, MTX_DEF);
    mtx_init( &sc->sim_lock,  "tws_sim_lock", NULL, MTX_DEF);
    mtx_init( &sc->gen_lock,  "tws_gen_lock", NULL, MTX_DEF);
    mtx_init( &sc->io_lock,  "tws_io_lock", NULL, MTX_DEF | MTX_RECURSE);

    if ( tws_init_trace_q(sc) == FAILURE )
        printf("trace init failure\n");
    /* send init event */
    mtx_lock(&sc->gen_lock);
    tws_send_event(sc, TWS_INIT_START);
    mtx_unlock(&sc->gen_lock);


#if _BYTE_ORDER == _BIG_ENDIAN
    TWS_TRACE(sc, "BIG endian", 0, 0);
#endif
    /* sysctl context setup */
    sysctl_ctx_init(&sc->tws_clist);
    sc->tws_oidp = SYSCTL_ADD_NODE(&sc->tws_clist,
                                   SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
                                   device_get_nameunit(dev), 
                                   CTLFLAG_RD, 0, "");
    if ( sc->tws_oidp == NULL ) {
        tws_log(sc, SYSCTL_TREE_NODE_ADD);
        goto attach_fail_1;
    }
    SYSCTL_ADD_STRING(&sc->tws_clist, SYSCTL_CHILDREN(sc->tws_oidp),
                      OID_AUTO, "driver_version", CTLFLAG_RD,
                      TWS_DRIVER_VERSION_STRING, 0, "TWS driver version");

    pci_enable_busmaster(dev);

    bar = pci_read_config(dev, TWS_PCI_BAR0, 4);
    TWS_TRACE_DEBUG(sc, "bar0 ", bar, 0);
    bar = pci_read_config(dev, TWS_PCI_BAR1, 4);
    bar = bar & ~TWS_BIT2;
    TWS_TRACE_DEBUG(sc, "bar1 ", bar, 0);
 
    /* MFA base address is BAR2 register used for 
     * push mode. Firmware will evatualy move to 
     * pull mode during witch this needs to change
     */ 
#ifndef TWS_PULL_MODE_ENABLE
    sc->mfa_base = (u_int64_t)pci_read_config(dev, TWS_PCI_BAR2, 4);
    sc->mfa_base = sc->mfa_base & ~TWS_BIT2;
    TWS_TRACE_DEBUG(sc, "bar2 ", sc->mfa_base, 0);
#endif

    /* allocate MMIO register space */ 
    sc->reg_res_id = TWS_PCI_BAR1; /* BAR1 offset */
    if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
                                &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
                                == NULL) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_1;
    }
    sc->bus_tag = rman_get_bustag(sc->reg_res);
    sc->bus_handle = rman_get_bushandle(sc->reg_res);

#ifndef TWS_PULL_MODE_ENABLE
    /* Allocate bus space for inbound mfa */ 
    sc->mfa_res_id = TWS_PCI_BAR2; /* BAR2 offset */
    if ((sc->mfa_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
                          &(sc->mfa_res_id), 0, ~0, 0x100000, RF_ACTIVE))
                                == NULL) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_2;
    }
    sc->bus_mfa_tag = rman_get_bustag(sc->mfa_res);
    sc->bus_mfa_handle = rman_get_bushandle(sc->mfa_res);
#endif

    /* Allocate and register our interrupt. */
    sc->intr_type = TWS_INTx; /* default */

    if ( tws_enable_msi )
        sc->intr_type = TWS_MSI;
    if ( tws_setup_irq(sc) == FAILURE ) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_3;
    }

    /*
     * Create a /dev entry for this device.  The kernel will assign us
     * a major number automatically.  We use the unit number of this
     * device as the minor number and name the character device
     * "tws<unit>".
     */
    sc->tws_cdev = make_dev(&tws_cdevsw, device_get_unit(dev),
        UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "tws%u", 
        device_get_unit(dev));
    sc->tws_cdev->si_drv1 = sc;

    if ( tws_init(sc) == FAILURE ) {
        tws_log(sc, TWS_INIT_FAILURE);
        goto attach_fail_4;
    }
    if ( tws_init_ctlr(sc) == FAILURE ) {
        tws_log(sc, TWS_CTLR_INIT_FAILURE);
        goto attach_fail_4;
    }
    if ((error = tws_cam_attach(sc))) {
        tws_log(sc, TWS_CAM_ATTACH);
        goto attach_fail_4;
    }
    /* send init complete event */
    mtx_lock(&sc->gen_lock);
    tws_send_event(sc, TWS_INIT_COMPLETE);
    mtx_unlock(&sc->gen_lock);
        
    TWS_TRACE_DEBUG(sc, "attached successfully", 0, sc->device_id);
    return(0);

attach_fail_4:
    tws_teardown_intr(sc);
    destroy_dev(sc->tws_cdev);
attach_fail_3:
    for(i=0;i<sc->irqs;i++) {
        if ( sc->irq_res[i] ){
            if (bus_release_resource(sc->tws_dev,
                 SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
                TWS_TRACE(sc, "bus irq res", 0, 0);
        }
    }
#ifndef TWS_PULL_MODE_ENABLE
attach_fail_2: 
#endif
    if ( sc->mfa_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res))
            TWS_TRACE(sc, "bus release ", 0, sc->mfa_res_id);
    }
    if ( sc->reg_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))
            TWS_TRACE(sc, "bus release2 ", 0, sc->reg_res_id);
    }
attach_fail_1:
    mtx_destroy(&sc->q_lock);
    mtx_destroy(&sc->sim_lock);
    mtx_destroy(&sc->gen_lock);
    mtx_destroy(&sc->io_lock);
    sysctl_ctx_free(&sc->tws_clist);
    return (ENXIO);
}