source: mainline/uspace/drv/nic/rtl8139/driver.c@ a1347a7

lfn serial ticket/834-toolchain-update topic/fix-logger-deadlock topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a1347a7 was 6d8455d, checked in by Jiri Svoboda <jiri@…>, 14 years ago

Eliminate packet_t from sending direction of NIC interface.

  • Property mode set to 100644
File size: 57.9 KB
Line 
1/*
2 * Copyright (c) 2011 Jiri Michalec
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <assert.h>
30#include <errno.h>
31#include <align.h>
32#include <byteorder.h>
33#include <libarch/ddi.h>
34#include <libarch/barrier.h>
35
36#include <as.h>
37#include <ddf/log.h>
38#include <ddf/interrupt.h>
39#include <io/log.h>
40#include <nic.h>
41#include <packet_client.h>
42#include <device/pci.h>
43
44#include <ipc/irc.h>
45#include <sysinfo.h>
46#include <ipc/ns.h>
47
48#include <net_checksum.h>
49
50#include <str.h>
51
52#include "defs.h"
53#include "driver.h"
54#include "general.h"
55
56/** Global mutex for work with shared irq structure */
57FIBRIL_MUTEX_INITIALIZE(irq_reg_lock);
58/** Lock interrupt structure mutex */
59#define RTL8139_IRQ_STRUCT_LOCK() fibril_mutex_lock(&irq_reg_lock)
60/** Unlock interrupt structure mutex */
61#define RTL8139_IRQ_STRUCT_UNLOCK() fibril_mutex_unlock(&irq_reg_lock)
62
63/** PCI clock frequency in kHz */
64#define RTL8139_PCI_FREQ_KHZ 33000
65
66#define RTL8139_AUTONEG_CAPS (ETH_AUTONEG_10BASE_T_HALF \
67 | ETH_AUTONEG_10BASE_T_FULL | ETH_AUTONEG_100BASE_TX_HALF \
68 | ETH_AUTONEG_100BASE_TX_FULL | ETH_AUTONEG_PAUSE_SYMETRIC)
69
70/** Lock transmitter and receiver data
71 * This function shall be called whenever both transmitter and receiver locking
72 * to force safe lock ordering (deadlock prevention)
73 *
74 * @param rtl8139 RTL8139 private data
75 */
76inline static void rtl8139_lock_all(rtl8139_t *rtl8139)
77{
78 assert(rtl8139);
79 fibril_mutex_lock(&rtl8139->tx_lock);
80 fibril_mutex_lock(&rtl8139->rx_lock);
81}
82
83/** Unlock transmitter and receiver data
84 *
85 * @param rtl8139 RTL8139 private data
86 */
87inline static void rtl8139_unlock_all(rtl8139_t *rtl8139)
88{
89 assert(rtl8139);
90 fibril_mutex_unlock(&rtl8139->rx_lock);
91 fibril_mutex_unlock(&rtl8139->tx_lock);
92}
93
94#ifndef RXBUF_SIZE_FLAGS
95 /** Flags for receiver buffer - 16kB default */
96 #define RXBUF_SIZE_FLAGS RTL8139_RXFLAGS_SIZE_16
97#endif
98
99#if (RXBUF_SIZE_FLAGS > RTL8139_RXFLAGS_SIZE_64) || (RXBUF_SIZE_FLAGS < 0)
100 #error Bad receiver buffer flags size flags
101#endif
102
103/** Size of the receiver buffer
104 *
105 * Incrementing flags by one twices the buffer size
106 * the lowest size is 8*1024 (flags = 0)
107 */
108#define RxBUF_SIZE RTL8139_RXSIZE(RXBUF_SIZE_FLAGS)
109
110/** Total size of the receiver buffer to allocate */
111#define RxBUF_TOT_LENGTH RTL8139_RXBUF_LENGTH(RXBUF_SIZE_FLAGS)
112
113
114/** Default interrupt mask */
115#define RTL_DEFAULT_INTERRUPTS UINT16_C(0xFFFF)
116
117/** Obtain the value of the register part
118 * The bit operations will be done
119 * The _SHIFT and _MASK for the register part must exists as macros
120 * or variables
121 */
122#define REG_GET_VAL(value, reg_part)\
123 (((value) >> reg_part##_SHIFT) & reg_part##_MASK)
124
125
126/** Disable interrupts on controller
127 *
128 * @param rtl8139 The card private structure
129 */
130inline static void rtl8139_hw_int_disable(rtl8139_t *rtl8139)
131{
132 pio_write_16(rtl8139->io_port + IMR, 0x0);
133}
134/** Enable interrupts on controller
135 *
136 * @param rtl8139 The card private structure
137 */
138inline static void rtl8139_hw_int_enable(rtl8139_t *rtl8139)
139{
140 pio_write_16(rtl8139->io_port + IMR, rtl8139->int_mask);
141}
142
143/** Check on the controller if the receiving buffer is empty
144 *
145 * @param rtl8139 The controller data
146 *
147 * @return Nonzero if empty, zero otherwise
148 */
149inline static int rtl8139_hw_buffer_empty(rtl8139_t *rtl8139)
150{
151 return pio_read_16(rtl8139->io_port + CR) & CR_BUFE;
152}
153
154/** Update the mask of accepted packets in the RCR register according to
155 * rcr_accept_mode value in rtl8139_t
156 *
157 * @param rtl8139 The rtl8139 private data
158 */
159static void rtl8139_hw_update_rcr(rtl8139_t *rtl8139)
160{
161 uint32_t rcr = rtl8139->rcr_data.rcr_base | rtl8139->rcr_data.ucast_mask
162 | rtl8139->rcr_data.mcast_mask | rtl8139->rcr_data.bcast_mask
163 | rtl8139->rcr_data.defect_mask |
164 (RXBUF_SIZE_FLAGS << RCR_RBLEN_SHIFT);
165
166 ddf_msg(LVL_DEBUG, "Rewriting rcr: %x -> %x", pio_read_32(rtl8139->io_port + RCR),
167 rcr);
168
169 pio_write_32(rtl8139->io_port + RCR, rcr);
170}
171
172/** Fill the mask of accepted multicast packets in the card registers
173 *
174 * @param rtl8139 The rtl8139 private data
175 * @param mask The mask to set
176 */
177inline static void rtl8139_hw_set_mcast_mask(rtl8139_t *rtl8139,
178 uint64_t mask)
179{
180 pio_write_32(rtl8139->io_port + MAR0, (uint32_t) mask);
181 pio_write_32(rtl8139->io_port + MAR0 + sizeof(uint32_t),
182 (uint32_t)(mask >> 32));
183 return;
184}
185
186#include <device/pci.h>
187
188/** Set PmEn (Power management enable) bit value
189 *
190 * @param rtl8139 rtl8139 card data
191 * @param bit_val If bit_val is zero pmen is set to 0, otherwise pmen is set to 1
192 */
193inline static void rtl8139_hw_pmen_set(rtl8139_t *rtl8139, uint8_t bit_val)
194{
195 uint8_t config1 = pio_read_8(rtl8139->io_port + CONFIG1);
196 uint8_t config1_new;
197 if (bit_val)
198 config1_new = config1 | CONFIG1_PMEn;
199 else
200 config1_new = config1 & ~(uint8_t)(CONFIG1_PMEn);
201
202 if (config1_new == config1)
203 return;
204
205 rtl8139_regs_unlock(rtl8139->io_port);
206 pio_write_8(rtl8139->io_port + CONFIG1, config1_new);
207 rtl8139_regs_lock(rtl8139->io_port);
208
209 if (bit_val) {
210 async_sess_t *pci_sess =
211 nic_get_ddf_dev(rtl8139->nic_data)->parent_sess;
212 uint8_t pmen;
213 pci_config_space_read_8(pci_sess, 0x55, &pmen);
214 pci_config_space_write_8(pci_sess, 0x55, pmen | 1 | (1 << 7));
215 } else {
216 async_sess_t *pci_sess =
217 nic_get_ddf_dev(rtl8139->nic_data)->parent_sess;
218 uint8_t pmen;
219 pci_config_space_read_8(pci_sess, 0x55, &pmen);
220 pci_config_space_write_8(pci_sess, 0x55, pmen & ~(1 | (1 << 7)));
221 }
222}
223
224/** Get MAC address of the RTL8139 adapter
225 *
226 * @param rtl8139 The RTL8139 device
227 * @param address The place to store the address
228 *
229 * @return EOK if succeed, negative error code otherwise
230 */
231inline static void rtl8139_hw_get_addr(rtl8139_t *rtl8139,
232 nic_address_t *addr)
233{
234 assert(rtl8139);
235 assert(addr);
236
237 uint32_t *mac0_dest = (uint32_t *)addr->address;
238 uint16_t *mac4_dest = (uint16_t *)(addr->address + 4);
239
240 /* Read MAC address from the i/o (4byte + 2byte reads) */
241 *mac0_dest = pio_read_32(rtl8139->io_port + MAC0);
242 *mac4_dest = pio_read_16(rtl8139->io_port + MAC0 + 4);
243};
244
245/** Set MAC address to the device
246 *
247 * @param rtl8139 Controller private structure
248 * @param addr The address to set
249 */
250static void rtl8139_hw_set_addr(rtl8139_t *rtl8139, const nic_address_t *addr)
251{
252 assert(rtl8139);
253 assert(addr);
254
255 const uint32_t *val1 = (const uint32_t*)addr->address;
256 const uint16_t *val2 = (const uint16_t*)(addr->address + sizeof(uint32_t));
257
258 rtl8139_regs_unlock(rtl8139->io_port);
259 pio_write_32(rtl8139->io_port + MAC0, *val1);
260 pio_write_32(rtl8139->io_port + MAC0 + 4, *val2);
261 rtl8139_regs_lock(rtl8139->io_port);
262}
263
264/** Provide OR in the 8bit register (set selected bits to 1)
265 *
266 * @param rtl8139 The rtl8139 structure
267 * @param reg_offset Register offset in the device IO space
268 * @param bits_add The value to or
269 */
270inline static void rtl8139_hw_reg_add_8(rtl8139_t * rtl8139, size_t reg_offset,
271 uint8_t bits_add)
272{
273 uint8_t value = pio_read_8(rtl8139->io_port + reg_offset);
274 value |= bits_add;
275 pio_write_8(rtl8139->io_port + reg_offset, value);
276}
277
278/** Provide OR in the 32bit register (set selected bits to 1)
279 *
280 * @param rtl8139 The rtl8139 structure
281 * @param reg_offset Register offset in the device IO space
282 * @param bits_add The value to or
283 */
284inline static void rtl8139_hw_reg_add_32(rtl8139_t * rtl8139, size_t reg_offset,
285 uint32_t bits_add)
286{
287 uint32_t value = pio_read_32(rtl8139->io_port + reg_offset);
288 value |= bits_add;
289 pio_write_32(rtl8139->io_port + reg_offset, value);
290}
291
292/** Unset selected bits in 8bit register
293 *
294 * @param rtl8139 The rtl8139 structure
295 * @param reg_offset Register offset in the device IO space
296 * @param bits_add The mask of bits to remove
297 */
298inline static void rtl8139_hw_reg_rem_8(rtl8139_t * rtl8139, size_t reg_offset,
299 uint8_t bits_add)
300{
301 uint8_t value = pio_read_8(rtl8139->io_port + reg_offset);
302 value &= ~bits_add;
303 pio_write_8(rtl8139->io_port + reg_offset, value);
304}
305
306/** Unset selected bits in 32bit register
307 *
308 * @param rtl8139 The rtl8139 structure
309 * @param reg_offset Register offset in the device IO space
310 * @param bits_add The mask of bits to remove
311 */
312inline static void rtl8139_hw_reg_rem_32(rtl8139_t * rtl8139, size_t reg_offset,
313 uint32_t bits_add)
314{
315 uint32_t value = pio_read_32(rtl8139->io_port + reg_offset);
316 value &= ~bits_add;
317 pio_write_32(rtl8139->io_port + reg_offset, value);
318}
319
320
321static int rtl8139_set_addr(ddf_fun_t *fun, const nic_address_t *);
322static int rtl8139_get_device_info(ddf_fun_t *fun, nic_device_info_t *info);
323static int rtl8139_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state);
324static int rtl8139_get_operation_mode(ddf_fun_t *fun, int *speed,
325 nic_channel_mode_t *duplex, nic_role_t *role);
326static int rtl8139_set_operation_mode(ddf_fun_t *fun, int speed,
327 nic_channel_mode_t duplex, nic_role_t);
328
329static int rtl8139_pause_get(ddf_fun_t*, nic_result_t*, nic_result_t*,
330 uint16_t *);
331static int rtl8139_pause_set(ddf_fun_t*, int, int, uint16_t);
332
333static int rtl8139_autoneg_enable(ddf_fun_t *fun, uint32_t advertisement);
334static int rtl8139_autoneg_disable(ddf_fun_t *fun);
335static int rtl8139_autoneg_probe(ddf_fun_t *fun, uint32_t *our_advertisement,
336 uint32_t *their_advertisement, nic_result_t *result,
337 nic_result_t *their_result);
338static int rtl8139_autoneg_restart(ddf_fun_t *fun);
339
340static int rtl8139_defective_get_mode(ddf_fun_t *fun, uint32_t *mode);
341static int rtl8139_defective_set_mode(ddf_fun_t *fun, uint32_t mode);
342
343static int rtl8139_wol_virtue_add(nic_t *nic_data,
344 const nic_wol_virtue_t *virtue);
345static void rtl8139_wol_virtue_rem(nic_t *nic_data,
346 const nic_wol_virtue_t *virtue);
347
348static int rtl8139_poll_mode_change(nic_t *nic_data, nic_poll_mode_t mode,
349 const struct timeval *period);
350static void rtl8139_poll(nic_t *nic_data);
351
352/** Network interface options for RTL8139 card driver */
353static nic_iface_t rtl8139_nic_iface = {
354 .set_address = &rtl8139_set_addr,
355 .get_device_info = &rtl8139_get_device_info,
356 .get_cable_state = &rtl8139_get_cable_state,
357 .get_operation_mode = &rtl8139_get_operation_mode,
358 .set_operation_mode = &rtl8139_set_operation_mode,
359
360 .get_pause = &rtl8139_pause_get,
361 .set_pause = &rtl8139_pause_set,
362
363 .autoneg_enable = &rtl8139_autoneg_enable,
364 .autoneg_disable = &rtl8139_autoneg_disable,
365 .autoneg_probe = &rtl8139_autoneg_probe,
366 .autoneg_restart = &rtl8139_autoneg_restart,
367
368 .defective_get_mode = &rtl8139_defective_get_mode,
369 .defective_set_mode = &rtl8139_defective_set_mode,
370};
371
372/** Basic device operations for RTL8139 driver */
373static ddf_dev_ops_t rtl8139_dev_ops;
374
375static int rtl8139_dev_add(ddf_dev_t *dev);
376
377/** Basic driver operations for RTL8139 driver */
378static driver_ops_t rtl8139_driver_ops = {
379 .dev_add = &rtl8139_dev_add,
380};
381
382/** Driver structure for RTL8139 driver */
383static driver_t rtl8139_driver = {
384 .name = NAME,
385 .driver_ops = &rtl8139_driver_ops
386};
387
388/* The default implementation callbacks */
389static int rtl8139_on_activated(nic_t *nic_data);
390static int rtl8139_on_stopped(nic_t *nic_data);
391static void rtl8139_send_frame(nic_t *nic_data, void *data, size_t size);
392
393/** Check if the transmit buffer is busy */
394#define rtl8139_tbuf_busy(tsd) ((pio_read_32(tsd) & TSD_OWN) == 0)
395
396/** Send packet with the hardware
397 *
398 * note: the main_lock is locked when framework calls this function
399 *
400 * @param nic_data The nic driver data structure
401 * @param data Frame data
402 * @param size Frame size in bytes
403 *
404 * @return EOK if succeed, error code in the case of error
405 */
406static void rtl8139_send_frame(nic_t *nic_data, void *data, size_t size)
407{
408 assert(nic_data);
409
410 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
411 assert(rtl8139);
412 ddf_msg(LVL_DEBUG, "Sending frame");
413
414 if (size > RTL8139_PACKET_MAX_LENGTH) {
415 ddf_msg(LVL_ERROR, "Send frame: frame too long, %zu bytes",
416 size);
417 nic_report_send_error(rtl8139->nic_data, NIC_SEC_OTHER, 1);
418 goto err_size;
419 }
420
421 assert((size & TSD_SIZE_MASK) == size);
422
423 /* Lock transmitter structure for obtaining next buffer */
424 fibril_mutex_lock(&rtl8139->tx_lock);
425
426 /* Check if there is free buffer */
427 if (rtl8139->tx_next - TX_BUFF_COUNT == rtl8139->tx_used) {
428 nic_set_tx_busy(nic_data, 1);
429 fibril_mutex_unlock(&rtl8139->tx_lock);
430 nic_report_send_error(nic_data, NIC_SEC_BUFFER_FULL, 1);
431 goto err_busy_no_inc;
432 }
433
434 /* Get buffer id to use and set next buffer to use */
435 size_t tx_curr = rtl8139->tx_next++ % TX_BUFF_COUNT;
436
437 fibril_mutex_unlock(&rtl8139->tx_lock);
438
439 /* Get address of the buffer descriptor and packet data */
440 void *tsd = rtl8139->io_port + TSD0 + tx_curr * 4;
441 void *buf_addr = rtl8139->tx_buff[tx_curr];
442
443 /* Wait until the buffer is free */
444 assert(!rtl8139_tbuf_busy(tsd));
445
446 /* Write frame data to the buffer, set the size to TSD and clear OWN bit */
447 memcpy(buf_addr, data, size);
448
449 /* Set size of the data to send */
450 uint32_t tsd_value = pio_read_32(tsd);
451 tsd_value = rtl8139_tsd_set_size(tsd_value, size);
452 pio_write_32(tsd, tsd_value);
453
454 /* barrier for HW to really see the current buffer data */
455 write_barrier();
456
457 tsd_value &= ~(uint32_t)TSD_OWN;
458 pio_write_32(tsd, tsd_value);
459 return;
460
461err_busy_no_inc:
462err_size:
463 return;
464};
465
466
467/** Reset the controller
468 *
469 * @param io_base The address of the i/o port mapping start
470 */
471inline static void rtl8139_hw_soft_reset(void *io_base)
472{
473 pio_write_8(io_base + CR, CR_RST);
474 memory_barrier();
475 while(pio_read_8(io_base + CR) & CR_RST) {
476 usleep(1);
477 read_barrier();
478 }
479}
480
481/** Provide soft reset of the controller
482 *
483 * The caller must lock tx_lock and rx_lock before calling this function
484 *
485 */
486static void rtl8139_soft_reset(rtl8139_t *rtl8139)
487{
488 assert(rtl8139);
489
490 rtl8139_hw_soft_reset(rtl8139->io_port);
491 nic_t *nic_data = rtl8139->nic_data;
492
493 /* Write MAC address to the card */
494 nic_address_t addr;
495 nic_query_address(nic_data, &addr);
496 rtl8139_hw_set_addr(rtl8139, &addr);
497
498 /* Recover accept modes back */
499 rtl8139_hw_set_mcast_mask(rtl8139, nic_query_mcast_hash(nic_data));
500 rtl8139_hw_update_rcr(rtl8139);
501
502 rtl8139->tx_used = 0;
503 rtl8139->tx_next = 0;
504 nic_set_tx_busy(rtl8139->nic_data, 0);
505}
506
507/** Create packet structure from the buffer data
508 *
509 * @param nic_data NIC driver data
510 * @param rx_buffer The receiver buffer
511 * @param rx_size The buffer size
512 * @param packet_start The offset where packet data start
513 * @param packet_size The size of the packet data
514 *
515 * @return The packet list node (not connected)
516 */
517static nic_frame_t *rtl8139_read_packet(nic_t *nic_data,
518 void *rx_buffer, size_t rx_size, size_t packet_start, size_t packet_size)
519{
520 nic_frame_t *frame = nic_alloc_frame(nic_data, packet_size);
521 if (! frame) {
522 ddf_msg(LVL_ERROR, "Can not allocate frame for received packet.");
523 return NULL;
524 }
525
526 void *packet_data = packet_suffix(frame->packet, packet_size);
527 if (!packet_data) {
528 ddf_msg(LVL_ERROR, "Can not get the packet suffix.");
529 nic_release_frame(nic_data, frame);
530 return NULL;
531 }
532
533 void *ret = rtl8139_memcpy_wrapped(packet_data, rx_buffer, packet_start,
534 RxBUF_SIZE, packet_size);
535 if (ret == NULL) {
536 nic_release_frame(nic_data, frame);
537 return NULL;
538 }
539 return frame;
540}
541
542/* Reset receiver
543 *
544 * Use in the case of receiver error (lost in the rx_buff)
545 *
546 * @param rtl8139 controller private data
547 */
548static void rtl8139_rx_reset(rtl8139_t *rtl8139)
549{
550 /* Disable receiver, update offset and enable receiver again */
551 uint8_t cr = pio_read_8(rtl8139->io_port + CR);
552 rtl8139_regs_unlock(rtl8139);
553
554 pio_write_8(rtl8139->io_port + CR, cr & ~(uint8_t)CR_RE);
555
556 write_barrier();
557 pio_write_32(rtl8139->io_port + CAPR, 0);
558 pio_write_32(rtl8139->io_port + RBSTART,
559 PTR2U32(rtl8139->rx_buff_phys));
560
561 write_barrier();
562
563 rtl8139_hw_update_rcr(rtl8139);
564 pio_write_8(rtl8139->io_port + CR, cr);
565 rtl8139_regs_lock(rtl8139);
566
567 nic_report_receive_error(rtl8139->nic_data, NIC_REC_OTHER, 1);
568}
569
570/** Receive all packets in queue
571 *
572 * @param nic_data The controller data
573 * @return The linked list of packet_list_t nodes, each containing one packet
574 */
575static nic_frame_list_t *rtl8139_packet_receive(nic_t *nic_data)
576{
577 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
578 if (rtl8139_hw_buffer_empty(rtl8139))
579 return NULL;
580
581 nic_frame_list_t *frames = nic_alloc_frame_list();
582 if (!frames)
583 ddf_msg(LVL_ERROR, "Can not allocate frame list for received packets.");
584
585 void *rx_buffer = rtl8139->rx_buff_virt;
586
587 /* where to start reading */
588 uint16_t rx_offset = pio_read_16(rtl8139->io_port + CAPR) + 16;
589 /* unread bytes count */
590 uint16_t bytes_received = pio_read_16(rtl8139->io_port + CBA);
591 uint16_t max_read;
592 uint16_t cur_read = 0;
593
594 /* get values to the <0, buffer size) */
595 bytes_received %= RxBUF_SIZE;
596 rx_offset %= RxBUF_SIZE;
597
598 /* count how many bytes to read maximaly */
599 if (bytes_received < rx_offset)
600 max_read = bytes_received + (RxBUF_SIZE - rx_offset);
601 else
602 max_read = bytes_received - rx_offset;
603
604 memory_barrier();
605 while (!rtl8139_hw_buffer_empty(rtl8139)) {
606 void *rx_ptr = rx_buffer + rx_offset % RxBUF_SIZE;
607 uint32_t packet_header = uint32_t_le2host( *((uint32_t*)rx_ptr) );
608 uint16_t size = packet_header >> 16;
609 uint16_t packet_size = size - RTL8139_CRC_SIZE;
610 /* received packet flags in packet header */
611 uint16_t rcs = (uint16_t) packet_header;
612
613 if (size == RTL8139_EARLY_SIZE) {
614 /* The packet copying is still in progress, break receiving */
615 ddf_msg(LVL_DEBUG, "Early threshold reached, not completely coppied");
616 break;
617 }
618
619 /* Check if the header is valid, otherwise we are lost in the buffer */
620 if (size == 0 || size > RTL8139_PACKET_MAX_LENGTH) {
621 ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (size: %4"PRIu16", "
622 "header 0x%4"PRIx16". Offset: %zu)", size, packet_header,
623 rx_offset);
624 goto rx_err;
625 }
626 if (size < RTL8139_RUNT_MAX_SIZE && !(rcs & RSR_RUNT)) {
627 ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (%"PRIx16")", size);
628 goto rx_err;
629 }
630
631 cur_read += size + RTL_PACKET_HEADER_SIZE;
632 if (cur_read > max_read)
633 break;
634
635 if (frames) {
636 nic_frame_t *frame = rtl8139_read_packet(nic_data, rx_buffer,
637 RxBUF_SIZE, rx_offset + RTL_PACKET_HEADER_SIZE, packet_size);
638
639 if (frame)
640 nic_frame_list_append(frames, frame);
641 }
642
643 /* Update offset */
644 rx_offset = ALIGN_UP(rx_offset + size + RTL_PACKET_HEADER_SIZE, 4);
645
646 /* Write lesser value to prevent overflow into unread packet
647 * (the recomendation from the RealTech rtl8139 programming guide)
648 */
649 uint16_t capr_val = rx_offset - 16;
650 pio_write_16(rtl8139->io_port + CAPR, capr_val);
651
652 /* Ensure no CR read optimalization during next empty buffer test */
653 memory_barrier();
654 }
655 return frames;
656rx_err:
657 rtl8139_rx_reset(rtl8139);
658 return frames;
659};
660
661
662
663/** Commands to deal with interrupt
664 *
665 * Read ISR, check if tere is any interrupt pending.
666 * If so, reset it and accept the interrupt.
667 * The .addr of the first and third command must
668 * be filled to the ISR port address
669 */
670irq_cmd_t rtl8139_irq_commands[] = {
671 {
672 /* Get the interrupt status */
673 .cmd = CMD_PIO_READ_16,
674 .addr = NULL,
675 .dstarg = 2
676 },
677 {
678 .cmd = CMD_PREDICATE,
679 .value = 3,
680 .srcarg = 2
681 },
682 {
683 /* Mark interrupts as solved */
684 .cmd = CMD_PIO_WRITE_16,
685 .addr = NULL,
686 .value = 0xFFFF
687 },
688 {
689 /* Disable interrupts until interrupt routine is finished */
690 .cmd = CMD_PIO_WRITE_16,
691 .addr = NULL,
692 .value = 0x0000
693 },
694 {
695 .cmd = CMD_ACCEPT
696 }
697};
698
699/** Interrupt code definition */
700irq_code_t rtl8139_irq_code = {
701 .cmdcount = sizeof(rtl8139_irq_commands)/sizeof(irq_cmd_t),
702 .cmds = rtl8139_irq_commands
703};
704
705/** Deal with transmitter interrupt
706 *
707 * @param nic_data Nic driver data
708 */
709static void rtl8139_tx_interrupt(nic_t *nic_data)
710{
711 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
712
713 fibril_mutex_lock(&rtl8139->tx_lock);
714
715 size_t tx_next = rtl8139->tx_next;
716 size_t tx_used = rtl8139->tx_used;
717 while (tx_used != tx_next) {
718 size_t desc_to_check = tx_used % TX_BUFF_COUNT;
719 void * tsd_to_check = rtl8139->io_port + TSD0
720 + desc_to_check * sizeof(uint32_t);
721 uint32_t tsd_value = pio_read_32(tsd_to_check);
722
723 /* If sending is still in the progress */
724 if ((tsd_value & TSD_OWN) == 0)
725 break;
726
727 tx_used++;
728
729 /* If the packet was sent */
730 if (tsd_value & TSD_TOK) {
731 size_t size = REG_GET_VAL(tsd_value, TSD_SIZE);
732 nic_report_send_ok(nic_data, 1, size);
733 } else if (tsd_value & TSD_CRS) {
734 nic_report_send_error(nic_data, NIC_SEC_CARRIER_LOST, 1);
735 } else if (tsd_value & TSD_OWC) {
736 nic_report_send_error(nic_data, NIC_SEC_WINDOW_ERROR, 1);
737 } else if (tsd_value & TSD_TABT) {
738 nic_report_send_error(nic_data, NIC_SEC_ABORTED, 1);
739 } else if (tsd_value & TSD_CDH) {
740 nic_report_send_error(nic_data, NIC_SEC_HEARTBEAT, 1);
741 }
742
743 unsigned collisions = REG_GET_VAL(tsd_value, TSD_NCC);
744 if (collisions > 0) {
745 nic_report_collisions(nic_data, collisions);
746 }
747
748 if (tsd_value & TSD_TUN) {
749 nic_report_send_error(nic_data, NIC_SEC_FIFO_OVERRUN, 1);
750 }
751 }
752 if (rtl8139->tx_used != tx_used) {
753 rtl8139->tx_used = tx_used;
754 nic_set_tx_busy(nic_data, 0);
755 }
756 fibril_mutex_unlock(&rtl8139->tx_lock);
757}
758
759/** Receive all packets from the buffer
760 *
761 * @param rtl8139 driver private data
762 */
763static void rtl8139_receive_packets(nic_t *nic_data)
764{
765 assert(nic_data);
766
767 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
768 assert(rtl8139);
769
770 fibril_mutex_lock(&rtl8139->rx_lock);
771 nic_frame_list_t *frames = rtl8139_packet_receive(nic_data);
772 fibril_mutex_unlock(&rtl8139->rx_lock);
773
774 if (frames)
775 nic_received_frame_list(nic_data, frames);
776}
777
778
779/** Deal with poll interrupt
780 *
781 * @param nic_data Nic driver data
782 */
783static int rtl8139_poll_interrupt(nic_t *nic_data)
784{
785 assert(nic_data);
786
787 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
788 assert(rtl8139);
789
790 uint32_t timer_val;
791 int receive = rtl8139_timer_act_step(&rtl8139->poll_timer, &timer_val);
792
793 assert(timer_val);
794 pio_write_32(rtl8139->io_port + TIMERINT, timer_val);
795 pio_write_32(rtl8139->io_port + TCTR, 0x0);
796 ddf_msg(LVL_DEBUG, "rtl8139 timer: %"PRIu32"\treceive: %d", timer_val, receive);
797 return receive;
798}
799
800
801/** Poll device according to isr status
802 *
803 * The isr value must be obtained and cleared by the caller. The reason
804 * of this function separate is to allow polling from both interrupt
805 * (which clears controller ISR before the handler runs) and the polling
806 * callbacks.
807 *
808 * @param nic_data Driver data
809 * @param isr Interrupt status register value
810 */
811static void rtl8139_interrupt_impl(nic_t *nic_data, uint16_t isr)
812{
813 assert(nic_data);
814
815 nic_poll_mode_t poll_mode = nic_query_poll_mode(nic_data, 0);
816
817 /* Process only when should in the polling mode */
818 if (poll_mode == NIC_POLL_PERIODIC) {
819 int receive = 0;
820 if (isr & INT_TIME_OUT) {
821 receive = rtl8139_poll_interrupt(nic_data);
822 }
823 if (! receive)
824 return;
825 }
826
827 /* Check transmittion interrupts first to allow transmit next packets
828 * sooner
829 */
830 if (isr & (INT_TOK | INT_TER)) {
831 rtl8139_tx_interrupt(nic_data);
832 }
833 if (isr & INT_ROK) {
834 rtl8139_receive_packets(nic_data);
835 }
836 if (isr & (INT_RER | INT_RXOVW | INT_FIFOOVW)) {
837 if (isr & INT_RER) {
838 //TODO: is this only the general error, or any particular?
839 }
840 if (isr & (INT_FIFOOVW)) {
841 nic_report_receive_error(nic_data, NIC_REC_FIFO_OVERRUN, 1);
842 } else if (isr & (INT_RXOVW)) {
843 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
844 assert(rtl8139);
845
846 uint32_t miss = pio_read_32(rtl8139->io_port + MPC) & MPC_VMASK;
847 pio_write_32(rtl8139->io_port + MPC, 0);
848 nic_report_receive_error(nic_data, NIC_REC_BUFFER_OVERFLOW, miss);
849 }
850 }
851}
852
853/** Handle device interrupt
854 *
855 * @param dev The rtl8139 device
856 * @param iid The IPC call id
857 * @param icall The IPC call structure
858 */
859static void rtl8139_interrupt_handler(ddf_dev_t *dev, ipc_callid_t iid,
860 ipc_call_t *icall)
861{
862 assert(dev);
863 assert(icall);
864
865 uint16_t isr = (uint16_t) IPC_GET_ARG2(*icall);
866 nic_t *nic_data = nic_get_from_ddf_dev(dev);
867 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
868
869 rtl8139_interrupt_impl(nic_data, isr);
870
871 /* Turn the interrupts on again */
872 rtl8139_hw_int_enable(rtl8139);
873};
874
875/** Register interrupt handler for the card in the system
876 *
877 * Note: the global irq_reg_mutex is locked because of work with global
878 * structure.
879 *
880 * @param nic_data The driver data
881 *
882 * @return EOK if the handler was registered, negative error code otherwise
883 */
884inline static int rtl8139_register_int_handler(nic_t *nic_data)
885{
886 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
887
888 /* Lock the mutex in whole driver while working with global structure */
889 RTL8139_IRQ_STRUCT_LOCK();
890
891 rtl8139_irq_code.cmds[0].addr = rtl8139->io_port + ISR;
892 rtl8139_irq_code.cmds[2].addr = rtl8139->io_port + ISR;
893 rtl8139_irq_code.cmds[3].addr = rtl8139->io_port + IMR;
894 int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data),
895 rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code);
896
897 RTL8139_IRQ_STRUCT_UNLOCK();
898
899 return rc;
900}
901
902/** Start the controller
903 *
904 * The caller must lock tx_lock and rx_lock before calling this function
905 *
906 * @param rtl8139 The card private data
907 */
908inline static void rtl8139_card_up(rtl8139_t *rtl8139)
909{
910 void *io_base = rtl8139->io_port;
911 size_t i;
912
913 /* Wake up the device */
914 pio_write_8(io_base + CONFIG1, 0x00);
915 /* Reset the device */
916 rtl8139_soft_reset(rtl8139);
917
918 /* Write transmittion buffer addresses */
919 for(i = 0; i < TX_BUFF_COUNT; ++i) {
920 uint32_t addr = PTR2U32(rtl8139->tx_buff_phys + i*TX_BUFF_SIZE);
921 pio_write_32(io_base + TSAD0 + 4*i, addr);
922 }
923 rtl8139->tx_next = 0;
924 rtl8139->tx_used = 0;
925 nic_set_tx_busy(rtl8139->nic_data, 0);
926
927 pio_write_32(io_base + RBSTART, PTR2U32(rtl8139->rx_buff_phys));
928
929 /* Enable transmitter and receiver */
930 uint8_t cr_value = pio_read_8(io_base + CR);
931 pio_write_8(io_base + CR, cr_value | CR_TE | CR_RE);
932 rtl8139_hw_update_rcr(rtl8139);
933}
934
935/** Activate the device to receive and transmit packets
936 *
937 * @param nic_data The nic driver data
938 *
939 * @return EOK if activated successfully, error code otherwise
940 */
941static int rtl8139_on_activated(nic_t *nic_data)
942{
943 assert(nic_data);
944 ddf_msg(LVL_NOTE, "Activating device");
945
946 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
947 assert(rtl8139);
948
949 rtl8139_lock_all(rtl8139);
950 rtl8139_card_up(rtl8139);
951 rtl8139_unlock_all(rtl8139);
952
953 rtl8139->int_mask = RTL_DEFAULT_INTERRUPTS;
954 rtl8139_hw_int_enable(rtl8139);
955 nic_enable_interrupt(nic_data, rtl8139->irq);
956
957 ddf_msg(LVL_DEBUG, "Device activated, interrupt %d registered", rtl8139->irq);
958 return EOK;
959}
960
961/** Callback for NIC_STATE_STOPPED change
962 *
963 * @param nic_data The nic driver data
964 *
965 * @return EOK if succeed, error code otherwise
966 */
967static int rtl8139_on_stopped(nic_t *nic_data)
968{
969 assert(nic_data);
970
971 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
972 assert(rtl8139);
973
974 rtl8139->rcr_data.ucast_mask = RTL8139_RCR_UCAST_DEFAULT;
975 rtl8139->rcr_data.mcast_mask = RTL8139_RCR_MCAST_DEFAULT;
976 rtl8139->rcr_data.bcast_mask = RTL8139_RCR_BCAST_DEFAULT;
977 rtl8139->rcr_data.defect_mask = RTL8139_RCR_DEFECT_DEFAULT;
978
979 /* Reset the card to the initial state (interrupts, Tx and Rx disabled) */
980 rtl8139_lock_all(rtl8139);
981 rtl8139_soft_reset(rtl8139);
982 rtl8139_unlock_all(rtl8139);
983 return EOK;
984}
985
986
987static int rtl8139_unicast_set(nic_t *nic_data, nic_unicast_mode_t mode,
988 const nic_address_t *, size_t);
989static int rtl8139_multicast_set(nic_t *nic_data, nic_multicast_mode_t mode,
990 const nic_address_t *addr, size_t addr_count);
991static int rtl8139_broadcast_set(nic_t *nic_data, nic_broadcast_mode_t mode);
992
993
994/** Create driver data structure
995 *
996 * @return Intialized device data structure or NULL
997 */
998static rtl8139_t *rtl8139_create_dev_data(ddf_dev_t *dev)
999{
1000 assert(dev);
1001 assert(!nic_get_from_ddf_dev(dev));
1002
1003 nic_t *nic_data = nic_create_and_bind(dev);
1004 if (!nic_data)
1005 return NULL;
1006
1007 rtl8139_t *rtl8139 = malloc(sizeof(rtl8139_t));
1008 if (!rtl8139) {
1009 nic_unbind_and_destroy(dev);
1010 return NULL;
1011 }
1012
1013 bzero(rtl8139, sizeof(rtl8139_t));
1014
1015 rtl8139->nic_data = nic_data;
1016 nic_set_specific(nic_data, rtl8139);
1017 nic_set_send_frame_handler(nic_data, rtl8139_send_frame);
1018 nic_set_state_change_handlers(nic_data,
1019 rtl8139_on_activated, NULL, rtl8139_on_stopped);
1020 nic_set_filtering_change_handlers(nic_data,
1021 rtl8139_unicast_set, rtl8139_multicast_set, rtl8139_broadcast_set,
1022 NULL, NULL);
1023 nic_set_wol_virtue_change_handlers(nic_data,
1024 rtl8139_wol_virtue_add, rtl8139_wol_virtue_rem);
1025 nic_set_poll_handlers(nic_data, rtl8139_poll_mode_change, rtl8139_poll);
1026
1027
1028 fibril_mutex_initialize(&rtl8139->rx_lock);
1029 fibril_mutex_initialize(&rtl8139->tx_lock);
1030
1031 nic_set_wol_max_caps(nic_data, NIC_WV_BROADCAST, 1);
1032 nic_set_wol_max_caps(nic_data, NIC_WV_LINK_CHANGE, 1);
1033 nic_set_wol_max_caps(nic_data, NIC_WV_MAGIC_PACKET, 1);
1034
1035 return rtl8139;
1036}
1037
1038/** Clean up the rtl8139 device structure.
1039 *
1040 * @param dev The device structure.
1041 */
1042static void rtl8139_dev_cleanup(ddf_dev_t *dev)
1043{
1044 assert(dev);
1045
1046 if (dev->driver_data)
1047 nic_unbind_and_destroy(dev);
1048
1049 if (dev->parent_sess != NULL) {
1050 async_hangup(dev->parent_sess);
1051 dev->parent_sess = NULL;
1052 }
1053}
1054
1055/** Fill the irq and io_addr part of device data structure
1056 *
1057 * The hw_resources must be obtained before calling this function
1058 *
1059 * @param dev The device structure
1060 * @param hw_resources Devices hardware resources
1061 *
1062 * @return EOK if succeed, negative error code otherwise
1063 */
1064static int rtl8139_fill_resource_info(ddf_dev_t *dev, const hw_res_list_parsed_t
1065 *hw_resources)
1066{
1067 assert(dev);
1068 assert(hw_resources);
1069
1070 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_dev(dev));
1071 assert(rtl8139);
1072
1073 if (hw_resources->irqs.count != 1) {
1074 ddf_msg(LVL_ERROR, "%s device: unexpected irq count", dev->name);
1075 return EINVAL;
1076 };
1077 if (hw_resources->io_ranges.count != 1) {
1078 ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", dev->name);
1079 return EINVAL;
1080 }
1081
1082 rtl8139->irq = hw_resources->irqs.irqs[0];
1083 ddf_msg(LVL_DEBUG, "%s device: irq 0x%x assigned", dev->name, rtl8139->irq);
1084
1085 rtl8139->io_addr = IOADDR_TO_PTR(hw_resources->io_ranges.ranges[0].address);
1086 if (hw_resources->io_ranges.ranges[0].size < RTL8139_IO_SIZE) {
1087 ddf_msg(LVL_ERROR, "i/o range assigned to the device "
1088 "%s is too small.", dev->name);
1089 return EINVAL;
1090 }
1091 ddf_msg(LVL_DEBUG, "%s device: i/o addr %p assigned.", dev->name, rtl8139->io_addr);
1092
1093 return EOK;
1094}
1095
1096/** Obtain information about hardware resources of the device
1097 *
1098 * The device must be connected to the parent
1099 *
1100 * @param dev The device structure
1101 *
1102 * @return EOK if succeed, negative error code otherwise
1103 */
1104static int rtl8139_get_resource_info(ddf_dev_t *dev)
1105{
1106 assert(dev);
1107
1108 nic_t *nic_data = nic_get_from_ddf_dev(dev);
1109 assert(nic_data);
1110
1111 hw_res_list_parsed_t hw_res_parsed;
1112 hw_res_list_parsed_init(&hw_res_parsed);
1113
1114 /* Get hw resources form parent driver */
1115 int rc = nic_get_resources(nic_data, &hw_res_parsed);
1116 if (rc != EOK)
1117 return rc;
1118
1119 /* Fill resources information to the device */
1120 int ret = rtl8139_fill_resource_info(dev, &hw_res_parsed);
1121 hw_res_list_parsed_clean(&hw_res_parsed);
1122
1123 return ret;
1124}
1125
1126
1127/** Allocate buffers using DMA framework
1128 *
1129 * The buffers structures in the device specific data is filled
1130 *
1131 * @param data The device specific structure to fill
1132 *
1133 * @return EOK in the case of success, error code otherwise
1134 */
1135static int rtl8139_buffers_create(rtl8139_t *rtl8139)
1136{
1137 size_t i = 0;
1138 int rc;
1139
1140 ddf_msg(LVL_DEBUG, "Creating buffers");
1141
1142 rc = dmamem_map_anonymous(TX_PAGES * PAGE_SIZE, AS_AREA_WRITE, 0,
1143 &rtl8139->tx_buff_phys, &rtl8139->tx_buff_virt);
1144 if (rc != EOK) {
1145 ddf_msg(LVL_ERROR, "Can not allocate transmitter buffers.");
1146 goto err_tx_alloc;
1147 }
1148
1149 for (i = 0; i < TX_BUFF_COUNT; ++i)
1150 rtl8139->tx_buff[i] = rtl8139->tx_buff_virt + i * TX_BUFF_SIZE;
1151
1152 ddf_msg(LVL_DEBUG, "The transmittion buffers allocated");
1153
1154 /* Use the first buffer for next transmittion */
1155 rtl8139->tx_next = 0;
1156 rtl8139->tx_used = 0;
1157
1158 /* Allocate buffer for receiver */
1159 ddf_msg(LVL_DEBUG, "Allocating receiver buffer of the size %zu bytes",
1160 RxBUF_TOT_LENGTH);
1161
1162 rc = dmamem_map_anonymous(RxBUF_TOT_LENGTH, AS_AREA_READ, 0,
1163 &rtl8139->rx_buff_phys, &rtl8139->rx_buff_virt);
1164 if (rc != EOK) {
1165 ddf_msg(LVL_ERROR, "Can not allocate receive buffer.");
1166 goto err_rx_alloc;
1167 }
1168 ddf_msg(LVL_DEBUG, "The buffers created");
1169
1170 return EOK;
1171
1172err_rx_alloc:
1173 dmamem_unmap_anonymous(&rtl8139->tx_buff_virt);
1174err_tx_alloc:
1175 return rc;
1176}
1177
1178/** Initialize the rtl8139 device structure
1179 *
1180 * @param dev The device information
1181 *
1182 * @return EOK if succeed, negative error code otherwise
1183 */
1184static int rtl8139_device_initialize(ddf_dev_t *dev)
1185{
1186 ddf_msg(LVL_DEBUG, "rtl8139_dev_initialize %s", dev->name);
1187
1188 int ret = EOK;
1189
1190 ddf_msg(LVL_DEBUG, "rtl8139: creating device data");
1191
1192 /* Allocate driver data for the device. */
1193 rtl8139_t *rtl8139 = rtl8139_create_dev_data(dev);
1194 if (rtl8139 == NULL) {
1195 ddf_msg(LVL_ERROR, "Not enough memory for initializing %s.", dev->name);
1196 return ENOMEM;
1197 }
1198
1199 ddf_msg(LVL_DEBUG, "rtl8139: dev_data created");
1200
1201 /* Obtain and fill hardware resources info and connect to parent */
1202 ret = rtl8139_get_resource_info(dev);
1203 if (ret != EOK) {
1204 ddf_msg(LVL_ERROR, "Can not obatin hw resources information");
1205 goto failed;
1206 }
1207
1208 ddf_msg(LVL_DEBUG, "rtl8139: resource_info obtained");
1209
1210 /* Allocate DMA buffers */
1211 ret = rtl8139_buffers_create(rtl8139);
1212 if (ret != EOK)
1213 goto failed;
1214
1215 /* Set default packet acceptance */
1216 rtl8139->rcr_data.ucast_mask = RTL8139_RCR_UCAST_DEFAULT;
1217 rtl8139->rcr_data.mcast_mask = RTL8139_RCR_MCAST_DEFAULT;
1218 rtl8139->rcr_data.bcast_mask = RTL8139_RCR_BCAST_DEFAULT;
1219 rtl8139->rcr_data.defect_mask = RTL8139_RCR_DEFECT_DEFAULT;
1220 /* Set receiver early treshold to 8/16 of packet length */
1221 rtl8139->rcr_data.rcr_base = (0x8 << RCR_ERTH_SHIFT);
1222
1223 ddf_msg(LVL_DEBUG, "The device is initialized");
1224 return ret;
1225
1226failed:
1227 ddf_msg(LVL_ERROR, "The device initialization failed");
1228 rtl8139_dev_cleanup(dev);
1229 return ret;
1230}
1231
1232/** Enable the i/o ports of the device.
1233 *
1234 * @param dev The RTL8139 device.
1235 *
1236 * @return EOK if successed, negative error code otherwise
1237 */
1238static int rtl8139_pio_enable(ddf_dev_t *dev)
1239{
1240 ddf_msg(LVL_DEBUG, NAME ": rtl8139_pio_enable %s", dev->name);
1241
1242 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_dev(dev));
1243
1244 /* Gain control over port's registers. */
1245 if (pio_enable(rtl8139->io_addr, RTL8139_IO_SIZE, &rtl8139->io_port)) {
1246 ddf_msg(LVL_ERROR, "Cannot gain the port %lx for device %s.", rtl8139->io_addr,
1247 dev->name);
1248 return EADDRNOTAVAIL;
1249 }
1250
1251 return EOK;
1252}
1253
1254/** Initialize the driver private data according to the
1255 * device registers
1256 *
1257 * @param rtl8139 rtl8139 private data
1258 */
1259static void rtl8139_data_init(rtl8139_t *rtl8139)
1260{
1261 assert(rtl8139);
1262
1263 /* Check the version id */
1264 uint32_t tcr = pio_read_32(rtl8139->io_port + TCR);
1265 uint32_t hwverid = RTL8139_HWVERID(tcr);
1266 size_t i = 0;
1267 rtl8139->hw_version = RTL8139_VER_COUNT;
1268 for (i = 0; i < RTL8139_VER_COUNT; ++i) {
1269 if (rtl8139_versions[i].hwverid == 0)
1270 break;
1271
1272 if (rtl8139_versions[i].hwverid == hwverid) {
1273 rtl8139->hw_version = rtl8139_versions[i].ver_id;
1274 ddf_msg(LVL_NOTE, "HW version found: index %zu, ver_id %d (%s)", i,
1275 rtl8139_versions[i].ver_id, model_names[rtl8139->hw_version]);
1276 }
1277 }
1278}
1279
1280/** The add_device callback of RTL8139 callback
1281 *
1282 * Probe and initialize the newly added device.
1283 *
1284 * @param dev The RTL8139 device.
1285 *
1286 * @return EOK if added successfully, negative error code otherwise
1287 */
1288int rtl8139_dev_add(ddf_dev_t *dev)
1289{
1290 assert(dev);
1291 ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %d)", dev->name, dev->handle);
1292
1293 /* Init device structure for rtl8139 */
1294 int rc = rtl8139_device_initialize(dev);
1295 if (rc != EOK)
1296 return rc;
1297
1298 /* Map I/O ports */
1299 rc = rtl8139_pio_enable(dev);
1300 if (rc != EOK)
1301 goto err_destroy;
1302
1303 nic_t *nic_data = nic_get_from_ddf_dev(dev);
1304 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
1305
1306 nic_address_t addr;
1307 rtl8139_hw_get_addr(rtl8139, &addr);
1308 rc = nic_report_address(nic_data, &addr);
1309 if (rc != EOK)
1310 goto err_pio;
1311
1312 /* Initialize the driver private structure */
1313 rtl8139_data_init(rtl8139);
1314
1315 /* Register interrupt handler */
1316 rc = rtl8139_register_int_handler(nic_data);
1317 if (rc != EOK)
1318 goto err_pio;
1319
1320 rc = nic_connect_to_services(nic_data);
1321 if (rc != EOK) {
1322 ddf_msg(LVL_ERROR, "Failed to connect to services", rc);
1323 goto err_irq;
1324 }
1325
1326 rc = nic_register_as_ddf_fun(nic_data, &rtl8139_dev_ops);
1327 if (rc != EOK) {
1328 ddf_msg(LVL_ERROR, "Failed to register as DDF function - error %d", rc);
1329 goto err_irq;
1330 }
1331
1332 ddf_msg(LVL_NOTE, "The %s device has been successfully initialized.",
1333 dev->name);
1334
1335 return EOK;
1336
1337err_irq:
1338 unregister_interrupt_handler(dev, rtl8139->irq);
1339err_pio:
1340 // rtl8139_pio_disable(dev);
1341 /* TODO: find out if the pio_disable is needed */
1342err_destroy:
1343 rtl8139_dev_cleanup(dev);
1344 return rc;
1345};
1346
1347/** Set card MAC address
1348 *
1349 * @param device The RTL8139 device
1350 * @param address The place to store the address
1351 * @param max_len Maximal addresss length to store
1352 *
1353 * @return EOK if succeed, negative error code otherwise
1354 */
1355static int rtl8139_set_addr(ddf_fun_t *fun, const nic_address_t *addr)
1356{
1357 assert(fun);
1358 assert(addr);
1359
1360 nic_t *nic_data =nic_get_from_ddf_fun((fun));
1361 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
1362 assert(rtl8139);
1363
1364 rtl8139_lock_all(rtl8139);
1365
1366 int rc = nic_report_address(nic_data, addr);
1367 if ( rc != EOK) {
1368 rtl8139_unlock_all(rtl8139);
1369 return rc;
1370 }
1371
1372 rtl8139_hw_set_addr(rtl8139, addr);
1373
1374 rtl8139_unlock_all(rtl8139);
1375 return EOK;
1376}
1377
1378/** Get the device information
1379 *
1380 * @param dev The NIC device
1381 * @param info The information to fill
1382 *
1383 * @return EOK
1384 */
1385static int rtl8139_get_device_info(ddf_fun_t *fun, nic_device_info_t *info)
1386{
1387 assert(fun);
1388 assert(info);
1389
1390 nic_t *nic_data = nic_get_from_ddf_fun(fun);
1391 assert(nic_data);
1392 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
1393 assert(rtl8139);
1394
1395 /* TODO: fill the information more completely */
1396 info->vendor_id = 0x10ec;
1397 str_cpy(info->vendor_name, NIC_VENDOR_MAX_LENGTH, "Realtek");
1398
1399 if (rtl8139->hw_version < RTL8139_VER_COUNT) {
1400 str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH,
1401 model_names[rtl8139->hw_version]);
1402 } else {
1403 str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH, "RTL8139");
1404 }
1405
1406 info->ethernet_support[ETH_10M] = ETH_10BASE_T;
1407 info->ethernet_support[ETH_100M] = ETH_100BASE_TX;
1408
1409 info->autoneg_support = RTL8139_AUTONEG_CAPS;
1410 return EOK;
1411}
1412
1413/** Check the cable state
1414 *
1415 * @param[in] dev The device
1416 * @param[out] state The state to fill
1417 *
1418 * @return EOK
1419 */
1420static int rtl8139_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state)
1421{
1422 assert(fun);
1423 assert(state);
1424
1425 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1426 assert(rtl8139);
1427
1428 if (pio_read_16(rtl8139->io_port + CSCR) & CS_CON_STATUS) {
1429 *state = NIC_CS_PLUGGED;
1430 } else {
1431 *state = NIC_CS_UNPLUGGED;
1432 }
1433
1434 return EOK;
1435}
1436
1437/** Get operation mode of the device
1438 */
1439static int rtl8139_get_operation_mode(ddf_fun_t *fun, int *speed,
1440 nic_channel_mode_t *duplex, nic_role_t *role)
1441{
1442 assert(fun);
1443 assert(speed);
1444 assert(duplex);
1445 assert(role);
1446
1447 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1448 assert(rtl8139);
1449
1450 uint16_t bmcr_val = pio_read_16(rtl8139->io_port + BMCR);
1451 uint8_t msr_val = pio_read_8(rtl8139->io_port + MSR);
1452
1453 if (bmcr_val & BMCR_DUPLEX) {
1454 *duplex = NIC_CM_FULL_DUPLEX;
1455 } else {
1456 *duplex = NIC_CM_HALF_DUPLEX;
1457 }
1458
1459 if (msr_val & MSR_SPEED10) {
1460 *speed = 10;
1461 } else {
1462 *speed = 100;
1463 }
1464
1465 *role = NIC_ROLE_UNKNOWN;
1466 return EOK;
1467}
1468
1469/** Value validity */
1470enum access_mode {
1471 /** Value is invalid now */
1472 VALUE_INVALID = 0,
1473 /** Read-only */
1474 VALUE_RO,
1475 /** Read-write */
1476 VALUE_RW
1477};
1478
1479/** Check if pause packet operations are valid in current situation
1480 *
1481 * @param rtl8139 RTL8139 private structure
1482 *
1483 * @return VALUE_INVALID if the value has no sense in current moment
1484 * @return VALUE_RO if the state is read-only in current moment
1485 * @return VALUE_RW if the state can be modified
1486 */
1487static int rtl8139_pause_is_valid(rtl8139_t *rtl8139)
1488{
1489 assert(rtl8139);
1490
1491 uint16_t bmcr = pio_read_16(rtl8139->io_port + BMCR);
1492 if ((bmcr & (BMCR_AN_ENABLE | BMCR_DUPLEX)) == 0)
1493 return VALUE_INVALID;
1494
1495 if (bmcr & BMCR_AN_ENABLE) {
1496 uint16_t anar_lp = pio_read_16(rtl8139->io_port + ANLPAR);
1497 if (anar_lp & ANAR_PAUSE)
1498 return VALUE_RO;
1499 }
1500
1501 return VALUE_RW;
1502}
1503
1504/** Get current pause packet configuration
1505 *
1506 * Values are filled with NIC_RESULT_NOT_AVAILABLE if the value has no sense in
1507 * the moment (half-duplex).
1508 *
1509 * @param[in] fun The DDF structure of the RTL8139
1510 * @param[out] we_send Sign if local constroller sends pause packets
1511 * @param[out] we_receive Sign if local constroller receives pause packets
1512 * @param[out] time Time filled in pause packets. 0xFFFF in rtl8139
1513 *
1514 * @return EOK if succeed
1515 */
1516static int rtl8139_pause_get(ddf_fun_t *fun, nic_result_t *we_send,
1517 nic_result_t *we_receive, uint16_t *time)
1518{
1519 assert(fun);
1520 assert(we_send);
1521 assert(we_receive);
1522
1523 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1524 assert(rtl8139);
1525
1526 if (rtl8139_pause_is_valid(rtl8139) == VALUE_INVALID) {
1527 *we_send = NIC_RESULT_NOT_AVAILABLE;
1528 *we_receive = NIC_RESULT_NOT_AVAILABLE;
1529 *time = 0;
1530 return EOK;
1531 }
1532
1533 uint8_t msr = pio_read_8(rtl8139->io_port + MSR);
1534
1535 *we_send = (msr & MSR_TXFCE) ? NIC_RESULT_ENABLED : NIC_RESULT_DISABLED;
1536 *we_receive = (msr & MSR_RXFCE) ? NIC_RESULT_ENABLED : NIC_RESULT_DISABLED;
1537 *time = RTL8139_PAUSE_VAL;
1538
1539 return EOK;
1540};
1541
1542/** Set current pause packet configuration
1543 *
1544 * @param fun The DDF structure of the RTL8139
1545 * @param allow_send Sign if local constroller sends pause packets
1546 * @param allow_receive Sign if local constroller receives pause packets
1547 * @param time Time to use, ignored (not supported by device)
1548 *
1549 * @return EOK if succeed, INVAL if the pause packet has no sence
1550 */
1551static int rtl8139_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive,
1552 uint16_t time)
1553{
1554 assert(fun);
1555
1556 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1557 assert(rtl8139);
1558
1559 if (rtl8139_pause_is_valid(rtl8139) != VALUE_RW)
1560 return EINVAL;
1561
1562 uint8_t msr = pio_read_8(rtl8139->io_port + MSR);
1563 msr &= ~(uint8_t)(MSR_TXFCE | MSR_RXFCE);
1564
1565 if (allow_receive)
1566 msr |= MSR_RXFCE;
1567 if (allow_send)
1568 msr |= MSR_TXFCE;
1569
1570 pio_write_8(rtl8139->io_port + MSR, msr);
1571
1572 if (allow_send && time > 0) {
1573 ddf_msg(LVL_WARN, "Time setting is not supported in set_pause method.");
1574 }
1575 return EOK;
1576};
1577
1578/** Set operation mode of the device
1579 *
1580 */
1581static int rtl8139_set_operation_mode(ddf_fun_t *fun, int speed,
1582 nic_channel_mode_t duplex, nic_role_t role)
1583{
1584 assert(fun);
1585
1586 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1587 assert(rtl8139);
1588
1589 if (speed != 10 && speed != 100)
1590 return EINVAL;
1591 if (duplex != NIC_CM_HALF_DUPLEX && duplex != NIC_CM_FULL_DUPLEX)
1592 return EINVAL;
1593
1594 uint16_t bmcr_val = pio_read_16(rtl8139->io_port + BMCR);
1595
1596 /* Set autonegotion disabled */
1597 bmcr_val &= ~(uint16_t)BMCR_AN_ENABLE;
1598
1599 if (duplex == NIC_CM_FULL_DUPLEX) {
1600 bmcr_val |= BMCR_DUPLEX;
1601 } else {
1602 bmcr_val &= ~((uint16_t)BMCR_DUPLEX);
1603 }
1604
1605 if (speed == 100) {
1606 bmcr_val |= BMCR_Spd_100;
1607 } else {
1608 bmcr_val &= ~((uint16_t)BMCR_Spd_100);
1609 }
1610
1611 rtl8139_regs_unlock(rtl8139->io_port);
1612 pio_write_16(rtl8139->io_port + BMCR, bmcr_val);
1613 rtl8139_regs_lock(rtl8139->io_port);
1614 return EOK;
1615}
1616
1617/** Enable autonegoation with specific advertisement
1618 *
1619 * @param dev The device to update
1620 * @param advertisement The advertisement to set
1621 *
1622 * @returns EINVAL if the advertisement mode is not supproted
1623 * @returns EOK if advertisement mode set successfully
1624 */
1625static int rtl8139_autoneg_enable(ddf_fun_t *fun, uint32_t advertisement)
1626{
1627 assert(fun);
1628
1629 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1630 assert(rtl8139);
1631
1632 if (advertisement == 0) {
1633 advertisement = RTL8139_AUTONEG_CAPS;
1634 }
1635
1636 if ((advertisement | RTL8139_AUTONEG_CAPS) != RTL8139_AUTONEG_CAPS)
1637 return EINVAL; /* some unsuported mode is requested */
1638
1639 assert(advertisement != 0);
1640
1641 /* Set the autonegotiation advertisement */
1642 uint16_t anar = ANAR_SELECTOR; /* default selector */
1643 if (advertisement & ETH_AUTONEG_10BASE_T_FULL)
1644 anar |= ANAR_10_FD;
1645 if (advertisement & ETH_AUTONEG_10BASE_T_HALF)
1646 anar |= ANAR_10_HD;
1647 if (advertisement & ETH_AUTONEG_100BASE_TX_FULL)
1648 anar |= ANAR_100TX_FD;
1649 if (advertisement & ETH_AUTONEG_100BASE_TX_HALF)
1650 anar |= ANAR_100TX_HD;
1651 if (advertisement & ETH_AUTONEG_PAUSE_SYMETRIC)
1652 anar |= ANAR_PAUSE;
1653
1654 uint16_t bmcr_val = pio_read_16(rtl8139->io_port + BMCR);
1655 bmcr_val |= BMCR_AN_ENABLE;
1656
1657 pio_write_16(rtl8139->io_port + ANAR, anar);
1658
1659 rtl8139_regs_unlock(rtl8139->io_port);
1660 pio_write_16(rtl8139->io_port + BMCR, bmcr_val);
1661 rtl8139_regs_lock(rtl8139->io_port);
1662 return EOK;
1663}
1664
1665/** Disable advertisement functionality
1666 *
1667 * @param dev The device to update
1668 *
1669 * @returns EOK
1670 */
1671static int rtl8139_autoneg_disable(ddf_fun_t *fun)
1672{
1673 assert(fun);
1674
1675 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1676 assert(rtl8139);
1677
1678 uint16_t bmcr_val = pio_read_16(rtl8139->io_port + BMCR);
1679
1680 bmcr_val &= ~((uint16_t)BMCR_AN_ENABLE);
1681
1682 rtl8139_regs_unlock(rtl8139->io_port);
1683 pio_write_16(rtl8139->io_port + BMCR, bmcr_val);
1684 rtl8139_regs_lock(rtl8139->io_port);
1685
1686 return EOK;
1687}
1688
1689/** Obtain the advertisement NIC framework value from the ANAR/ANLPAR register
1690 * value
1691 *
1692 * @param[in] anar The ANAR register value
1693 * @param[out] advertisement The advertisement result
1694 */
1695static void rtl8139_get_anar_state(uint16_t anar, uint32_t *advertisement)
1696{
1697 *advertisement = 0;
1698 if (anar & ANAR_10_HD)
1699 *advertisement |= ETH_AUTONEG_10BASE_T_HALF;
1700 if (anar & ANAR_10_FD)
1701 *advertisement |= ETH_AUTONEG_10BASE_T_FULL;
1702 if (anar & ANAR_100TX_HD)
1703 *advertisement |= ETH_AUTONEG_100BASE_TX_HALF;
1704 if (anar & ANAR_100TX_FD)
1705 *advertisement |= ETH_AUTONEG_100BASE_TX_FULL;
1706 if (anar & ANAR_100T4)
1707 *advertisement |= ETH_AUTONEG_100BASE_T4_HALF;
1708 if (anar & ANAR_PAUSE)
1709 *advertisement |= ETH_AUTONEG_PAUSE_SYMETRIC;
1710}
1711
1712/** Check the autonegotion state
1713 *
1714 * @param[in] dev The device to check
1715 * @param[out] advertisement The device advertisement
1716 * @param[out] their_adv The partners advertisement
1717 * @param[out] result The autonegotion state
1718 * @param[out] their_result The link partner autonegotion status
1719 *
1720 * @returns EOK
1721 */
1722static int rtl8139_autoneg_probe(ddf_fun_t *fun, uint32_t *advertisement,
1723 uint32_t *their_adv, nic_result_t *result, nic_result_t *their_result)
1724{
1725 assert(fun);
1726
1727 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1728 assert(rtl8139);
1729
1730 uint16_t bmcr = pio_read_16(rtl8139->io_port + BMCR);
1731 uint16_t anar = pio_read_16(rtl8139->io_port + ANAR);
1732 uint16_t anar_lp = pio_read_16(rtl8139->io_port + ANLPAR);
1733 uint16_t aner = pio_read_16(rtl8139->io_port + ANER);
1734
1735 if (bmcr & BMCR_AN_ENABLE) {
1736 *result = NIC_RESULT_ENABLED;
1737 } else {
1738 *result = NIC_RESULT_DISABLED;
1739 }
1740
1741 if (aner & ANER_LP_NW_ABLE) {
1742 *their_result = NIC_RESULT_ENABLED;
1743 } else {
1744 *their_result = NIC_RESULT_DISABLED;
1745 }
1746
1747 rtl8139_get_anar_state(anar, advertisement);
1748 rtl8139_get_anar_state(anar_lp, their_adv);
1749
1750 return EOK;
1751}
1752
1753/** Restart autonegotiation process
1754 *
1755 * @param dev The device to update
1756 *
1757 * @returns EOK
1758 */
1759static int rtl8139_autoneg_restart(ddf_fun_t *fun)
1760{
1761 assert(fun);
1762
1763 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1764 assert(rtl8139);
1765
1766 uint16_t bmcr = pio_read_16(rtl8139->io_port + BMCR);
1767 bmcr |= BMCR_AN_RESTART;
1768 bmcr |= BMCR_AN_ENABLE;
1769
1770 rtl8139_regs_unlock(rtl8139);
1771 pio_write_16(rtl8139->io_port + BMCR, bmcr);
1772 rtl8139_regs_lock(rtl8139);
1773
1774 return EOK;
1775}
1776
1777/** Notify NIC framework about HW filtering state when promisc mode was disabled
1778 *
1779 * @param nic_data The NIC data
1780 * @param mcast_mode Current multicast mode
1781 * @param was_promisc Sign if the promiscuous mode was active before disabling
1782 */
1783inline static void rtl8139_rcx_promics_rem(nic_t *nic_data,
1784 nic_multicast_mode_t mcast_mode, uint8_t was_promisc)
1785{
1786 assert(nic_data);
1787
1788 if (was_promisc != 0) {
1789 if (mcast_mode == NIC_MULTICAST_LIST)
1790 nic_report_hw_filtering(nic_data, 1, 0, -1);
1791 else
1792 nic_report_hw_filtering(nic_data, 1, 1, -1);
1793 } else {
1794 nic_report_hw_filtering(nic_data, 1, -1, -1);
1795 }
1796}
1797
1798/** Set unicast packets acceptance mode
1799 *
1800 * @param nic_data The nic device to update
1801 * @param mode The mode to set
1802 * @param addr Ignored, no HW support, just use unicast promisc
1803 * @param addr_cnt Ignored, no HW support
1804 *
1805 * @returns EOK
1806 */
1807static int rtl8139_unicast_set(nic_t *nic_data, nic_unicast_mode_t mode,
1808 const nic_address_t *addr, size_t addr_cnt)
1809{
1810 assert(nic_data);
1811
1812 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
1813 assert(rtl8139);
1814
1815 uint8_t was_promisc = rtl8139->rcr_data.ucast_mask & RCR_ACCEPT_ALL_PHYS;
1816
1817 nic_multicast_mode_t mcast_mode;
1818 nic_query_multicast(nic_data, &mcast_mode, 0, NULL, NULL);
1819
1820 switch (mode) {
1821 case NIC_UNICAST_BLOCKED:
1822 rtl8139->rcr_data.ucast_mask = 0;
1823 rtl8139_rcx_promics_rem(nic_data, mcast_mode, was_promisc);
1824 break;
1825 case NIC_UNICAST_DEFAULT:
1826 rtl8139->rcr_data.ucast_mask = RCR_ACCEPT_PHYS_MATCH;
1827 rtl8139_rcx_promics_rem(nic_data, mcast_mode, was_promisc);
1828 break;
1829 case NIC_UNICAST_LIST:
1830 rtl8139->rcr_data.ucast_mask = RCR_ACCEPT_PHYS_MATCH
1831 | RCR_ACCEPT_ALL_PHYS;
1832
1833 if (mcast_mode == NIC_MULTICAST_PROMISC)
1834 nic_report_hw_filtering(nic_data, 0, 1, -1);
1835 else
1836 nic_report_hw_filtering(nic_data, 0, 0, -1);
1837 break;
1838 case NIC_UNICAST_PROMISC:
1839 rtl8139->rcr_data.ucast_mask = RCR_ACCEPT_PHYS_MATCH
1840 | RCR_ACCEPT_ALL_PHYS;
1841
1842 if (mcast_mode == NIC_MULTICAST_PROMISC)
1843 nic_report_hw_filtering(nic_data, 1, 1, -1);
1844 else
1845 nic_report_hw_filtering(nic_data, 1, 0, -1);
1846 break;
1847 default:
1848 return ENOTSUP;
1849 }
1850 fibril_mutex_lock(&rtl8139->rx_lock);
1851 rtl8139_hw_update_rcr(rtl8139);
1852 fibril_mutex_unlock(&rtl8139->rx_lock);
1853 return EOK;
1854}
1855
1856/** Set multicast packets acceptance mode
1857 *
1858 * @param nic_data The nic device to update
1859 * @param mode The mode to set
1860 * @param addr Addresses to accept
1861 * @param addr_cnt Addresses count
1862 *
1863 * @returns EOK
1864 */
1865static int rtl8139_multicast_set(nic_t *nic_data, nic_multicast_mode_t mode,
1866 const nic_address_t *addr, size_t addr_count)
1867{
1868 assert(nic_data);
1869 assert(addr_count == 0 || addr);
1870
1871 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
1872 assert(rtl8139);
1873
1874 switch (mode) {
1875 case NIC_MULTICAST_BLOCKED:
1876 rtl8139->rcr_data.mcast_mask = 0;
1877 if ((rtl8139->rcr_data.ucast_mask & RCR_ACCEPT_ALL_PHYS) != 0)
1878 nic_report_hw_filtering(nic_data, -1, 0, -1);
1879 else
1880 nic_report_hw_filtering(nic_data, -1, 1, -1);
1881 break;
1882 case NIC_MULTICAST_LIST:
1883 rtl8139_hw_set_mcast_mask(rtl8139, nic_mcast_hash(addr, addr_count));
1884 rtl8139->rcr_data.mcast_mask = RCR_ACCEPT_MULTICAST;
1885 nic_report_hw_filtering(nic_data, -1, 0, -1);
1886 break;
1887 case NIC_MULTICAST_PROMISC:
1888 rtl8139_hw_set_mcast_mask(rtl8139, RTL8139_MCAST_MASK_PROMISC);
1889 rtl8139->rcr_data.mcast_mask = RCR_ACCEPT_MULTICAST;
1890 nic_report_hw_filtering(nic_data, -1, 1, -1);
1891 break;
1892 default:
1893 return ENOTSUP;
1894 }
1895 fibril_mutex_lock(&rtl8139->rx_lock);
1896 rtl8139_hw_update_rcr(rtl8139);
1897 fibril_mutex_unlock(&rtl8139->rx_lock);
1898 return EOK;
1899}
1900
1901/** Set broadcast packets acceptance mode
1902 *
1903 * @param nic_data The nic device to update
1904 * @param mode The mode to set
1905 *
1906 * @returns EOK
1907 */
1908static int rtl8139_broadcast_set(nic_t *nic_data, nic_broadcast_mode_t mode)
1909{
1910 assert(nic_data);
1911
1912 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
1913 assert(rtl8139);
1914
1915 switch (mode) {
1916 case NIC_BROADCAST_BLOCKED:
1917 rtl8139->rcr_data.bcast_mask = 0;
1918 break;
1919 case NIC_BROADCAST_ACCEPTED:
1920 rtl8139->rcr_data.bcast_mask = RCR_ACCEPT_BROADCAST;
1921 break;
1922 default:
1923 return ENOTSUP;
1924 }
1925 fibril_mutex_lock(&rtl8139->rx_lock);
1926 rtl8139_hw_update_rcr(rtl8139);
1927 fibril_mutex_unlock(&rtl8139->rx_lock);
1928 return EOK;
1929}
1930
1931/** Get state of acceptance of weird packets
1932 *
1933 * @param[in] device The device to check
1934 * @param[out] mode The current mode
1935 */
1936static int rtl8139_defective_get_mode(ddf_fun_t *fun, uint32_t *mode)
1937{
1938 assert(fun);
1939 assert(mode);
1940
1941 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1942 assert(rtl8139);
1943
1944 *mode = 0;
1945 if (rtl8139->rcr_data.defect_mask & RCR_ACCEPT_ERROR)
1946 *mode |= NIC_DEFECTIVE_BAD_CRC;
1947 if (rtl8139->rcr_data.defect_mask & RCR_ACCEPT_RUNT)
1948 *mode |= NIC_DEFECTIVE_SHORT;
1949
1950 return EOK;
1951};
1952
1953/** Set acceptance of weird packets
1954 *
1955 * @param device The device to update
1956 * @param mode The mode to set
1957 *
1958 * @returns ENOTSUP if the mode is not supported
1959 * @returns EOK of mode was set
1960 */
1961static int rtl8139_defective_set_mode(ddf_fun_t *fun, uint32_t mode)
1962{
1963 assert(fun);
1964
1965 rtl8139_t *rtl8139 = nic_get_specific(nic_get_from_ddf_fun(fun));
1966 assert(rtl8139);
1967
1968 if ((mode & (NIC_DEFECTIVE_SHORT | NIC_DEFECTIVE_BAD_CRC)) != mode)
1969 return ENOTSUP;
1970
1971 rtl8139->rcr_data.defect_mask = 0;
1972 if (mode & NIC_DEFECTIVE_SHORT)
1973 rtl8139->rcr_data.defect_mask |= RCR_ACCEPT_RUNT;
1974 if (mode & NIC_DEFECTIVE_BAD_CRC)
1975 rtl8139->rcr_data.defect_mask |= RCR_ACCEPT_ERROR;
1976
1977 fibril_mutex_lock(&rtl8139->rx_lock);
1978 rtl8139_hw_update_rcr(rtl8139);
1979 fibril_mutex_unlock(&rtl8139->rx_lock);
1980 return EOK;
1981};
1982
1983
1984/** Turn Wakeup On Lan method on
1985 *
1986 * @param nic_data The NIC to update
1987 * @param virtue The method to turn on
1988 *
1989 * @returns EINVAL if the method is not supported
1990 * @returns EOK if succeed
1991 * @returns ELIMIT if no more methods of this kind can be enabled
1992 */
1993static int rtl8139_wol_virtue_add(nic_t *nic_data,
1994 const nic_wol_virtue_t *virtue)
1995{
1996 assert(nic_data);
1997 assert(virtue);
1998
1999 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
2000 assert(rtl8139);
2001
2002 switch(virtue->type) {
2003 case NIC_WV_BROADCAST:
2004 rtl8139_hw_reg_add_8(rtl8139, CONFIG5, CONFIG5_BROADCAST_WAKEUP);
2005 break;
2006 case NIC_WV_LINK_CHANGE:
2007 rtl8139_regs_unlock(rtl8139->io_port);
2008 rtl8139_hw_reg_add_8(rtl8139, CONFIG3, CONFIG3_LINK_UP);
2009 rtl8139_regs_lock(rtl8139->io_port);
2010 break;
2011 case NIC_WV_MAGIC_PACKET:
2012 if (virtue->data)
2013 return EINVAL;
2014 rtl8139_regs_unlock(rtl8139->io_port);
2015 rtl8139_hw_reg_add_8(rtl8139, CONFIG3, CONFIG3_MAGIC);
2016 rtl8139_regs_lock(rtl8139->io_port);
2017 break;
2018 default:
2019 return EINVAL;
2020 };
2021 if(rtl8139->pm.active++ == 0)
2022 rtl8139_hw_pmen_set(rtl8139, 1);
2023 return EOK;
2024}
2025
2026/** Turn Wakeup On Lan method off
2027 *
2028 * @param nic_data The NIC to update
2029 * @param virtue The method to turn off
2030 */
2031static void rtl8139_wol_virtue_rem(nic_t *nic_data,
2032 const nic_wol_virtue_t *virtue)
2033{
2034 assert(nic_data);
2035 assert(virtue);
2036
2037 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
2038 assert(rtl8139);
2039
2040 switch(virtue->type) {
2041 case NIC_WV_BROADCAST:
2042 rtl8139_hw_reg_rem_8(rtl8139, CONFIG5, CONFIG5_BROADCAST_WAKEUP);
2043 break;
2044 case NIC_WV_LINK_CHANGE:
2045 rtl8139_regs_unlock(rtl8139->io_port);
2046 rtl8139_hw_reg_rem_8(rtl8139, CONFIG3, CONFIG3_LINK_UP);
2047 rtl8139_regs_lock(rtl8139->io_port);
2048 break;
2049 case NIC_WV_MAGIC_PACKET:
2050 rtl8139_regs_unlock(rtl8139->io_port);
2051 rtl8139_hw_reg_rem_8(rtl8139, CONFIG3, CONFIG3_MAGIC);
2052 rtl8139_regs_lock(rtl8139->io_port);
2053 break;
2054 default:
2055 return;
2056 };
2057 rtl8139->pm.active--;
2058 if (rtl8139->pm.active == 0)
2059 rtl8139_hw_pmen_set(rtl8139, 0);
2060}
2061
2062
2063/** Set polling mode
2064 *
2065 * @param device The device to set
2066 * @param mode The mode to set
2067 * @param period The period for NIC_POLL_PERIODIC
2068 *
2069 * @returns EOK if succeed
2070 * @returns ENOTSUP if the mode is not supported
2071 */
2072static int rtl8139_poll_mode_change(nic_t *nic_data, nic_poll_mode_t mode,
2073 const struct timeval *period)
2074{
2075 assert(nic_data);
2076 int rc = EOK;
2077
2078 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
2079 assert(rtl8139);
2080
2081 fibril_mutex_lock(&rtl8139->rx_lock);
2082
2083 switch(mode) {
2084 case NIC_POLL_IMMEDIATE:
2085 rtl8139->int_mask = RTL_DEFAULT_INTERRUPTS;
2086 break;
2087 case NIC_POLL_ON_DEMAND:
2088 rtl8139->int_mask = 0;
2089 break;
2090 case NIC_POLL_PERIODIC:
2091 assert(period);
2092
2093 rtl8139_timer_act_t new_timer;
2094 rc = rtl8139_timer_act_init(&new_timer, RTL8139_PCI_FREQ_KHZ, period);
2095 if (rc != EOK)
2096 break;
2097
2098 /* Disable timer interrupts while working with timer-related data */
2099 rtl8139->int_mask = 0;
2100 rtl8139_hw_int_enable(rtl8139);
2101
2102 rtl8139->poll_timer = new_timer;
2103 rtl8139->int_mask = INT_TIME_OUT;
2104
2105 /* Force timer interrupt start be writing nonzero value to timer
2106 * interrutp register (should be small to prevent big delay)
2107 * Read TCTR to reset timer counter
2108 * Change values to simulate the last interrupt from the period.
2109 */
2110 pio_write_32(rtl8139->io_port + TIMERINT, 10);
2111 pio_write_32(rtl8139->io_port + TCTR, 0);
2112
2113 ddf_msg(LVL_DEBUG, "Periodic mode. Interrupt mask %"PRIx16", poll.full_skips %"
2114 PRIu32", last timer %"PRIu32".", rtl8139->int_mask,
2115 rtl8139->poll_timer.full_skips, rtl8139->poll_timer.last_val);
2116 break;
2117 default:
2118 rc = ENOTSUP;
2119 break;
2120 }
2121
2122 rtl8139_hw_int_enable(rtl8139);
2123
2124 fibril_mutex_unlock(&rtl8139->rx_lock);
2125
2126 return rc;
2127}
2128
2129/** Force receiving all packets in the receive buffer
2130 *
2131 * @param device The device to receive
2132 */
2133static void rtl8139_poll(nic_t *nic_data)
2134{
2135 assert(nic_data);
2136
2137 rtl8139_t *rtl8139 = nic_get_specific(nic_data);
2138 assert(rtl8139);
2139
2140 uint16_t isr = pio_read_16(rtl8139->io_port + ISR);
2141 pio_write_16(rtl8139->io_port + ISR, 0);
2142
2143 rtl8139_interrupt_impl(nic_data, isr);
2144}
2145
2146
2147/** Main function of RTL8139 driver
2148 *
2149 * Just initialize the driver structures and
2150 * put it into the device drivers interface
2151 */
2152int main(void)
2153{
2154 int rc = nic_driver_init(NAME);
2155 if (rc != EOK)
2156 return rc;
2157 nic_driver_implement(
2158 &rtl8139_driver_ops, &rtl8139_dev_ops, &rtl8139_nic_iface);
2159
2160 ddf_log_init(NAME, LVL_ERROR);
2161 ddf_msg(LVL_NOTE, "HelenOS RTL8139 driver started");
2162 return ddf_driver_main(&rtl8139_driver);
2163}
Note: See TracBrowser for help on using the repository browser.