added ADDMULTI/REMMULTI support to ipro1000. Also cleaned up the compat. layer a bit to reuse some of the system's definitions.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20960 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos 2007-05-02 00:10:00 +00:00
parent 96575d053e
commit 09b89797af
6 changed files with 162 additions and 68 deletions
headers/posix/net
src/add-ons/kernel/drivers/network/ipro1000

@ -52,6 +52,7 @@ struct ifreq {
int ifr_mtu;
int ifr_media;
int ifr_type;
int ifr_reqcap;
};
};

@ -296,6 +296,13 @@ ipro1000_write(void* cookie, off_t position, const void* buffer, size_t* num_byt
}
static struct ifnet *
device_ifp(ipro1000_device *device)
{
return &device->adapter->interface_data.ac_if;
}
status_t
ipro1000_control(void *cookie, uint32 op, void *arg, size_t len)
{
@ -322,13 +329,24 @@ ipro1000_control(void *cookie, uint32 op, void *arg, size_t len)
return B_OK;
case ETHER_ADDMULTI:
DEVICE_DEBUGOUT("ipro1000_control() ETHER_ADDMULTI not supported");
break;
case ETHER_REMMULTI:
DEVICE_DEBUGOUT("ipro1000_control() ETHER_REMMULTI not supported");
return B_OK;
{
struct ifnet *ifp = device_ifp(device);
struct sockaddr_dl address;
if (len != ETHER_ADDR_LEN)
return EINVAL;
memset(&address, 0, sizeof(address));
address.sdl_family = AF_LINK;
memcpy(LLADDR(&address), arg, ETHER_ADDR_LEN);
if (op == ETHER_ADDMULTI)
return ether_add_multi(ifp, (struct sockaddr *)&address);
else
return ether_rem_multi(ifp, (struct sockaddr *)&address);
}
case ETHER_SETPROMISC:
if (*(int32 *)arg) {
DEVICE_DEBUGOUT("promiscuous mode on not supported");
@ -345,14 +363,13 @@ ipro1000_control(void *cookie, uint32 op, void *arg, size_t len)
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
case ETHER_GET_LINK_STATE:
{
struct ifnet ifp = { .if_softc = device->adapter };
struct ifmediareq mediareq;
ether_link_state_t state;
if (len < sizeof(ether_link_state_t))
return ENOBUFS;
em_media_status(&ifp, &mediareq);
em_media_status(device_ifp(device), &mediareq);
state.media = mediareq.ifm_active;
if (mediareq.ifm_status & IFM_ACTIVE)

@ -22,6 +22,9 @@
#include "debug.h"
#include "mempool.h"
#undef malloc
#undef free
spinlock mbuf_lock = 0;
struct mbuf *
@ -96,6 +99,8 @@ ether_ifattach(struct ifnet *ifp, const uint8 *etheraddr)
INIT_DEBUGOUT("ether_ifattach");
TAILQ_INIT(&ifp->if_multiaddrs);
memcpy(dev->macaddr, etheraddr, 6);
ifp->if_input = ether_input;
@ -108,12 +113,85 @@ ether_ifattach(struct ifnet *ifp, const uint8 *etheraddr)
INIT_DEBUGOUT("done calling if_init!");
}
static struct ifmultiaddr *
ether_find_multi(struct ifnet *ifp, const struct sockaddr *_address)
{
const struct sockaddr_dl *address = (const struct sockaddr_dl *)_address;
struct ifmultiaddr *ifma;
TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link) {
if (memcmp(LLADDR(address),
LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
ETHER_ADDR_LEN) == 0)
return ifma;
}
return NULL;
}
int
ether_add_multi(struct ifnet *ifp, const struct sockaddr *address)
{
struct ifmultiaddr *addr = ether_find_multi(ifp, address);
if (addr != NULL) {
addr->ifma_refcount++;
return 0;
}
addr = (struct ifmultiaddr *)malloc(sizeof(struct ifmultiaddr));
if (addr == NULL)
return ENOBUFS;
memcpy(&addr->ifma_addr_storage, address, sizeof(struct sockaddr_dl));
addr->ifma_addr = (struct sockaddr *)&addr->ifma_addr_storage;
addr->ifma_refcount = 1;
TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, addr, ifma_link);
return ifp->if_ioctl(ifp, SIOCADDMULTI, NULL);
}
static void
ether_delete_multi(struct ifnet *ifp, struct ifmultiaddr *ifma)
{
TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
free(ifma);
}
int
ether_rem_multi(struct ifnet *ifp, const struct sockaddr *address)
{
struct ifmultiaddr *addr = ether_find_multi(ifp, address);
if (addr == NULL)
return EADDRNOTAVAIL;
addr->ifma_refcount--;
if (addr->ifma_refcount == 0) {
ether_delete_multi(ifp, addr);
return ifp->if_ioctl(ifp, SIOCDELMULTI, NULL);
}
return 0;
}
void
ether_ifdetach(struct ifnet *ifp)
{
struct ifmultiaddr *ifma, *next;
INIT_DEBUGOUT("ether_ifdetach");
delete_sem(ifp->if_rcv_sem);
TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next)
ether_delete_multi(ifp, ifma);
}
struct mbuf *

