1 /* Intel PRO/1000 Family Driver
2 * Copyright (C) 2004 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
4 * Permission to use, copy, modify and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies, and that both the
7 * copyright notice and this permission notice appear in supporting documentation.
9 * Marcus Overhagen makes no representations about the suitability of this software
10 * for any purpose. It is provided "as is" without express or implied warranty.
12 * MARCUS OVERHAGEN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
13 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL MARCUS
14 * OVERHAGEN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
15 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "if_compat.h"
28 spinlock mbuf_lock
= 0;
31 m_gethdr(int how
, int type
)
33 struct mbuf
*m
= mbuf_pool_get();
36 memset(m
, 0, sizeof(m
));
37 m
->m_flags
= M_PKTHDR
;
42 m_clget(struct mbuf
* m
, int how
)
44 // TRACE("m_clget\n");
46 m
->m_ext
.ext_buf
= chunk_pool_get();
47 m
->m_data
= m
->m_ext
.ext_buf
;
53 m_adj(struct mbuf
*mp
, int bytes
)
55 mp
->m_data
= (char *)mp
->m_data
+ bytes
;
59 m_freem(struct mbuf
*mp
)
62 // TRACE("m_freem\n");
65 if (m
->m_flags
& M_EXT
)
66 chunk_pool_put(m
->m_ext
.ext_buf
);
74 ether_input(struct ifnet
*ifp
, struct mbuf
*m
)
80 buf = mtod(m, uint8 *);
82 TRACE("ether_input: received packet with %d bytes\n", len);
83 TRACE("%02x %02x %02x %02x . %02x %02x %02x %02x . %02x %02x %02x %02x \n",
84 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
85 buf[6], buf[7], buf[8], buf[8], buf[10], buf[11]);
91 IF_APPEND(&ifp
->if_rcv
, m
);
92 release_sem_etc(ifp
->if_rcv_sem
, 1, B_DO_NOT_RESCHEDULE
);
96 ether_ifattach(struct ifnet
*ifp
, const uint8
*etheraddr
)
98 ipro1000_device
*dev
= ifp
->if_softc
->dev
;
100 INIT_DEBUGOUT("ether_ifattach");
102 TAILQ_INIT(&ifp
->if_multiaddrs
);
104 memcpy(dev
->macaddr
, etheraddr
, 6);
106 ifp
->if_input
= ether_input
;
108 ifp
->if_rcv_sem
= create_sem(0, "ifp->if_rcv_sem");
109 set_sem_owner(ifp
->if_rcv_sem
, B_SYSTEM_TEAM
);
111 INIT_DEBUGOUT("calling if_init...");
112 ifp
->if_init(ifp
->if_softc
);
113 INIT_DEBUGOUT("done calling if_init!");
117 static struct ifmultiaddr
*
118 ether_find_multi(struct ifnet
*ifp
, const struct sockaddr
*_address
)
120 const struct sockaddr_dl
*address
= (const struct sockaddr_dl
*)_address
;
121 struct ifmultiaddr
*ifma
;
123 TAILQ_FOREACH (ifma
, &ifp
->if_multiaddrs
, ifma_link
) {
124 if (memcmp(LLADDR(address
),
125 LLADDR((struct sockaddr_dl
*)ifma
->ifma_addr
),
126 ETHER_ADDR_LEN
) == 0)
135 ether_add_multi(struct ifnet
*ifp
, const struct sockaddr
*address
)
137 struct ifmultiaddr
*addr
= ether_find_multi(ifp
, address
);
140 addr
->ifma_refcount
++;
144 addr
= (struct ifmultiaddr
*)malloc(sizeof(struct ifmultiaddr
));
148 memcpy(&addr
->ifma_addr_storage
, address
, sizeof(struct sockaddr_dl
));
149 addr
->ifma_addr
= (struct sockaddr
*)&addr
->ifma_addr_storage
;
151 addr
->ifma_refcount
= 1;
153 TAILQ_INSERT_HEAD(&ifp
->if_multiaddrs
, addr
, ifma_link
);
155 return ifp
->if_ioctl(ifp
, SIOCADDMULTI
, NULL
);
160 ether_delete_multi(struct ifnet
*ifp
, struct ifmultiaddr
*ifma
)
162 TAILQ_REMOVE(&ifp
->if_multiaddrs
, ifma
, ifma_link
);
168 ether_rem_multi(struct ifnet
*ifp
, const struct sockaddr
*address
)
170 struct ifmultiaddr
*addr
= ether_find_multi(ifp
, address
);
172 return EADDRNOTAVAIL
;
174 addr
->ifma_refcount
--;
175 if (addr
->ifma_refcount
== 0) {
176 ether_delete_multi(ifp
, addr
);
177 return ifp
->if_ioctl(ifp
, SIOCDELMULTI
, NULL
);
185 ether_ifdetach(struct ifnet
*ifp
)
187 struct ifmultiaddr
*ifma
, *next
;
189 INIT_DEBUGOUT("ether_ifdetach");
191 delete_sem(ifp
->if_rcv_sem
);
193 TAILQ_FOREACH_SAFE(ifma
, &ifp
->if_multiaddrs
, ifma_link
, next
)
194 ether_delete_multi(ifp
, ifma
);
198 if_dequeue(struct if_queue
*queue
)
203 // TRACE("IF_DEQUEUE\n");
205 s
= disable_interrupts();
206 acquire_spinlock(&mbuf_lock
);
208 m
= (struct mbuf
*) queue
->ifq_head
;
210 queue
->ifq_head
= m
->m_nextq
;
211 if (!queue
->ifq_head
)
216 release_spinlock(&mbuf_lock
);
217 restore_interrupts(s
);
223 if_prepend(struct if_queue
*queue
, struct mbuf
*mb
)
226 // TRACE("IF_PREPEND\n");
228 s
= disable_interrupts();
229 acquire_spinlock(&mbuf_lock
);
231 mb
->m_nextq
= (struct mbuf
*) queue
->ifq_head
;
232 queue
->ifq_head
= mb
;
233 if (!queue
->ifq_tail
)
234 queue
->ifq_tail
= mb
;
236 release_spinlock(&mbuf_lock
);
237 restore_interrupts(s
);
241 if_append(struct if_queue
*queue
, struct mbuf
*mb
)
244 // TRACE("IF_APPEND\n");
246 s
= disable_interrupts();
247 acquire_spinlock(&mbuf_lock
);
250 if (!queue
->ifq_tail
) {
251 queue
->ifq_tail
= mb
;
252 queue
->ifq_head
= mb
;
254 queue
->ifq_tail
->m_nextq
= mb
;
255 queue
->ifq_tail
= mb
;
258 release_spinlock(&mbuf_lock
);
259 restore_interrupts(s
);