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.
26 #include "if_compat.h"
28 #include <KernelExport.h>
29 #include <driver_settings.h>
35 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
36 # include <net/if_media.h>
42 static int32 gOpenMask
= 0;
44 int em_attach(device_t
);
45 int em_detach(device_t
);
46 void em_media_status(struct ifnet
*, struct ifmediareq
*);
50 ipro1000_read_settings(ipro1000_device
*device
)
56 handle
= load_driver_settings("ipro1000");
60 param
= get_driver_parameter(handle
, "mtu", "-1", "-1");
62 if (mtu
>= 50 && mtu
<= 1500)
63 device
->maxframesize
= mtu
+ ENET_HEADER_SIZE
;
65 dprintf("ipro1000: unsupported mtu setting '%s' ignored\n", param
);
67 unload_driver_settings(handle
);
72 ipro1000_open(const char *name
, uint32 flags
, void** cookie
)
74 ipro1000_device
*device
;
79 DEVICE_DEBUGOUT("ipro1000_open()");
81 for (dev_id
= 0; (deviceName
= gDevNameList
[dev_id
]) != NULL
; dev_id
++) {
82 if (!strcmp(name
, deviceName
))
85 if (deviceName
== NULL
) {
86 ERROROUT("invalid device name");
90 // allow only one concurrent access
92 if (atomic_or(&gOpenMask
, mask
) & mask
)
95 *cookie
= device
= (ipro1000_device
*)malloc(sizeof(ipro1000_device
));
97 atomic_and(&gOpenMask
, ~(1 << dev_id
));
101 memset(device
, 0, sizeof(*device
));
103 device
->devId
= dev_id
;
104 device
->pciInfo
= gDevList
[dev_id
];
105 device
->nonblocking
= (flags
& O_NONBLOCK
) ? true : false;
106 device
->closed
= false;
108 device
->pciBus
= device
->pciInfo
->bus
;
109 device
->pciDev
= device
->pciInfo
->device
;
110 device
->pciFunc
= device
->pciInfo
->function
;
112 device
->maxframesize
= 1514; // XXX is MAXIMUM_ETHERNET_FRAME_SIZE = 1518 too much?
114 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
115 device
->linkChangeSem
= -1;
118 ipro1000_read_settings(device
);
120 if (em_attach(device
) != 0) {
121 DEVICE_DEBUGOUT("em_attach failed");
129 atomic_and(&gOpenMask
, ~(1 << dev_id
));
135 ipro1000_close(void* cookie
)
137 ipro1000_device
*device
= (ipro1000_device
*)cookie
;
138 struct ifnet
*ifp
= &device
->adapter
->interface_data
.ac_if
;
139 DEVICE_DEBUGOUT("ipro1000_close()");
141 device
->closed
= true;
142 release_sem(ifp
->if_rcv_sem
);
149 ipro1000_free(void* cookie
)
151 ipro1000_device
*device
= (ipro1000_device
*)cookie
;
152 DEVICE_DEBUGOUT("ipro1000_free()");
154 if (em_detach(device
) != 0) {
155 DEVICE_DEBUGOUT("em_detach failed");
159 atomic_and(&gOpenMask
, ~(1 << device
->devId
));
165 ipro1000_read(void* cookie
, off_t position
, void *buf
, size_t* num_bytes
)
167 ipro1000_device
*device
= (ipro1000_device
*)cookie
;
168 struct ifnet
*ifp
= &device
->adapter
->interface_data
.ac_if
;
173 // DEVICE_DEBUGOUT("ipro1000_read() enter");
175 if (device
->closed
) {
176 DEVICE_DEBUGOUT("ipro1000_read() interrupted 1");
177 return B_INTERRUPTED
;
180 stat
= acquire_sem_etc(ifp
->if_rcv_sem
, 1, B_CAN_INTERRUPT
| (device
->nonblocking
? B_TIMEOUT
: 0), 0);
181 if (device
->closed
) {
182 // DEVICE_DEBUGOUT("ipro1000_read() interrupted 2"); // net_server will crash if we print this (race condition in net_server?)
183 return B_INTERRUPTED
;
185 if (stat
== B_WOULD_BLOCK
) {
186 DEVICE_DEBUGOUT("ipro1000_read() would block (OK 0 bytes)");
191 DEVICE_DEBUGOUT("ipro1000_read() error");
195 IF_DEQUEUE(&ifp
->if_rcv
, mb
);
197 ERROROUT("ipro1000_read() mbuf not ready");
204 if (len
> (int)*num_bytes
)
207 memcpy(buf
, mtod(mb
, uint8
*), len
); // XXX this is broken for jumbo frames
212 // DEVICE_DEBUGOUT1("ipro1000_read() leave, %d bytes", len);
218 ipro1000_write(void* cookie
, off_t position
, const void* buffer
, size_t* num_bytes
)
220 // bigtime_t t = system_time();
221 ipro1000_device
*device
= (ipro1000_device
*)cookie
;
222 struct ifnet
*ifp
= &device
->adapter
->interface_data
.ac_if
;
225 // DEVICE_DEBUGOUT("ipro1000_write() enter");
229 MGETHDR(mb
, M_DONTWAIT
, MT_DATA
);
234 return B_INTERRUPTED
;
237 // DEVICE_DEBUGOUT("ipro1000_write() 1");
241 MCLGET(mb
, M_DONTWAIT
);
242 if (mb
->m_flags
& M_EXT
)
245 if (device
->closed
) {
247 return B_INTERRUPTED
;
251 // DEVICE_DEBUGOUT("ipro1000_write() 2");
254 mb
->m_len
= *num_bytes
;
255 if (mb
->m_len
> MCLBYTES
)
256 mb
->m_len
= MCLBYTES
;
257 memcpy(mtod(mb
, uint8
*), buffer
, mb
->m_len
);
259 // DEVICE_DEBUGOUT("ipro1000_write() 3");
261 // add mbuf to send queue
262 IF_APPEND(&ifp
->if_snd
, mb
);
264 // DEVICE_DEBUGOUT("ipro1000_write() 4");
266 // wait for output available
267 while (ifp
->if_flags
& IFF_OACTIVE
) {
270 return B_INTERRUPTED
;
273 // DEVICE_DEBUGOUT("ipro1000_write() 5");
275 // send everything (if still required)
276 if (ifp
->if_snd
.ifq_head
!= NULL
)
279 // while (ifp->if_snd.ifq_head != NULL) {
280 // ifp->if_start(ifp);
281 // if (ifp->if_snd.ifq_head != NULL) {
283 // if (device->closed)
284 // return B_INTERRUPTED;
288 // t = system_time() - t;
291 // DEVICE_DEBUGOUT("write %Ld", t);
293 // DEVICE_DEBUGOUT("ipro1000_write() finished");
299 static struct ifnet
*
300 device_ifp(ipro1000_device
*device
)
302 return &device
->adapter
->interface_data
.ac_if
;
307 ipro1000_control(void *cookie
, uint32 op
, void *arg
, size_t len
)
309 ipro1000_device
*device
= (ipro1000_device
*)cookie
;
313 DEVICE_DEBUGOUT("ipro1000_control() ETHER_INIT");
317 DEVICE_DEBUGOUT("ipro1000_control() ETHER_GETADDR");
318 memcpy(arg
, &device
->macaddr
, sizeof(device
->macaddr
));
323 DEVICE_DEBUGOUT("non blocking mode on");
324 device
->nonblocking
= true;
326 DEVICE_DEBUGOUT("non blocking mode off");
327 device
->nonblocking
= false;
334 struct ifnet
*ifp
= device_ifp(device
);
335 struct sockaddr_dl address
;
337 if (len
!= ETHER_ADDR_LEN
)
340 memset(&address
, 0, sizeof(address
));
341 address
.sdl_family
= AF_LINK
;
342 memcpy(LLADDR(&address
), arg
, ETHER_ADDR_LEN
);
344 if (op
== ETHER_ADDMULTI
)
345 return ether_add_multi(ifp
, (struct sockaddr
*)&address
);
347 return ether_rem_multi(ifp
, (struct sockaddr
*)&address
);
350 case ETHER_SETPROMISC
:
352 DEVICE_DEBUGOUT("promiscuous mode on not supported");
354 DEVICE_DEBUGOUT("promiscuous mode off");
358 case ETHER_GETFRAMESIZE
:
359 DEVICE_DEBUGOUT2("ipro1000_control() ETHER_GETFRAMESIZE, framesize = %d (MTU = %d)", device
->maxframesize
, device
->maxframesize
- ENET_HEADER_SIZE
);
360 *(uint32
*)arg
= device
->maxframesize
;
363 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
364 case ETHER_GET_LINK_STATE
:
366 struct ifmediareq mediareq
;
367 ether_link_state_t state
;
369 if (len
< sizeof(ether_link_state_t
))
372 em_media_status(device_ifp(device
), &mediareq
);
374 state
.media
= mediareq
.ifm_active
;
375 if (mediareq
.ifm_status
& IFM_ACTIVE
)
376 state
.media
|= IFM_ACTIVE
;
377 if (mediareq
.ifm_active
& IFM_10_T
)
378 state
.speed
= 10000000;
379 else if (mediareq
.ifm_active
& IFM_100_TX
)
380 state
.speed
= 100000000;
382 state
.speed
= 1000000000;
383 state
.quality
= 1000;
385 return user_memcpy(arg
, &state
, sizeof(ether_link_state_t
));
388 case ETHER_SET_LINK_STATE_SEM
:
390 if (user_memcpy(&device
->linkChangeSem
, arg
, sizeof(sem_id
)) < B_OK
) {
391 device
->linkChangeSem
= -1;
392 return B_BAD_ADDRESS
;
399 DEVICE_DEBUGOUT("ipro1000_control() Invalid command");