@ -20,18 +20,16 @@
#define __IF_COMPAT_H
#include <OS.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include "if_em_osdep.h" // for TAILQ_...
#define __FreeBSD_version 500001
#define IFF_BROADCAST 0x0001
#define IFF_SIMPLEX 0x0002
#define IFF_MULTICAST 0x0004
#define IFF_RUNNING 0x0008
#define IFF_OACTIVE 0x0010
#define IFF_UP 0x0020
#define IFF_PROMISC 0x0040
#define IFF_ALLMULTI 0x0080
#define IFF_RUNNING 0x10000
#define IFF_OACTIVE 0x20000
#define IFCAP_HWCSUM 0x0001
#define IFCAP_VLAN_HWTAGGING 0x0002
@ -203,15 +201,19 @@ void m_freem(struct mbuf *mp);
void ether_ifattach(struct ifnet *ifp, const uint8 *etheraddr);
void ether_ifdetach(struct ifnet *ifp);
#define AF_LINK 0
struct ifma_addr
{
int sa_family; // must be AF_LINK
};
int ether_add_multi(struct ifnet *ifp, const struct sockaddr *address);
int ether_rem_multi(struct ifnet *ifp, const struct sockaddr *address);
TAILQ_HEAD(ifmultihead, ifmultiaddr);
struct ifmultiaddr
{
struct ifma_addr *ifma_addr;
TAILQ_ENTRY(ifmultiaddr) ifma_link;
struct sockaddr *ifma_addr;
int ifma_refcount;
/* private */
struct sockaddr_dl ifma_addr_storage;
};
struct if_data
@ -257,8 +259,8 @@ struct ifnet
sem_id if_rcv_sem;
// struct if_multiaddrs if_multiaddrs; // multicast addr list
struct if_data if_data;
struct ifmultihead if_multiaddrs;
if_start if_start;
if_ioctl if_ioctl;
@ -295,34 +297,12 @@ enum { // ioctl commands
SIOCSIFCAP,
};
struct ifreq // ioctl command data
{
uint32 ifr_reqcap;
int ifr_mtu;
};
// used for media properties
#define ifmedia_init(a, b, c, d)
#define ifmedia_add(a, b, c, d)
#define ifmedia_set(a, b)
#define ifmedia_ioctl(ifp, ifr, media, command) 0
// used inside multicast stuff
struct sockaddr_dl
{
u_char sdl_len;
u_char sdl_family;
u_short sdl_index;
u_char sdl_type;
u_char sdl_nlen;
u_char sdl_alen;
u_char sdl_slen;
char sdl_data[46];
};
// used inside multicast stuff
#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen))
// called for SIOCxIFADDR (Get/Set Interface Addr)
#define ether_ioctl(ifp, command, data)

@ -1293,7 +1293,7 @@ em_set_multi(struct adapter * adapter)
u_int8_t mta[MAX_NUM_MULTICAST_ADDRESSES * ETH_LENGTH_OF_ADDRESS];
struct ifmultiaddr *ifma;
int mcnt = 0;
// struct ifnet *ifp = &adapter->interface_data.ac_if;
struct ifnet *ifp = &adapter->interface_data.ac_if;
IOCTL_DEBUGOUT("em_set_multi: begin");

@ -45,6 +45,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#define usec_delay(x) snooze(x)
@ -71,18 +72,6 @@ POSSIBILITY OF SUCH DAMAGE.
#define hz 1000000LL
typedef uint64 u_int64_t;
typedef uint32 u_int32_t;
typedef uint16 u_int16_t;
typedef uint8 u_int8_t;
typedef uint64 uint64_t;
typedef uint32 uint32_t;
typedef uint16 uint16_t;
typedef uint8 uint8_t;
typedef int64 int64_t;
typedef int32 int32_t;
typedef int16 int16_t;
typedef int8 int8_t;
typedef bool boolean_t;
typedef unsigned long vm_offset_t;
@ -210,16 +199,45 @@ void driver_free(void *p, int p2);
#define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \
E1000_WRITE_OFFSET(hw, E1000_REG_OFFSET(hw, reg) + ((index) << 2), value)
#define TAILQ_HEAD(name, type) \
struct name { struct type *tqh_first, **tqh_last; }
/*
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); \
(var); \
(var) = TAILQ_NEXT((var), field))
*/
// used only for multicast setup, fix later...
#define TAILQ_FOREACH(a, b, c) for (a = 0; a != 0; a = 0)
#define TAILQ_ENTRY(type) \
struct { struct type *tqe_next, **tqe_prev; }
#define TAILQ_FIRST(head) \
((head)->tqh_first)
#define TAILQ_NEXT(elm, field) \
((elm)->field.tqe_next)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = TAILQ_FIRST((head)); (var); (var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); (var) = (tvar))
#define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
TAILQ_FIRST((head))->field.tqe_prev = &TAILQ_NEXT((elm), field); \
else \
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
TAILQ_FIRST((head)) = (elm); \
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
} while (0)
#define TAILQ_REMOVE(head, elm, field) do { \
if ((TAILQ_NEXT((elm), field)) != NULL) \
TAILQ_NEXT((elm), field)->field.tqe_prev = (elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
} while (0)
#endif