Exemple #1
0
static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
{
    struct device *dev = &drive->gendev;
    int ret = 1;
    int err;

    device_release_driver(dev);
    /* FIXME: device can still be in use by previous driver */
    strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
    err = device_attach(dev);
    if (err < 0)
        printk(KERN_WARNING "IDE: %s: device_attach error: %d\n",
               __func__, err);
    drive->driver_req[0] = 0;
    if (dev->driver == NULL) {
        err = device_attach(dev);
        if (err < 0)
            printk(KERN_WARNING
                   "IDE: %s: device_attach(2) error: %d\n",
                   __func__, err);
    }
    if (dev->driver && !strcmp(dev->driver->name, driver))
        ret = 0;

    return ret;
}
Exemple #2
0
static void
vtpci_probe_and_attach_child(struct vtpci_softc *sc)
{
	device_t dev, child;

	dev = sc->vtpci_dev;
	child = sc->vtpci_child_dev;

	if (child == NULL)
		return;

	if (device_get_state(child) != DS_NOTPRESENT)
		return;

	if (device_probe(child) != 0)
		return;

	vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER);
	if (device_attach(child) != 0) {
		vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_FAILED);
		vtpci_reset(sc);
		vtpci_release_child_resources(sc);
		/* Reset status for future attempt. */
		vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_ACK);
	} else {
		vtpci_set_status(dev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
		VIRTIO_ATTACH_COMPLETED(child);
	}
}
Exemple #3
0
/**
 * Per network device initialization
 *
 * @param dev    Device to initialize
 * @return Zero on success
 */
int cvm_oct_common_init(struct ifnet *ifp)
{
	uint8_t mac[6];
	cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;

	if (cvm_assign_mac_address(NULL, mac) != 0)
		return ENXIO;

	ifp->if_mtu = ETHERMTU;

	cvm_oct_mdio_setup_device(ifp);

	cvm_oct_common_set_mac_address(ifp, mac);
	cvm_oct_common_change_mtu(ifp, ifp->if_mtu);

	/*
	 * Do any last-minute board-specific initialization.
	 */
	switch (cvmx_sysinfo_get()->board_type) {
#if defined(OCTEON_VENDOR_LANNER)
	case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
	case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
		if (priv->phy_id == 16)
			cvm_oct_mv88e61xx_setup_device(ifp);
		break;
#endif
	default:
		break;
	}

	device_attach(priv->dev);

	return 0;
}
Exemple #4
0
static ssize_t rebind_store(struct device_driver *dev, const char *buf,
				 size_t count)
{
	int ret;
	int len;
	struct bus_id_priv *bid;

	/* buf length should be less that BUSID_SIZE */
	len = strnlen(buf, BUSID_SIZE);

	if (!(len < BUSID_SIZE))
		return -EINVAL;

	bid = get_busid_priv(buf);
	if (!bid)
		return -ENODEV;

	ret = device_attach(&bid->udev->dev);
	if (ret < 0) {
		dev_err(&bid->udev->dev, "rebind failed\n");
		return ret;
	}

	return count;
}
Exemple #5
0
/**
 *	bus_attach_device - add device to bus
 *	@dev:	device tried to attach to a driver
 *
 *	- Try to attach to driver.
 */
void bus_attach_device(struct device * dev)
{
	struct bus_type * bus = dev->bus;

	if (bus) {
		device_attach(dev);
		klist_add_tail(&dev->knode_bus, &bus->klist_devices);
	}
}
static int umc_bus_rescan_helper(struct device *dev, void *data)
{
	int ret = 0;

	if (!dev->driver)
		ret = device_attach(dev);

	return ret;
}
Exemple #7
0
static void gameport_find_driver(struct gameport *gameport)
{
    int error;

    error = device_attach(&gameport->dev);
    if (error < 0)
        printk(KERN_WARNING
            "gameport: device_attach() failed for %s (%s), error: %d\n",
            gameport->phys, gameport->name, error);
}
static void serio_find_driver(struct serio *serio)
{
    int error;

    error = device_attach(&serio->dev);
    if (error < 0)
        dev_warn(&serio->dev,
                 "device_attach() failed for %s (%s), error: %d\n",
                 serio->phys, serio->name, error);
}
Exemple #9
0
/**
 * bus_probe_device - probe drivers for a new device
 * @dev: device to probe
 *
 * - Automatically probe for a driver if the bus allows it.
 */
