You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
2.3 KiB

/* This contains large amounts of code from Donald Becker's mii-diag.c.
* The copyright for that file is as follows:
*
* Written/copyright 1997-2002 by Donald Becker <becker@scyld.com>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation.
*
* The author may be reached as becker@scyld.com, or C/O
* Scyld Computing Corporation
* 410 Severn Ave., Suite 210
* Annapolis MD 21403
*
* The excerpt and the corresponding glue made to make it work with netcfg
* is (C) 2004 Joshua Kwan <joshk@triplehelix.org>, and by consequence is
* also under the GPL.
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <debian-installer/log.h>
#include "netcfg.h"
typedef unsigned short u16;
int skfd = -1; /* AF_INET socket for ioctl() calls. */
struct ifreq ifr;
int new_ioctl_nums;
inline int mdio_read(int skfd, int phy_id, int location);
method_t
mii_diag_status_lite (char *ifname)
{
u16 *data = NULL;
/* Open a basic socket. */
if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
di_error("Couldn't open skfd!");
return DUNNO;
}
/* Verify that the interface supports the ioctl(), and if
it is using the new or old SIOCGMIIPHY value (grrr...).
*/
data = (u16 *)(&ifr.ifr_data);
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
data[0] = 0;
if (ioctl(skfd, 0x8947, &ifr) >= 0)
new_ioctl_nums = 1;
else if (ioctl(skfd, SIOCDEVPRIVATE, &ifr) >= 0)
new_ioctl_nums = 0;
else {
close(skfd);
return DUNNO;
}
if ((mdio_read(skfd, (unsigned)data[0], 1) & 0x0004) == 0)
{
di_info("ioctl: media state for %s is: disconnected", ifname);
return STATIC;
}
else
{
close(skfd);
di_info("ioctl: media state for %s is: connected", ifname);
return DHCP;
}
}
inline int mdio_read(int skfd, int phy_id, int location)
{
u16 *data = (u16 *)(&ifr.ifr_data);
data[0] = phy_id;
data[1] = location;
if (ioctl(skfd, new_ioctl_nums ? 0x8948 : SIOCDEVPRIVATE+1, &ifr) < 0)
return -1;
else
return data[3];
}