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; }
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; }
/*! 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; }
void device_node::_ReleaseWaiting() { NodeList::Iterator iterator = fChildren.GetIterator(); while (iterator.HasNext()) { device_node* child = iterator.Next(); child->fFlags &= ~NODE_FLAG_WAITING_FOR_DRIVER; } }
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; }
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; }
/*! 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(); }
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); }
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; }
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; }