* @brief Attach a device driver to a device * * This function is a wrapper around the DEVICE_ATTACH() driver * method. In addition to calling DEVICE_ATTACH(), it initialises the * device's sysctl tree, optionally prints a description of the device * and queues a notification event for user-based device management * services. * * Normally this function is only called internally from * devi
| 2931 | * @retval non-zero some other unix error code |
| 2932 | */ |
| 2933 | int |
| 2934 | device_attach(device_t dev) |
| 2935 | { |
| 2936 | uint64_t attachtime; |
| 2937 | uint16_t attachentropy; |
| 2938 | int error; |
| 2939 | |
| 2940 | if (resource_disabled(dev->driver->name, dev->unit)) { |
| 2941 | device_disable(dev); |
| 2942 | if (bootverbose) |
| 2943 | device_printf(dev, "disabled via hints entry\n"); |
| 2944 | return (ENXIO); |
| 2945 | } |
| 2946 | |
| 2947 | device_sysctl_init(dev); |
| 2948 | if (!device_is_quiet(dev)) |
| 2949 | device_print_child(dev->parent, dev); |
| 2950 | attachtime = get_cyclecount(); |
| 2951 | dev->state = DS_ATTACHING; |
| 2952 | if ((error = DEVICE_ATTACH(dev)) != 0) { |
| 2953 | printf("device_attach: %s%d attach returned %d\n", |
| 2954 | dev->driver->name, dev->unit, error); |
| 2955 | if (!(dev->flags & DF_FIXEDCLASS)) |
| 2956 | devclass_delete_device(dev->devclass, dev); |
| 2957 | (void)device_set_driver(dev, NULL); |
| 2958 | device_sysctl_fini(dev); |
| 2959 | KASSERT(dev->busy == 0, ("attach failed but busy")); |
| 2960 | dev->state = DS_NOTPRESENT; |
| 2961 | return (error); |
| 2962 | } |
| 2963 | dev->flags |= DF_ATTACHED_ONCE; |
| 2964 | /* We only need the low bits of this time, but ranges from tens to thousands |
| 2965 | * have been seen, so keep 2 bytes' worth. |
| 2966 | */ |
| 2967 | attachentropy = (uint16_t)(get_cyclecount() - attachtime); |
| 2968 | random_harvest_direct(&attachentropy, sizeof(attachentropy), RANDOM_ATTACH); |
| 2969 | device_sysctl_update(dev); |
| 2970 | if (dev->busy) |
| 2971 | dev->state = DS_BUSY; |
| 2972 | else |
| 2973 | dev->state = DS_ATTACHED; |
| 2974 | dev->flags &= ~DF_DONENOMATCH; |
| 2975 | EVENTHANDLER_DIRECT_INVOKE(device_attach, dev); |
| 2976 | devadded(dev); |
| 2977 | return (0); |
| 2978 | } |
| 2979 | |
| 2980 | /** |
| 2981 | * @brief Detach a driver from a device |
no test coverage detected