void bus_probe_device(struct device *dev)
{
	struct bus_type *bus = dev->bus;
	int ret;

	if (bus && bus->p->drivers_autoprobe) {
		ret = device_attach(dev);
		WARN_ON(ret < 0);
	}
}
Exemple #10
0
static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
{
	struct device *dev = &drive->gendev;
	int ret = 1;

	down_write(&dev->bus->subsys.rwsem);
	device_release_driver(dev);
	/* FIXME: device can still be in use by previous driver */
	strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
	device_attach(dev);
	drive->driver_req[0] = 0;
	if (dev->driver == NULL)
		device_attach(dev);
	if (dev->driver && !strcmp(dev->driver->name, driver))
		ret = 0;
	up_write(&dev->bus->subsys.rwsem);

	return ret;
}
Exemple #11
0
static void serio_find_driver(struct serio *serio)
{
	int error;

	error = device_attach(&serio->dev);
	if (error < 0)
		printk(KERN_WARNING
			"serio: device_attach() failed for %s (%s), error: %d\n",
			serio->phys, serio->name, error);
}
static void gameport_find_driver(struct gameport *gameport)
{
	int error;

	error = device_attach(&gameport->dev);
	if (error < 0)
		dev_warn(&gameport->dev,
			 "device_attach() failed for %s (%s), error: %d\n",
			 gameport->phys, gameport->name, error);
}
Exemple #13
0
/* Helper for bus_rescan_devices's iter */
static int bus_rescan_devices_helper(struct device *dev, void *data)
{
	if (!dev->driver) {
		if (dev->parent)	/* Needed for USB */
			down(&dev->parent->sem);
		device_attach(dev);
		if (dev->parent)
			up(&dev->parent->sem);
	}
	return 0;
}
Exemple #14
0
/**
 * bus_attach_device - add device to bus
 * @dev: device tried to attach to a driver
 *
 * - Add device to bus's list of devices.
 * - Try to attach to driver.
 */
void bus_attach_device(struct device *dev)
{
	struct bus_type *bus = dev->bus;
	int ret = 0;

	if (bus) {
		if (bus->p->drivers_autoprobe)
			ret = device_attach(dev);
		WARN_ON(ret < 0);
		if (ret >= 0)
			klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
	}
}
Exemple #15
0
static int __must_check bus_rescan_devices_helper(struct device *dev,
						  void *data)
{
	int ret = 0;

	if (!dev->driver) {
		if (dev->parent)	
			down(&dev->parent->sem);
		ret = device_attach(dev);
		if (dev->parent)
			up(&dev->parent->sem);
	}
	return ret < 0 ? ret : 0;
}
Exemple #16
0
/* Helper for bus_rescan_devices's iter */
static int __must_check bus_rescan_devices_helper(struct device *dev,
						  void *data)
{
	int ret = 0;

	if (!dev->driver) {
		if (dev->parent)	/* Needed for USB */
			device_lock(dev->parent);
		ret = device_attach(dev);
		if (dev->parent)
			device_unlock(dev->parent);
	}
	return ret < 0 ? ret : 0;
}
static int umc_bus_post_reset_helper(struct device *dev, void *data)
{
	int ret = 0;

	if (dev->driver) {
		struct umc_dev *umc = to_umc_dev(dev);
		struct umc_driver *umc_drv = to_umc_driver(dev->driver);

		if (umc_drv->post_reset)
			ret = umc_drv->post_reset(umc);
	} else
		ret = device_attach(dev);

	return ret;
}
static int __mcb_bus_add_devices(struct device *dev, void *data)
{
    struct mcb_device *mdev = to_mcb_device(dev);
    int retval;

    if (mdev->is_added)
        return 0;

    retval = device_attach(dev);
    if (retval < 0)
        dev_err(dev, "Error adding device (%d)\n", retval);

    mdev->is_added = true;

    return 0;
}
Exemple #19
0
/**
 *	bus_attach_device - add device to bus
 *	@dev:	device tried to attach to a driver
 *
 *	- Add device to bus's list of devices.
 *	- Try to attach to driver.
 */
