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:
parent
96575d053e
commit
09b89797af
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user