static int
e1000_phys_id(struct net_device *netdev, uint32_t data)
{
	struct e1000_adapter *adapter = netdev->priv;

	if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
		data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);

	if(!adapter->blink_timer.function) {
		init_timer(&adapter->blink_timer);
		adapter->blink_timer.function = e1000_led_blink_callback;
		adapter->blink_timer.data = (unsigned long) adapter;
	}

	e1000_setup_led(&adapter->hw);
	mod_timer(&adapter->blink_timer, jiffies);

	msleep_interruptible(data * 1000);
	del_timer_sync(&adapter->blink_timer);
	e1000_led_off(&adapter->hw);
	clear_bit(E1000_LED_ON, &adapter->led_status);
	e1000_cleanup_led(&adapter->hw);

	return 0;
}
static int
e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
{
	if(!adapter->blink_timer.function) {
		init_timer(&adapter->blink_timer);
		adapter->blink_timer.function = e1000_led_blink_callback;
		adapter->blink_timer.data = (unsigned long) adapter;
	}

	e1000_setup_led(&adapter->hw);
	mod_timer(&adapter->blink_timer, jiffies);

	set_current_state(TASK_INTERRUPTIBLE);
	if(id->data)
		schedule_timeout(id->data * HZ);
	else
		schedule_timeout(MAX_SCHEDULE_TIMEOUT);

	del_timer_sync(&adapter->blink_timer);
	e1000_led_off(&adapter->hw);
	clear_bit(E1000_LED_ON, &adapter->led_status);
	e1000_cleanup_led(&adapter->hw);

	return 0;
}
static void
e1000_led_blink_callback(unsigned long data)
{
	struct e1000_adapter *adapter = (struct e1000_adapter *) data;

	if(test_and_change_bit(E1000_LED_ON, &adapter->led_status))
		e1000_led_off(&adapter->hw);
	else
		e1000_led_on(&adapter->hw);

	mod_timer(&adapter->blink_timer, jiffies + E1000_ID_INTERVAL);
}