int bus_attach_device(struct device * dev)
{
	struct bus_type *bus = dev->bus;
	int ret = 0;

	if (bus) {
		dev->is_registered = 1;
		ret = device_attach(dev);
		if (ret >= 0) {
			klist_add_tail(&dev->knode_bus, &bus->klist_devices);
			ret = 0;
		} else
			dev->is_registered = 0;
	}
	return ret;
}
Exemple #20
0
/**
 *	bus_add_device - add device to bus
 *	@dev:	device being added
 *
 *	- Add the device to its bus's list of devices.
 *	- Try to attach to driver.
 *	- Create link to device's physical location.
 */
int bus_add_device(struct device * dev)
{
	struct bus_type * bus = get_bus(dev->bus);
	int error = 0;

	if (bus) {
		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
		device_attach(dev);
		klist_add_tail(&dev->knode_bus, &bus->klist_devices);
		error = device_add_attrs(bus, dev);
		if (!error) {
			sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
			sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
		}
	}
	return error;
}
Exemple #21
0
/**
 * Per network device initialization
 *
 * @param dev    Device to initialize
 * @return Zero on success
 */
int cvm_oct_common_init(struct ifnet *ifp)
{
	static int count;
	char mac[6] = {
		octeon_bootinfo->mac_addr_base[0],
		octeon_bootinfo->mac_addr_base[1],
		octeon_bootinfo->mac_addr_base[2],
		octeon_bootinfo->mac_addr_base[3],
		octeon_bootinfo->mac_addr_base[4],
		octeon_bootinfo->mac_addr_base[5] + count};
	cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;

	/* Force the interface to use the POW send if always_use_pow was
	   specified or it is in the pow send list */
	if ((pow_send_group != -1) && (always_use_pow || strstr(pow_send_list, if_name(ifp))))
		priv->queue = -1;

	ifp->if_mtu = ETHERMTU;

	count++;

#if 0
	ifp->get_stats          = cvm_oct_common_get_stats;
#ifdef CONFIG_NET_POLL_CONTROLLER
	ifp->poll_controller    = cvm_oct_poll_controller;
#endif
#endif

	cvm_oct_mdio_setup_device(ifp);

	cvm_oct_common_set_mac_address(ifp, mac);
	cvm_oct_common_change_mtu(ifp, ifp->if_mtu);

#if 0
	/* Zero out stats for port so we won't mistakenly show counters from the
	   bootloader */
	memset(ifp->get_stats(ifp), 0, sizeof(struct ifnet_stats));
#endif

	device_attach(priv->dev);

	return 0;
}
Exemple #22
0
std::vector<std::wstring> get_device_list()
{
	std::vector<std::wstring> devices;

	try
	{		
		blue_initialize();
		
		auto blue = create_blue();

		for(int n = 1; BLUE_PASS(blue->device_attach(n, FALSE)); ++n)
		{				
			devices.push_back(std::wstring(get_card_desc(*blue)) + L" [" + boost::lexical_cast<std::wstring>(n) + L"]");
			blue->device_detach();		
		}
	}
	catch(...){}

	return devices;
}
Exemple #23
0
/**
 * bus_probe_device - probe drivers for a new device
 * @dev: device to probe
 *
 * - Automatically probe for a driver if the bus allows it.
 */
void bus_probe_device(struct device *dev)
{
    struct bus_type *bus = dev->bus;
    struct subsys_interface *sif;
    int ret;

    if (!bus)
        return;

    if (bus->p->drivers_autoprobe) {
        ret = device_attach(dev);
        WARN_ON(ret < 0);
    }

    mutex_lock(&bus->p->mutex);
    list_for_each_entry(sif, &bus->p->interfaces, node)
    if (sif->add_dev)
        sif->add_dev(dev, sif);
    mutex_unlock(&bus->p->mutex);
}
/**
 * Per network device initialization
 *
 * @param dev    Device to initialize
 * @return Zero on success
 */
