status_t device_node::_GetNextDriverPath(void*& cookie, KPath& _path) { Stack<KPath*>* stack = NULL; if (cookie == NULL) { // find all paths and add them stack = new(std::nothrow) Stack<KPath*>(); if (stack == NULL) return B_NO_MEMORY; StackDeleter<KPath*> stackDeleter(stack); bool generic = false; uint16 type = 0; uint16 subType = 0; uint16 interface = 0; if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK || get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) != B_OK) generic = true; get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false); // TODO: maybe make this extendible via settings file? switch (type) { case PCI_mass_storage: switch (subType) { case PCI_scsi: _AddPath(*stack, "busses", "scsi"); _AddPath(*stack, "busses", "virtio"); break; case PCI_ide: _AddPath(*stack, "busses", "ata"); _AddPath(*stack, "busses", "ide"); break; case PCI_sata: // TODO: check for ahci interface _AddPath(*stack, "busses", "scsi"); _AddPath(*stack, "busses", "ata"); _AddPath(*stack, "busses", "ide"); break; default: _AddPath(*stack, "busses"); break; } break; case PCI_serial_bus: switch (subType) { case PCI_firewire: _AddPath(*stack, "busses", "firewire"); break; case PCI_usb: _AddPath(*stack, "busses", "usb"); break; default: _AddPath(*stack, "busses"); break; } break; case PCI_network: _AddPath(*stack, "drivers", "net"); _AddPath(*stack, "busses", "virtio"); break; case PCI_display: _AddPath(*stack, "drivers", "graphics"); break; case PCI_multimedia: switch (subType) { case PCI_audio: case PCI_hd_audio: _AddPath(*stack, "drivers", "audio"); break; case PCI_video: _AddPath(*stack, "drivers", "video"); break; default: _AddPath(*stack, "drivers"); break; } break; default: if (sRootNode == this) { _AddPath(*stack, "busses/pci"); _AddPath(*stack, "bus_managers"); } else if (!generic) { _AddPath(*stack, "busses", "virtio"); _AddPath(*stack, "drivers"); } else { // For generic drivers, we only allow busses when the // request is more specified if (sGenericContextPath != NULL && (!strcmp(sGenericContextPath, "disk") || !strcmp(sGenericContextPath, "ports") || !strcmp(sGenericContextPath, "bus"))) { _AddPath(*stack, "busses"); } _AddPath(*stack, "drivers", sGenericContextPath); _AddPath(*stack, "busses/scsi"); _AddPath(*stack, "busses/random"); } break; } stackDeleter.Detach(); cookie = (void*)stack; } else stack = static_cast<Stack<KPath*>*>(cookie); KPath* path; if (stack->Pop(&path)) { _path.Adopt(*path); delete path; return B_OK; } delete stack; return B_ENTRY_NOT_FOUND; }