freebsd compat. layer: added ETHER_SETPROMISC, ETHER_GET_LINK_STATE and ETHER_SET_LINK_STATE_SEM support.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21050 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos 2007-05-07 05:29:06 +00:00
parent 9534d90eb9
commit b27873dc4a
4 changed files with 62 additions and 14 deletions

View File

@ -267,8 +267,8 @@ uint64_t ifmedia_baudrate(int);
/*
* Status bits
*/
#define IFM_AVALID 0x00000001 /* Active bit valid */
#define IFM_ACTIVE 0x00000002 /* Interface attached to working net */
#define IFM_AVALID 0x10000000 /* Active bit valid */
#define IFM_ACTIVE 0x00800000 /* same as Haiku's */
/* Mask of "status valid" bits, for ifconfig(8). */
#define IFM_STATUS_VALID IFM_AVALID

View File

@ -61,6 +61,8 @@ allocate_device(driver_t *driver)
return NULL;
}
dev->link_state_sem = -1;
ifq_init(&dev->receive_queue, semName);
return dev;
@ -241,29 +243,47 @@ static status_t
compat_control(void *cookie, uint32 op, void *arg, size_t len)
{
device_t dev = cookie;
struct ifnet *ifp = dev->ifp;
switch (op) {
case ETHER_INIT:
return B_OK;
case ETHER_GETADDR:
memcpy(arg, IF_LLADDR(dev->ifp), ETHER_ADDR_LEN);
return B_OK;
return user_memcpy(arg, IF_LLADDR(dev->ifp), ETHER_ADDR_LEN);
case ETHER_NONBLOCK:
if (*(int32 *)arg)
{
int32 value;
if (len < 4)
return B_BAD_VALUE;
if (user_memcpy(&value, arg, sizeof(int32)) < B_OK)
return B_BAD_ADDRESS;
if (value)
dev->flags |= DEVICE_NON_BLOCK;
else
dev->flags &= ~DEVICE_NON_BLOCK;
return B_OK;
}
case ETHER_SETPROMISC:
/* TODO */
return B_ERROR;
{
int32 value;
if (len < 4)
return B_BAD_VALUE;
if (user_memcpy(&value, arg, sizeof(int32)) < B_OK)
return B_BAD_ADDRESS;
if (value)
ifp->if_flags |= IFF_PROMISC;
else
ifp->if_flags &= ~IFF_PROMISC;
return ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL);
}
case ETHER_GETFRAMESIZE:
*(uint32 *)arg = dev->ifp->if_mtu;
return B_OK;
if (len < 4)
return B_BAD_VALUE;
return user_memcpy(arg, &dev->ifp->if_mtu, 4);
case ETHER_ADDMULTI:
case ETHER_REMMULTI:
@ -271,11 +291,38 @@ compat_control(void *cookie, uint32 op, void *arg, size_t len)
return B_ERROR;
case ETHER_GET_LINK_STATE:
/* TODO */
return B_ERROR;
{
struct ifmediareq mediareq;
ether_link_state_t state;
status_t status;
if (len < sizeof(ether_link_state_t))
return EINVAL;
memset(&mediareq, 0, sizeof(mediareq));
status = ifp->if_ioctl(ifp, SIOCGIFMEDIA, &mediareq);
if (status < B_OK)
return status;
state.media = mediareq.ifm_active;
if (mediareq.ifm_status & IFM_ACTIVE)
state.media |= IFM_ACTIVE;
if (mediareq.ifm_active & IFM_10_T)
state.speed = 10000;
else if (mediareq.ifm_active & IFM_100_TX)
state.speed = 100000;
else
state.speed = 1000000;
state.quality = 1000;
return user_memcpy(arg, &state, sizeof(ether_link_state_t));
}
case ETHER_SET_LINK_STATE_SEM:
/* TODO */
if (user_memcpy(&dev->link_state_sem, arg, sizeof(sem_id)) < B_OK) {
dev->link_state_sem = -1;
return B_BAD_ADDRESS;
}
return B_OK;
}

View File

@ -32,6 +32,8 @@ struct device {
struct ifqueue receive_queue;
sem_id receive_sem;
sem_id link_state_sem;
struct ifnet * ifp;
int unit;

View File

@ -143,8 +143,7 @@ if_link_state_change(struct ifnet *ifp, int link_state)
ifp->if_link_state = link_state;
/* XXX */
/* wake network stack's link state sem */
release_sem_etc(ifp->if_dev->link_state_sem, 1, B_DO_NOT_RESCHEDULE);
}