int cvm_oct_common_init(struct ifnet *ifp)
{
	char mac[6] = {
		octeon_bootinfo->mac_addr_base[0],
		octeon_bootinfo->mac_addr_base[1],
		octeon_bootinfo->mac_addr_base[2],
		octeon_bootinfo->mac_addr_base[3],
		octeon_bootinfo->mac_addr_base[4],
		octeon_bootinfo->mac_addr_base[5] };
	cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc;

	mac[5] += cvm_oct_mac_addr_offset++;

	ifp->if_mtu = ETHERMTU;

	cvm_oct_mdio_setup_device(ifp);

	cvm_oct_common_set_mac_address(ifp, mac);
	cvm_oct_common_change_mtu(ifp, ifp->if_mtu);

	/*
	 * Do any last-minute board-specific initialization.
	 */
	switch (cvmx_sysinfo_get()->board_type) {
#if defined(OCTEON_VENDOR_LANNER)
	case CVMX_BOARD_TYPE_CUST_LANNER_MR320:
	case CVMX_BOARD_TYPE_CUST_LANNER_MR321X:
		if (priv->phy_id == 16)
			cvm_oct_mv88e61xx_setup_device(ifp);
		break;
#endif
	default:
		break;
	}

	device_attach(priv->dev);

	return 0;
}
Exemple #25
0
/**
 * check_plugged_state_change - Check change in an MC object's plugged state
 *
 * @mc_dev: pointer to the fsl-mc device for a given MC object
 * @obj_desc: pointer to the MC object's descriptor in the MC
 *
 * If the plugged state has changed from unplugged to plugged, the fsl-mc
 * device is bound to the corresponding device driver.
 * If the plugged state has changed from plugged to unplugged, the fsl-mc
 * device is unbound from the corresponding device driver.
 */
static void check_plugged_state_change(struct fsl_mc_device *mc_dev,
				       struct dprc_obj_desc *obj_desc)
{
	int error;
	u32 plugged_flag_at_mc =
			obj_desc->state & DPRC_OBJ_STATE_PLUGGED;

	if (plugged_flag_at_mc !=
	    (mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED)) {
		if (plugged_flag_at_mc) {
			mc_dev->obj_desc.state |= DPRC_OBJ_STATE_PLUGGED;
			error = device_attach(&mc_dev->dev);
			if (error < 0) {
				dev_err(&mc_dev->dev,
					"device_attach() failed: %d\n",
					error);
			}
		} else {
			mc_dev->obj_desc.state &= ~DPRC_OBJ_STATE_PLUGGED;
			device_release_driver(&mc_dev->dev);
		}
	}
}
Exemple #26
0
void bus_probe_device(struct device *dev)

#endif									
{


	struct bus_type *bus = dev->bus;
	int ret;
	


	if (bus && bus->p->drivers_autoprobe) {
		ret = device_attach(dev);
		WARN_ON(ret < 0);
	}

#ifdef CONFIG_MACH_LGE_MMC_REFRESH		
	if(ret == 0xbcbc)
		return ret;
	else return 0;
#endif									

	
}
static int acpi_processor_add(struct acpi_device *device,
					const struct acpi_device_id *id)
{
	struct acpi_processor *pr;
	struct device *dev;
	int result = 0;

	pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
	if (!pr)
		return -ENOMEM;

	if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
		result = -ENOMEM;
		goto err_free_pr;
	}

	pr->handle = device->handle;
	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
	device->driver_data = pr;

	result = acpi_processor_get_info(device);
	if (result) /* Processor is not physically present or unavailable */
		return 0;

#ifdef CONFIG_SMP
	if (pr->id >= setup_max_cpus && pr->id != 0)
		return 0;
