Changeset 25406

Show
Ignore:
Timestamp:
05/09/08 17:05:50 (3 days ago)
Author:
axeld
Message:
* Work in progress: driver loading triggered by devfs.
* get_driver() now returns a result, as you may theoretically call it on
  any node (and not just your parent, which is guaranteed to be there).
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • haiku/trunk/src/tests/system/kernel/device_manager/playground/device_manager.cpp

    r25394 r25406  
    9797 
    9898                        status_t                InitDriver(); 
    99                         void                  UninitDriver(); 
     99                        bool                  UninitDriver(); 
    100100 
    101101                        // The following two are only valid, if the node's driver is 
     
    107107                        void                    RemoveChild(device_node *node); 
    108108                        const NodeList& Children() const { return fChildren; } 
     109                        void                    UninitUnusedChildren(); 
    109110 
    110111                        status_t                Register(); 
     112                        status_t                Probe(const char* devicePath); 
    111113                        bool                    IsRegistered() const { return fRegistered; } 
     114                        bool                    IsInitialized() const { return fInitialized > 0; } 
    112115 
    113116private: 
     
    124127                        status_t                _RegisterPath(const char* path); 
    125128                        status_t                _RegisterDynamic(); 
     129                        status_t                _RemoveChildren(); 
     130                        bool                    _UninitUnusedChildren(); 
    126131 
    127132        device_node*                    fParent; 
     
    130135        int32                                   fInitialized; 
    131136        bool                                    fRegistered; 
     137        uint32                                  fFlags; 
    132138 
    133139        const char*                             fModuleName; 
     
    138144}; 
    139145 
     146enum node_flags { 
     147        NODE_FLAG_REMOVE_ON_UNINIT      = 0x01 
     148}; 
     149 
    140150device_manager_info *gDeviceManager; 
    141151 
    142152static device_node *sRootNode; 
     153static recursive_lock sLock; 
    143154 
    144155 
     
    372383 
    373384 
     385static void 
     386uninit_unused() 
     387{ 
     388        RecursiveLocker _(sLock); 
     389        sRootNode->UninitUnusedChildren(); 
     390} 
     391 
     392 
     393static status_t 
     394probe_path(const char* path) 
     395{ 
     396        RecursiveLocker _(sLock); 
     397        return sRootNode->Probe(path); 
     398} 
     399 
     400 
    374401//      #pragma mark - device_node 
    375402 
     
    408435device_node::~device_node() 
    409436{ 
    410         AttributeList::Iterator iterator = fAttributes.GetIterator(); 
    411         while (iterator.HasNext()) { 
    412                 device_attr_private* attr = iterator.Next(); 
    413                 iterator.Remove(); 
     437        // Delete children 
     438        NodeList::Iterator nodeIterator = fChildren.GetIterator(); 
     439        while (nodeIterator.HasNext()) { 
     440                device_node* child = nodeIterator.Next(); 
     441                nodeIterator.Remove(); 
     442                delete child; 
     443        } 
     444 
     445        // Delete attributes 
     446        AttributeList::Iterator attrIterator = fAttributes.GetIterator(); 
     447        while (attrIterator.HasNext()) { 
     448                device_attr_private* attr = attrIterator.Next(); 
     449                attrIterator.Remove(); 
    414450                delete attr; 
    415451        } 
     452 
    416453        free((char*)fModuleName); 
    417454} 
     
    449486 
    450487 
    451 void 
     488bool 
    452489device_node::UninitDriver() 
    453490{ 
    454491        if (fInitialized-- > 1) 
    455                 return
     492                return false
    456493 
    457494        if (fDriver->uninit_driver != NULL) 
    458495                fDriver->uninit_driver(this); 
     496 
     497        fDriver = NULL; 
    459498        fDriverData = NULL; 
    460499 
    461500        put_module(ModuleName()); 
     501 
     502        if ((fFlags & NODE_FLAG_REMOVE_ON_UNINIT) != 0) 
     503                delete this; 
     504 
     505        return true; 
    462506} 
    463507 
     
    808852 
    809853 
    810 //      #pragma mark - 
     854status_t 
     855device_node::_RemoveChildren() 
     856
     857        NodeList::Iterator iterator = fChildren.GetIterator(); 
     858        while (iterator.HasNext()) { 
     859                device_node* child = iterator.Next(); 
     860 
     861                if (!child->IsInitialized()) { 
     862                        // this child is not used currently, and can be removed safely 
     863                        iterator.Remove(); 
     864                        fRefCount--; 
     865                        child->fParent = NULL; 
     866                        delete child; 
     867                } else 
     868                        child->fFlags |= NODE_FLAG_REMOVE_ON_UNINIT; 
     869        } 
     870 
     871        return fChildren.IsEmpty() ? B_OK : B_BUSY; 
     872
     873 
     874 
     875status_t 
     876device_node::Probe(const char* devicePath) 
     877
     878        uint16 type = 0; 
     879        uint16 subType = 0; 
     880        if (dm_get_attr_uint16(this, B_DEVICE_TYPE, &type, false) == B_OK 
     881                && dm_get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false) 
     882                        == B_OK) { 
     883                // Check if this node matches the device path 
     884                // TODO: maybe make this extendible via settings file? 
     885                bool matches = false; 
     886                if (!strcmp(devicePath, "disk")) { 
     887                        matches = type == PCI_mass_storage; 
     888                } else if (!strcmp(devicePath, "audio")) { 
     889                        matches = type == PCI_multimedia 
     890                                && (subType == PCI_audio || subType == PCI_hd_audio); 
     891                } else if (!strcmp(devicePath, "net")) { 
     892                        matches = type == PCI_network; 
     893                } else if (!strcmp(devicePath, "graphics")) { 
     894                        matches = type == PCI_display; 
     895                } else if (!strcmp(devicePath, "video")) { 
     896                        matches = type == PCI_multimedia && subType == PCI_video; 
     897                } 
     898 
     899                if (matches) { 
     900                        if (!fChildren.IsEmpty()) { 
     901                                // We already have a driver that claims this node. 
     902                                // Try to remove uninitialized children, so that this node 
     903                                // can be re-evaluated 
     904                                // TODO: try first if there is a better child! 
     905                                // TODO: publish both devices, make new one busy as long 
     906                                // as the old one is in use! 
     907                                if (_RemoveChildren() != B_OK) 
     908                                        return B_OK; 
     909                        } 
     910                        return _RegisterDynamic(); 
     911                } 
     912 
     913                return B_OK; 
     914        } 
     915 
     916        NodeList::Iterator iterator = fChildren.GetIterator(); 
     917        while (iterator.HasNext()) { 
     918                device_node* child = iterator.Next(); 
     919                 
     920                status_t status = child->Probe(devicePath); 
     921                if (status != B_OK) 
     922                        return status; 
     923        } 
     924 
     925        return B_OK; 
     926
     927 
     928 
     929bool 
     930device_node::_UninitUnusedChildren() 
     931
     932        // First, we need to go to the leaf, and go back from there 
     933 
     934        bool uninit = true; 
     935 
     936        NodeList::Iterator iterator = fChildren.GetIterator(); 
     937 
     938        while (iterator.HasNext()) { 
     939                device_node* child = iterator.Next(); 
     940 
     941                if (!child->_UninitUnusedChildren()) 
     942                        uninit = false; 
     943        } 
     944 
     945        // Not all of our children could be uninitialized 
     946        if (!uninit) 
     947                return false; 
     948 
     949        if (!IsInitialized()) 
     950                return true; 
     951 
     952        if ((DriverModule()->info.flags & B_KEEP_LOADED) != 0) { 
     953                // We must not get unloaded 
     954                return false; 
     955        } 
     956 
     957        return UninitDriver(); 
     958
     959 
     960 
     961void 
     962device_node::UninitUnusedChildren() 
     963
     964        _UninitUnusedChildren(); 
     965
    811966 
    812967 
     
    838993        TRACE(("%p: register device \"%s\", parent %p\n", newNode, moduleName, 
    839994                parent)); 
     995 
     996        RecursiveLocker _(sLock); 
    840997 
    841998        status_t status = newNode->InitCheck(); 
     
    8911048 
    8921049 
    893 static void 
     1050static status_t 
    8941051get_driver(device_node* node, driver_module_info** _module, void** _data) 
    8951052{ 
     1053        if (node->DriverModule() == NULL) 
     1054                return B_NO_INIT; 
     1055 
    8961056        if (_module != NULL) 
    8971057                *_module = node->DriverModule(); 
    8981058        if (_data != NULL) 
    8991059                *_data = node->DriverData(); 
     1060 
     1061        return B_OK; 
    9001062} 
    9011063 
     
    11371299        } 
    11381300 
     1301        recursive_lock_init(&sLock, "device manager"); 
     1302 
    11391303        dm_init_root_node(); 
    11401304        dm_dump_node(sRootNode, 0); 
    11411305 
     1306        probe_path("net"); 
     1307        uninit_unused(); 
     1308 
     1309        recursive_lock_destroy(&sLock); 
    11421310        return 0; 
    11431311} 
  • haiku/trunk/src/tests/system/kernel/device_manager/playground/device_manager.h

    r25394 r25406  
    7070        status_t (*unregister_device)(device_node *node); 
    7171 
    72         void (*get_driver)(device_node *node, driver_module_info **_module, 
     72        status_t (*get_driver)(device_node *node, driver_module_info **_module, 
    7373                                        void **_cookie); 
    7474