Example #1
0
status_t
device_node::Reprobe()
{
	status_t status = InitDriver();
	if (status < B_OK)
		return status;

	MethodDeleter<device_node, bool> uninit(this,
		&device_node::UninitDriver);

	// If this child has been probed already, probe it again
	status = _Probe();
	if (status != B_OK)
		return status;

	NodeList::Iterator iterator = fChildren.GetIterator();
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();

		status = child->Reprobe();
		if (status != B_OK)
			return status;
	}

	return B_OK;
}
Example #2
0
status_t
device_node::Rescan()
{
	status_t status = InitDriver();
	if (status < B_OK)
		return status;

	MethodDeleter<device_node, bool> uninit(this,
		&device_node::UninitDriver);

	if (DriverModule()->rescan_child_devices != NULL) {
		status = DriverModule()->rescan_child_devices(DriverData());
		if (status != B_OK)
			return status;
	}

	NodeList::Iterator iterator = fChildren.GetIterator();
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();

		status = child->Rescan();
		if (status != B_OK)
			return status;
	}

	return B_OK;
}
Example #3
0
/*! Gets the boot device, scans all of its partitions, gets the
	boot partition, and mounts its file system.

	\param args The stage 2 arguments.
	\param _bootVolume On success set to the boot volume.
	\return \c B_OK on success, another error code otherwise.
*/
status_t
get_boot_file_system(stage2_args* args, BootVolume& _bootVolume)
{
	status_t error = platform_add_boot_device(args, &gBootDevices);
	if (error != B_OK)
		return error;

	NodeIterator iterator = gBootDevices.GetIterator();
	while (iterator.HasNext()) {
		Node *device = iterator.Next();

		error = add_partitions_for(device, false, true);
		if (error != B_OK)
			continue;

		NodeList bootPartitions;
		error = platform_get_boot_partitions(args, device, &gPartitions, &bootPartitions);
		if (error != B_OK)
			continue;

		NodeIterator partitionIterator = bootPartitions.GetIterator();
		while (partitionIterator.HasNext()) {
			Partition *partition = (Partition*)partitionIterator.Next();

			Directory *fileSystem;
			error = partition->Mount(&fileSystem, true);
			if (error != B_OK) {
				// this partition doesn't contain any known file system; we
				// don't need it anymore
				gPartitions.Remove(partition);
				delete partition;
				continue;
			}

			// init the BootVolume
			error = _bootVolume.SetTo(fileSystem);
			if (error != B_OK)
				continue;

			sBootDevice = device;
			return B_OK;
		}
	}

	return B_ERROR;
}
Example #4
0
void
device_node::_ReleaseWaiting()
{
	NodeList::Iterator iterator = fChildren.GetIterator();
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();

		child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER;
	}
}
Example #5
0
status_t
device_node::_RemoveChildren()
{
	NodeList::Iterator iterator = fChildren.GetIterator();
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();
		child->Release();
	}

	return fChildren.IsEmpty() ? B_OK : B_BUSY;
}
Example #6
0
device_node*
device_node::_FindCurrentChild()
{
	NodeList::Iterator iterator = fChildren.GetIterator();
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();

		if ((child->Flags() & NODE_FLAG_WAITING_FOR_DRIVER) == 0)
			return child;
	}

	return NULL;
}
Example #7
0
/*!	Uninitializes all temporary references to the driver. The registration
	process keeps the driver initialized to optimize the startup procedure;
	this function gives this reference away again.
*/
void
device_node::UninitUnusedDriver()
{
	// First, we need to go to the leaf, and go back from there

	NodeList::Iterator iterator = fChildren.GetIterator();
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();

		child->UninitUnusedDriver();
	}

	if (!IsInitialized()
		|| (fFlags & NODE_FLAG_REGISTER_INITIALIZED) == 0)
		return;

	fFlags &= ~NODE_FLAG_REGISTER_INITIALIZED;

	UninitDriver();
}
Example #8
0
void
device_node::AddChild(device_node* node)
{
	// we must not be destroyed	as long as we have children
	Acquire();
	node->fParent = this;

	int32 priority = node->Priority();

	// Enforce an order in which the children are traversed - from most
	// specific to least specific child.
	NodeList::Iterator iterator = fChildren.GetIterator();
	device_node* before = NULL;
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();
		if (child->Priority() <= priority) {
			before = child;
			break;
		}
	}

	fChildren.Insert(before, node);
}
Example #9
0
status_t
mount_file_systems(stage2_args *args)
{
	// mount other partitions on boot device (if any)
	NodeIterator iterator = gPartitions.GetIterator();

	Partition *partition = NULL;
	while ((partition = (Partition *)iterator.Next()) != NULL) {
		// don't scan known partitions again
		if (partition->IsFileSystem())
			continue;

		// remove the partition if it doesn't contain a (known) file system
		if (partition->Scan(true) != B_OK && !partition->IsFileSystem()) {
			gPartitions.Remove(partition);
			delete partition;
		}
	}

	// add all block devices the platform has for us

	status_t status = platform_add_block_devices(args, &gBootDevices);
	if (status < B_OK)
		return status;

	iterator = gBootDevices.GetIterator();
	Node *device = NULL, *last = NULL;
	while ((device = iterator.Next()) != NULL) {
		// don't scan former boot device again
		if (device == sBootDevice)
			continue;

		if (add_partitions_for(device, true) == B_OK) {
			// ToDo: we can't delete the object here, because it must
			//	be removed from the list before we know that it was
			//	deleted.

/*			// if the Release() deletes the object, we need to skip it
			if (device->Release() > 0) {
				list_remove_item(&gBootDevices, device);
				device = last;
			}
*/
(void)last;
		}
		last = device;
	}

	if (gPartitions.IsEmpty())
		return B_ENTRY_NOT_FOUND;

#if 0
	void *cookie;
	if (gRoot->Open(&cookie, O_RDONLY) == B_OK) {
		Directory *directory;
		while (gRoot->GetNextNode(cookie, (Node **)&directory) == B_OK) {
			char name[256];
			if (directory->GetName(name, sizeof(name)) == B_OK)
				printf(":: %s (%p)\n", name, directory);

			void *subCookie;
			if (directory->Open(&subCookie, O_RDONLY) == B_OK) {
				while (directory->GetNextEntry(subCookie, name, sizeof(name)) == B_OK) {
					printf("\t%s\n", name);
				}
				directory->Close(subCookie);
			}
		}
		gRoot->Close(cookie);
	}
#endif

	return B_OK;
}
Example #10
0
status_t
device_node::Probe(const char* devicePath, uint32 updateCycle)
{
	if ((fFlags & NODE_FLAG_DEVICE_REMOVED) != 0
		|| updateCycle == fLastUpdateCycle)
		return B_OK;

	status_t status = InitDriver();
	if (status < B_OK)
		return status;

	MethodDeleter<device_node, bool> uninit(this,
		&device_node::UninitDriver);

	if ((fFlags & B_FIND_CHILD_ON_DEMAND) != 0) {
		bool matches = false;
		uint16 type = 0;
		uint16 subType = 0;
		if (get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) == B_OK
			&& get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK) {
			// Check if this node matches the device path
			// TODO: maybe make this extendible via settings file?
			if (!strcmp(devicePath, "disk")) {
				matches = type == PCI_mass_storage;
			} else if (!strcmp(devicePath, "audio")) {
				matches = type == PCI_multimedia
					&& (subType == PCI_audio || subType == PCI_hd_audio);
			} else if (!strcmp(devicePath, "net")) {
				matches = type == PCI_network;
			} else if (!strcmp(devicePath, "graphics")) {
				matches = type == PCI_display;
			} else if (!strcmp(devicePath, "video")) {
				matches = type == PCI_multimedia && subType == PCI_video;
			}
		} else {
			// This driver does not support types, but still wants to its
			// children explored on demand only.
			matches = true;
			sGenericContextPath = devicePath;
		}

		if (matches) {
			fLastUpdateCycle = updateCycle;
				// This node will be probed in this update cycle

			status = _Probe();

			sGenericContextPath = NULL;
			return status;
		}

		return B_OK;
	}

	NodeList::Iterator iterator = fChildren.GetIterator();
	while (iterator.HasNext()) {
		device_node* child = iterator.Next();

		status = child->Probe(devicePath, updateCycle);
		if (status != B_OK)
			return status;
	}

	return B_OK;
}