#endif

	BUG_ON(pr->id >= nr_cpu_ids);

	/*
	 * Buggy BIOS check.
	 * ACPI id of processors can be reported wrongly by the BIOS.
	 * Don't trust it blindly
	 */
	if (per_cpu(processor_device_array, pr->id) != NULL &&
	    per_cpu(processor_device_array, pr->id) != device) {
		dev_warn(&device->dev,
			"BIOS reported wrong ACPI id %d for the processor\n",
			pr->id);
		/* Give up, but do not abort the namespace scan. */
		goto err;
	}
	/*
	 * processor_device_array is not cleared on errors to allow buggy BIOS
	 * checks.
	 */
	per_cpu(processor_device_array, pr->id) = device;
	per_cpu(processors, pr->id) = pr;

	dev = get_cpu_device(pr->id);
	if (!dev) {
		result = -ENODEV;
		goto err;
	}

	result = acpi_bind_one(dev, pr->handle);
	if (result)
		goto err;

	pr->dev = dev;
	dev->offline = pr->flags.need_hotplug_init;

	/* Trigger the processor driver's .probe() if present. */
	if (device_attach(dev) >= 0)
		return 1;

	dev_err(dev, "Processor driver could not be attached\n");
	acpi_unbind_one(dev);

 err:
	free_cpumask_var(pr->throttling.shared_cpu_map);
	device->driver_data = NULL;
	per_cpu(processors, pr->id) = NULL;
 err_free_pr:
	kfree(pr);
	return result;
}
Exemple #28
0
static int nokia_modem_probe(struct device *dev)
{
	struct device_node *np;
	struct nokia_modem_device *modem;
	struct hsi_client *cl = to_hsi_client(dev);
	struct hsi_port *port = hsi_get_port(cl);
	int irq, pflags, err;
	struct hsi_board_info ssip;
	struct hsi_board_info cmtspeech;

	np = dev->of_node;
	if (!np) {
		dev_err(dev, "device tree node not found\n");
		return -ENXIO;
	}

	modem = devm_kzalloc(dev, sizeof(*modem), GFP_KERNEL);
	if (!modem) {
		dev_err(dev, "Could not allocate memory for nokia_modem_device\n");
		return -ENOMEM;
	}
	dev_set_drvdata(dev, modem);
	modem->device = dev;

	irq = irq_of_parse_and_map(np, 0);
	if (!irq) {
		dev_err(dev, "Invalid rst_ind interrupt (%d)\n", irq);
		return -EINVAL;
	}
	modem->nokia_modem_rst_ind_irq = irq;
	pflags = irq_get_trigger_type(irq);

	tasklet_init(&modem->nokia_modem_rst_ind_tasklet,
			do_nokia_modem_rst_ind_tasklet, (unsigned long)modem);
	err = devm_request_irq(dev, irq, nokia_modem_rst_ind_isr,
				pflags, "modem_rst_ind", modem);
	if (err < 0) {
		dev_err(dev, "Request rst_ind irq(%d) failed (flags %d)\n",
								irq, pflags);
		return err;
	}
	enable_irq_wake(irq);

	if(pm) {
		err = nokia_modem_gpio_probe(dev);
		if (err < 0) {
			dev_err(dev, "Could not probe GPIOs\n");
			goto error1;
		}
	}

	ssip.name = "ssi-protocol";
	ssip.tx_cfg = cl->tx_cfg;
	ssip.rx_cfg = cl->rx_cfg;
	ssip.platform_data = NULL;
	ssip.archdata = NULL;

	modem->ssi_protocol = hsi_new_client(port, &ssip);
	if (!modem->ssi_protocol) {
		dev_err(dev, "Could not register ssi-protocol device\n");
		err = -ENOMEM;
		goto error2;
	}

	err = device_attach(&modem->ssi_protocol->device);
	if (err == 0) {
		dev_dbg(dev, "Missing ssi-protocol driver\n");
		err = -EPROBE_DEFER;
		goto error3;
	} else if (err < 0) {
		dev_err(dev, "Could not load ssi-protocol driver (%d)\n", err);
		goto error3;
	}

	cmtspeech.name = "cmt-speech";
	cmtspeech.tx_cfg = cl->tx_cfg;
	cmtspeech.rx_cfg = cl->rx_cfg;
	cmtspeech.platform_data = NULL;
	cmtspeech.archdata = NULL;

	modem->cmt_speech = hsi_new_client(port, &cmtspeech);
	if (!modem->cmt_speech) {
		dev_err(dev, "Could not register cmt-speech device\n");
		err = -ENOMEM;
		goto error3;
	}

	err = device_attach(&modem->cmt_speech->device);
	if (err == 0) {
		dev_dbg(dev, "Missing cmt-speech driver\n");
		err = -EPROBE_DEFER;
		goto error4;
	} else if (err < 0) {
		dev_err(dev, "Could not load cmt-speech driver (%d)\n", err);
		goto error4;
	}

	dev_info(dev, "Registered Nokia HSI modem\n");

	return 0;

error4:
	hsi_remove_client(&modem->cmt_speech->device, NULL);
error3:
	hsi_remove_client(&modem->ssi_protocol->device, NULL);
error2:
	nokia_modem_gpio_unexport(dev);
error1:
	disable_irq_wake(modem->nokia_modem_rst_ind_irq);
	tasklet_kill(&modem->nokia_modem_rst_ind_tasklet);

	return err;
}
Exemple #29
0
int
scc_bfe_attach(device_t dev, u_int ipc)
{
	struct resource_list_entry *rle;
	struct scc_chan *ch;
	struct scc_class *cl;
	struct scc_mode *m;
	struct scc_softc *sc, *sc0;
	const char *sep;
	bus_space_handle_t bh;
	u_long base, size, start, sz;
	int c, error, mode, sysdev;

	/*
	 * The sc_class field defines the type of SCC we're going to work
	 * with and thus the size of the softc. Replace the generic softc
	 * with one that matches the SCC now that we're certain we handle
	 * the device.
	 */
	sc0 = device_get_softc(dev);
	cl = sc0->sc_class;
	if (cl->size > sizeof(*sc)) {
		sc = malloc(cl->size, M_SCC, M_WAITOK|M_ZERO);
		bcopy(sc0, sc, sizeof(*sc));
		device_set_softc(dev, sc);
	} else
		sc = sc0;

	size = abs(cl->cl_range) << sc->sc_bas.regshft;

	mtx_init(&sc->sc_hwmtx, "scc_hwmtx", NULL, MTX_SPIN);

	/*
	 * Re-allocate. We expect that the softc contains the information
	 * collected by scc_bfe_probe() intact.
	 */
	sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
	    0, ~0, cl->cl_channels * size, RF_ACTIVE);
	if (sc->sc_rres == NULL)
		return (ENXIO);
	sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
	sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);

	/*
	 * Allocate interrupt resources. There may be a different interrupt
	 * per channel. We allocate them all...
	 */
	sc->sc_chan = malloc(sizeof(struct scc_chan) * cl->cl_channels,
	    M_SCC, M_WAITOK | M_ZERO);
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		/*
		 * XXX temporary hack. If we have more than 1 interrupt
		 * per channel, allocate the first for the channel. At
		 * this time only the macio bus front-end has more than
		 * 1 interrupt per channel and we don't use the 2nd and
		 * 3rd, because we don't support DMA yet.
		 */
		ch->ch_irid = c * ipc;
		ch->ch_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
		    &ch->ch_irid, RF_ACTIVE | RF_SHAREABLE);
		if (ipc == 0)
			break;
	}

	/*
	 * Create the control structures for our children. Probe devices
	 * and query them to see if we can reset the hardware.
	 */
	sysdev = 0;
	base = rman_get_start(sc->sc_rres);
	sz = (size != 0) ? size : rman_get_size(sc->sc_rres);
	start = base + ((cl->cl_range < 0) ? size * (cl->cl_channels - 1) : 0);
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		resource_list_init(&ch->ch_rlist);
		ch->ch_nr = c + 1;

		if (!SCC_ENABLED(sc, ch))
			goto next;

		ch->ch_enabled = 1;
		resource_list_add(&ch->ch_rlist, sc->sc_rtype, 0, start,
		    start + sz - 1, sz);
		rle = resource_list_find(&ch->ch_rlist, sc->sc_rtype, 0);
		rle->res = &ch->ch_rres;
		bus_space_subregion(rman_get_bustag(sc->sc_rres),
		    rman_get_bushandle(sc->sc_rres), start - base, sz, &bh);
		rman_set_bushandle(rle->res, bh);
		rman_set_bustag(rle->res, rman_get_bustag(sc->sc_rres));

		resource_list_add(&ch->ch_rlist, SYS_RES_IRQ, 0, c, c, 1);
		rle = resource_list_find(&ch->ch_rlist, SYS_RES_IRQ, 0);
		rle->res = (ch->ch_ires != NULL) ? ch->ch_ires :
			    sc->sc_chan[0].ch_ires;

		for (mode = 0; mode < SCC_NMODES; mode++) {
			m = &ch->ch_mode[mode];
			m->m_chan = ch;
			m->m_mode = 1U << mode;
			if ((cl->cl_modes & m->m_mode) == 0 || ch->ch_sysdev)
				continue;
			m->m_dev = device_add_child(dev, NULL, -1);
			device_set_ivars(m->m_dev, (void *)m);
			error = device_probe_child(dev, m->m_dev);
			if (!error) {
				m->m_probed = 1;
				m->m_sysdev = SERDEV_SYSDEV(m->m_dev) ? 1 : 0;
				ch->ch_sysdev |= m->m_sysdev;
			}
		}

	 next:
		start += (cl->cl_range < 0) ? -size : size;
		sysdev |= ch->ch_sysdev;
	}

	/*
	 * Have the hardware driver initialize the hardware. Tell it
	 * whether or not a hardware reset should be performed.
	 */
	if (bootverbose) {
		device_printf(dev, "%sresetting hardware\n",
		    (sysdev) ? "not " : "");
	}
	error = SCC_ATTACH(sc, !sysdev);
	if (error)
		goto fail;

	/*
	 * Setup our interrupt handler. Make it FAST under the assumption
	 * that our children's are fast as well. We make it MPSAFE as soon
	 * as a child sets up a MPSAFE interrupt handler.
	 * Of course, if we can't setup a fast handler, we make it MPSAFE
	 * right away.
	 */
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		if (ch->ch_ires == NULL)
			continue;
		error = bus_setup_intr(dev, ch->ch_ires,
		    INTR_TYPE_TTY, scc_bfe_intr, NULL, sc,
		    &ch->ch_icookie);
		if (error) {
			error = bus_setup_intr(dev, ch->ch_ires,
			    INTR_TYPE_TTY | INTR_MPSAFE, NULL,
			    (driver_intr_t *)scc_bfe_intr, sc, &ch->ch_icookie);
		} else
			sc->sc_fastintr = 1;

		if (error) {
			device_printf(dev, "could not activate interrupt\n");
			bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
			    ch->ch_ires);
			ch->ch_ires = NULL;
		}
	}
	sc->sc_polled = 1;
	for (c = 0; c < cl->cl_channels; c++) {
		if (sc->sc_chan[0].ch_ires != NULL)
			sc->sc_polled = 0;
	}

	/*
	 * Attach all child devices that were probed successfully.
	 */
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		for (mode = 0; mode < SCC_NMODES; mode++) {
			m = &ch->ch_mode[mode];
			if (!m->m_probed)
				continue;
			error = device_attach(m->m_dev);
			if (error)
				continue;
			m->m_attached = 1;
		}
	}

	if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
		sep = "";
		device_print_prettyname(dev);
		if (sc->sc_fastintr) {
			printf("%sfast interrupt", sep);
			sep = ", ";
		}
		if (sc->sc_polled) {
			printf("%spolled mode", sep);
			sep = ", ";
		}
		printf("\n");
	}

	return (0);

 fail:
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		if (ch->ch_ires == NULL)
			continue;
		bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
		    ch->ch_ires);
	}
	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
	return (error);
}
Exemple #30
0
/* Helper for bus_rescan_devices's iter */
static int bus_rescan_devices_helper(struct device *dev, void *data)
{
	if (!dev->driver)
		device_attach(dev);
	return 0;
}