2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2011, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Lei Xia <lxia@northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <devices/pci.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_types.h>
23 #include <palacios/vmm_io.h>
24 #include <palacios/vmm_debug.h>
25 #include <palacios/vm_guest_mem.h>
26 #include <palacios/vmm_ethernet.h>
27 #include <palacios/vmm_sprintf.h>
31 #ifndef V3_CONFIG_DEBUG_RTL8139
33 #define PrintDebug(fmts, args...)
36 #define RTL8139_IDR0 (0x00) /* ID Registers start, len 6*1bytes */
37 #define RTL8139_MAR0 (0x08) /* Mulicast Registers start, len 8*1bytes */
39 #define RTL8139_TSD0 (0x10) /* Tx Status of Descriptors */
40 #define RTL8139_TSD1 (0x14)
41 #define RTL8139_TSD2 (0x18)
42 #define RTL8139_TSD3 (0x1c)
44 #define RTL8139_TSAD0 (0x20) /* Tx Start Address of Descriptors */
45 #define RTL8139_TSAD1 (0x24)
46 #define RTL8139_TSAD2 (0x28)
47 #define RTL8139_TSAD3 (0x2c)
49 #define RTL8139_RBSTART (0x30) /* Rx Buffer Start Address */
50 #define RTL8139_ERBCR (0x34) /* Early Rx Byte Count Register */
51 #define RTL8139_ERSR (0x36) /* Early Rx Status Register */
52 #define RTL8139_CR (0x37) /* Command Register */
53 #define RTL8139_CAPR (0x38) /* Current Address of Pkt Read */
54 #define RTL8139_CBR (0x3a) /* Current Buffer Address */
55 #define RTL8139_IMR (0x3c) /* Intrpt Mask Reg */
56 #define RTL8139_ISR (0x3e) /* Intrpt Status Reg */
57 #define RTL8139_TCR (0x40) /* Tx Config Reg */
58 #define RTL8139_RCR (0x44) /* Rx Config Reg */
59 #define RTL8139_TCTR (0x48) /* Timer Count Reg */
60 #define RTL8139_MPC (0x4c) /* Missed Pkt Counter */
61 #define RTL8139_9346CR (0x50) /* 9346 Command Reg */
62 #define RTL8139_CONFIG0 (0x51) /* Config Reg */
63 #define RTL8139_CONFIG1 (0x52)
64 #define RTL8139_TimerInt (0x54) /* Timer Intrpt Reg */
65 #define RTL8139_MSR (0x58) /* Media Status Reg */
66 #define RTL8139_CONFIG3 (0x59)
67 #define RTL8139_CONFIG4 (0x5a)
68 #define RTL8139_MULINT (0x5c) /* Multiple Intrpt Select */
69 #define RTL8139_RERID (0x5e)
70 #define RTL8139_TXSAD (0x60) /* Tx Status of All Descriptors */
71 #define RTL8139_BMCR (0x62) /* Basic Mode Control Register */
72 #define RTL8139_BMSR (0x64) /* Basic Mode Status Register */
73 #define RTL8139_ANAR (0x66) /* Auto-Negotiation Advertisement Register */
74 #define RTL8139_ANLPAR (0x68) /* Auto-Negotiation Link Partner Register */
75 #define RTL8139_ANER (0x6a) /* Auto-Negotiation Expansion Register */
76 #define RTL8139_DIS (0x6c) /* Disconnect Counter */
77 #define RTL8139_FCSC (0x6e) /* False Carrier Sense Counter */
78 #define RTL8139_NWAYTR (0x70) /* N-way Test Register */
79 #define RTL8139_REC (0x72) /* RX ER Counter */
80 #define RTL8139_CSCR (0x74) /* CS Config Register */
81 #define RTL8139_PHY1_PARM (0x78) /* PHY parameter */
82 #define RTL8139_TW_PARM (0x7c) /* Twister parameter */
83 #define RTL8139_PHY2_PARM (0x80)
85 #define RTL8139_CRC0 (0x84) /* Power Management CRC Reg for wakeup frame 8*1bytes */
87 #define RTL8139_Wakeup0 (0x8c) /* Power Management wakeup frame */
88 #define RTL8139_Wakeup1 (0x94)
89 #define RTL8139_Wakeup2 (0x9c)
90 #define RTL8139_Wakeup3 (0xa4)
91 #define RTL8139_Wakeup4 (0xac)
92 #define RTL8139_Wakeup5 (0xb4)
93 #define RTL8139_Wakeup6 (0xbc)
94 #define RTL8139_Wakeup7 (0xc4)
96 #define RTL8139_LSBCRO0 (0xcc) /* LSB of the mask byte of wakeup frame */
97 #define RTL8139_LSBCRO1 (0xcd)
98 #define RTL8139_LSBCRO2 (0xce)
99 #define RTL8139_LSBCRO3 (0xcf)
100 #define RTL8139_LSBCRO4 (0xd0)
101 #define RTL8139_LSBCRO5 (0xd1)
102 #define RTL8139_LSBCRO6 (0xd2)
103 #define RTL8139_LSBCRO7 (0xd3)
105 #define RTL8139_Config5 (0xd8)
108 #define PKT_RX 0x0001
109 #define RX_ERR 0x0002
111 #define TX_ERR 0x0008
112 #define RX_BUFF_OF 0x0010
113 #define RX_UNDERRUN 0x0020
114 #define RX_FIFO_OF 0x0040
115 #define CABLE_LEN_CHNG 0x2000
116 #define TIME_OUT 0x4000
119 #define DESC_SIZE 2048
120 #define TX_FIFO_SIZE (DESC_SIZE * 4)
121 #define RX_FIFO_SIZE (DESC_SIZE * 4)
123 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
135 /* Transmit Status Register (TSD0-3) Offset: 0x10-0x1F */
136 struct tx_status_reg {
144 uint8_t er_tx_th : 6;
145 uint8_t reserved : 2;
151 } __attribute__((packed));
152 } __attribute__((packed));
153 } __attribute__((packed));
157 Rx_Multicast = 1<<15,
159 Rx_Broadcast = 1<<13,
169 /* Receive Status Register in RX Packet Header */
170 struct rx_status_reg {
175 uint8_t rx_bad_align : 1;
176 uint8_t rx_crc_err : 1;
177 uint8_t rx_too_long : 1;
179 uint8_t rx_bad_sym : 1;
180 uint8_t reserved : 7;
181 uint8_t rx_brdcast : 1;
183 uint8_t rx_multi : 1;
184 } __attribute__((packed));
185 } __attribute__((packed));
186 } __attribute__((packed));
189 /* ERSR - Early Rx Status Register Offset: 0x36*/
190 struct errx_status_reg{
194 uint8_t er_rx_ok : 1;
195 uint8_t er_rx_ovw : 1;
196 uint8_t er_rx_bad_pkt : 1;
197 uint8_t er_rx_good : 1;
198 uint8_t reserved : 4;
199 } __attribute__((packed));
200 } __attribute__((packed));
201 } __attribute__((packed));
204 /* Transmit Status of All Descriptors (TSAD) Register */
206 TSAD_TOK3 = 1<<15, /* TOK bits of Descriptors*/
210 TSAD_TUN3 = 1<<11, /* TUN bits of Descriptors */
214 TSAD_TABT3 = 1<<7, /* TABT bits of Descriptors */
218 TSAD_OWN3 = 1<<3, /* OWN bits of Descriptors */
225 /* Transmit Status of All Descriptors (TSAD) Register Offset: 0x60-0x61*/
246 } __attribute__((packed));
247 } __attribute__((packed));
248 } __attribute__((packed));
266 * Interrupt Status Register (ISR) Offset: ox3e-0x3f
267 * Interrupt Mask Register (IMR 0x3c-0x3d) shares the same structure
278 uint8_t pun_linkchg : 1;
279 uint8_t rx_fifo_ovw : 1;
284 } __attribute__((packed));
285 } __attribute__((packed));
286 } __attribute__((packed));
296 /* Commmand Register Offset: 0x37 */
301 uint8_t cmd_bufe : 1;
302 uint8_t reservd_1 : 1;
306 uint8_t reservd_2 : 3;
307 } __attribute__((packed));
308 } __attribute__((packed));
309 } __attribute__((packed));
316 CMD9346_Unlock = 0xC0,
321 /* 93C46 Commmand Register Offset: 0x50 */
330 uint8_t reserved : 2;
332 } __attribute__((packed));
333 } __attribute__((packed));
334 } __attribute__((packed));
341 /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
343 TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
344 TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
345 TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
346 TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
348 TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
349 TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
350 TxClearAbt = (1 << 0), /* Clear abort (WO) */
351 TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */
352 TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */
354 TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
358 /* Transmit Configuration Register (TCR) Offset: 0x40-0x43 */
359 struct tx_config_reg {
363 uint8_t clr_abort :1;
364 uint8_t reserved_1 : 3;
365 uint8_t tx_retry_cnt : 4;
367 uint8_t reserved_2 : 5;
369 uint8_t loop_test : 2;
370 uint8_t reservd_3: 3;
371 uint8_t hw_verid_b :2;
373 uint8_t hw_verid_a :5;
374 uint8_t reservd_4 :1;
375 } __attribute__((packed));
376 } __attribute__((packed));
377 } __attribute__((packed));
383 CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */
384 CSCR_LD = 1<<9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/
385 CSCR_HEART_BIT = 1<<8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/
386 CSCR_JBEN = 1<<7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/
387 CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/
388 CSCR_F_Connect = 1<<5, /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/
389 CSCR_Con_status = 1<<3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/
390 CSCR_Con_status_En = 1<<2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/
391 CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/
395 /* CS Configuration Register (CSCR) Offset: 0x74-0x75 */
401 uint8_t reserved_1 : 1;
402 uint8_t con_status_en : 1;
403 uint8_t con_status : 1;
404 uint8_t reserved_2 : 1;
405 uint8_t f_connect : 1;
406 uint8_t f_link_100 : 1;
408 uint8_t heart_beat :1;
410 uint8_t reservd_3 :5;
412 } __attribute__((packed));
413 } __attribute__((packed));
414 } __attribute__((packed));
417 /* Bits in RxConfig. */
421 AcceptBroadcast = 0x08,
422 AcceptMulticast = 0x04,
424 AcceptAllPhys = 0x01,
428 /* Receive Configuration Register (RCR) Offset: 0x44-0x47 */
429 struct rx_config_reg {
435 uint8_t all_multi : 1;
436 uint8_t all_brdcast : 1;
437 uint8_t acpt_runt : 1;
438 uint8_t acpt_err : 1;
439 uint8_t reserved_1 : 1;
442 uint8_t rx_buf_len :2;
443 uint8_t rx_fifo_thresd :3;
445 uint8_t mul_er_intr :1;
446 uint8_t reserved_2 : 6;
447 uint8_t eraly_rx_thresd :4;
448 uint8_t reserved_3 : 4;
449 } __attribute__((packed));
450 } __attribute__((packed));
451 } __attribute__((packed));
456 #define RTL8139_PCI_REVID_8139 0x10
458 #define SET_MASKED(input, mask, curr) \
459 (((input) & ~(mask)) | ((curr) & (mask)))
461 /* arg % size for size which is a power of 2 */
462 #define MOD2(input, size) \
463 ((input) & (size - 1))
466 /* Size is 64 * 16bit words */
467 #define EEPROM_9346_ADDR_BITS 6
468 #define EEPROM_9346_SIZE (1 << EEPROM_9346_ADDR_BITS)
469 #define EEPROM_9346_ADDR_MASK (EEPROM_9346_SIZE - 1)
471 enum Chip9346Operation
473 Chip9346_op_mask = 0xc0, /* 10 zzzzzz */
474 Chip9346_op_read = 0x80, /* 10 AAAAAA */
475 Chip9346_op_write = 0x40, /* 01 AAAAAA D(15)..D(0) */
476 Chip9346_op_ext_mask = 0xf0, /* 11 zzzzzz */
477 Chip9346_op_write_enable = 0x30, /* 00 11zzzz */
478 Chip9346_op_write_all = 0x10, /* 00 01zzzz */
479 Chip9346_op_write_disable = 0x00, /* 00 00zzzz */
484 Chip9346_enter_command_mode,
485 Chip9346_read_command,
486 Chip9346_data_read, /* from output register */
487 Chip9346_data_write, /* to input register, then to contents at specified address */
488 Chip9346_data_write_all, /* to input register, then filling contents */
492 uint16_t contents[EEPROM_9346_SIZE];
505 struct rtl8139_regs {
552 }__attribute__((packed));
553 }__attribute__((packed));
558 struct rtl8139_state {
559 nic_state_t dev_state;
561 struct v3_vm_info * vm;
562 struct pci_device * pci_dev;
563 struct vm_device * pci_bus;
564 struct vm_device * dev;
566 struct nic_statistics statistic;
568 struct rtl8139_regs regs;
569 struct EEprom9346 eeprom;
571 uint8_t tx_fifo[TX_FIFO_SIZE];
572 uint8_t rx_fifo[RX_FIFO_SIZE];
575 uint8_t mac[ETH_ALEN];
577 struct v3_dev_net_ops *net_ops;
581 static inline void rtl8139_update_irq(struct rtl8139_state * nic_state) {
582 int isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0xffff);
585 v3_pci_raise_irq(nic_state->pci_bus, 0, nic_state->pci_dev);
589 static void prom9346_decode_command(struct EEprom9346 * eeprom, uint8_t command) {
590 PrintDebug("RTL8139: eeprom command 0x%02x\n", command);
592 switch (command & Chip9346_op_mask) {
593 case Chip9346_op_read:
595 eeprom->address = command & EEPROM_9346_ADDR_MASK;
596 eeprom->output = eeprom->contents[eeprom->address];
599 eeprom->mode = Chip9346_data_read;
600 PrintDebug("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",
601 eeprom->address, eeprom->output);
605 case Chip9346_op_write:
607 eeprom->address = command & EEPROM_9346_ADDR_MASK;
610 eeprom->mode = Chip9346_none; /* Chip9346_data_write */
611 PrintDebug("RTL8139: eeprom begin write to address 0x%02x\n",
616 eeprom->mode = Chip9346_none;
617 switch (command & Chip9346_op_ext_mask) {
618 case Chip9346_op_write_enable:
619 PrintDebug("RTL8139: eeprom write enabled\n");
621 case Chip9346_op_write_all:
622 PrintDebug("RTL8139: eeprom begin write all\n");
624 case Chip9346_op_write_disable:
625 PrintDebug("RTL8139: eeprom write disabled\n");
632 static void prom9346_shift_clock(struct EEprom9346 * eeprom) {
633 int bit = eeprom->eedi?1:0;
637 PrintDebug("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo);
639 switch (eeprom->mode) {
640 case Chip9346_enter_command_mode:
642 eeprom->mode = Chip9346_read_command;
645 PrintDebug("eeprom: +++ synchronized, begin command read\n");
649 case Chip9346_read_command:
650 eeprom->input = (eeprom->input << 1) | (bit & 1);
651 if (eeprom->tick == 8) {
652 prom9346_decode_command(eeprom, eeprom->input & 0xff);
656 case Chip9346_data_read:
657 eeprom->eedo = (eeprom->output & 0x8000)?1:0;
658 eeprom->output <<= 1;
659 if (eeprom->tick == 16){
661 // the FreeBSD drivers (rl and re) don't explicitly toggle
662 // CS between reads (or does setting Cfg9346 to 0 count too?),
663 // so we need to enter wait-for-command state here
664 eeprom->mode = Chip9346_enter_command_mode;
668 PrintDebug("eeprom: +++ end of read, awaiting next command\n");
670 // original behaviour
672 eeprom->address &= EEPROM_9346_ADDR_MASK;
673 eeprom->output = eeprom->contents[eeprom->address];
676 DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n",
677 eeprom->address, eeprom->output));
682 case Chip9346_data_write:
683 eeprom->input = (eeprom->input << 1) | (bit & 1);
684 if (eeprom->tick == 16) {
685 PrintDebug("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
686 eeprom->address, eeprom->input);
688 eeprom->contents[eeprom->address] = eeprom->input;
689 eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */
695 case Chip9346_data_write_all:
696 eeprom->input = (eeprom->input << 1) | (bit & 1);
697 if (eeprom->tick == 16) {
699 for (i = 0; i < EEPROM_9346_SIZE; i++)
701 eeprom->contents[i] = eeprom->input;
703 PrintDebug("RTL8139: eeprom filled with data=0x%04x\n",
706 eeprom->mode = Chip9346_enter_command_mode;
717 static int prom9346_get_wire(struct rtl8139_state * nic_state) {
718 struct EEprom9346 *eeprom = &(nic_state->eeprom);
720 if (eeprom->eecs == 0)
726 static void prom9346_set_wire(struct rtl8139_state * nic_state,
730 struct EEprom9346 *eeprom = &(nic_state->eeprom);
731 uint8_t old_eecs = eeprom->eecs;
732 uint8_t old_eesk = eeprom->eesk;
738 PrintDebug("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
739 eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo);
741 if (old_eecs == 0 && eecs) {
742 /* Synchronize start */
746 eeprom->mode = Chip9346_enter_command_mode;
748 PrintDebug("=== eeprom: begin access, enter command mode\n");
752 PrintDebug("=== eeprom: end access\n");
756 if (!old_eesk && eesk) {
758 prom9346_shift_clock(eeprom);
763 static inline void rtl8139_reset_rxbuf(struct rtl8139_state * nic_state, uint32_t bufsize) {
764 nic_state->rx_bufsize = bufsize;
765 nic_state->regs.capr = 0;
766 nic_state->regs.cbr = 0;
770 static void rtl8139_reset(struct rtl8139_state *nic_state) {
771 struct rtl8139_regs *regs = &(nic_state->regs);
774 PrintDebug("Rtl8139: Reset\n");
776 /* restore MAC address */
777 memcpy(regs->id, nic_state->mac, ETH_ALEN);
778 memset(regs->mult, 0xff, 8);
780 rtl8139_update_irq(nic_state);
783 nic_state->eeprom.contents[0] = 0x8129;
785 // PCI vendor and device ID
786 nic_state->eeprom.contents[1] = 0x10ec;
787 nic_state->eeprom.contents[2] = 0x8139;
789 nic_state->eeprom.contents[7] = nic_state->mac[0] | nic_state->mac[1] << 8;
790 nic_state->eeprom.contents[8] = nic_state->mac[2] | nic_state->mac[3] << 8;
791 nic_state->eeprom.contents[9] = nic_state->mac[4] | nic_state->mac[5] << 8;
793 for (i = 0; i < 4; ++i) {
794 regs->tsd[i] = TSD_Own;
797 rtl8139_reset_rxbuf(nic_state, 1024*8);
802 regs->tcr |= ((0x1d << 26) | (0x1 << 22)); // RTL-8139D
803 regs->rerid = RTL8139_PCI_REVID_8139;
805 regs->cmd = CMD_Rst; //RxBufEmpty bit is calculated on read from ChipCmd
807 regs->config[0] = 0x0 | (1 << 4); // No boot ROM
808 regs->config[1] = 0xC; //IO mapped and MEM mapped registers available
809 //regs->config[1] = 0x4; //Only IO mapped registers available
810 regs->config3[0] = 0x1; // fast back-to-back compatible
811 regs->config3[1] = 0x0;
814 regs->cscr = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
816 //0x3100 : 100Mbps, full duplex, autonegotiation. 0x2100 : 100Mbps, full duplex
817 regs->bmcr = 0x1000; // autonegotiation
820 regs->bmsr |= 0x0020; // autonegotiation completed
821 regs->bmsr |= 0x0004; // link is up
823 regs->anar = 0x05e1; // all modes, full duplex
824 regs->anlpar = 0x05e1; // all modes, full duplex
825 regs->aner = 0x0001; // autonegotiation supported
827 // reset timer and disable timer interrupt
834 static void rtl8139_9346cr_write(struct rtl8139_state * nic_state, uint32_t val) {
837 PrintDebug("RTL8139: 9346CR write val=0x%02x\n", val);
839 /* mask unwriteable bits */
840 val = SET_MASKED(val, 0x31, nic_state->regs.cmd9346);
842 uint32_t opmode = val & 0xc0;
843 uint32_t eeprom_val = val & 0xf;
845 if (opmode == 0x80) {
847 int eecs = (eeprom_val & 0x08)?1:0;
848 int eesk = (eeprom_val & 0x04)?1:0;
849 int eedi = (eeprom_val & 0x02)?1:0;
850 prom9346_set_wire(nic_state, eecs, eesk, eedi);
851 } else if (opmode == 0x40) {
854 rtl8139_reset(nic_state);
857 nic_state->regs.cmd9346 = val;
860 static uint32_t rtl8139_9346cr_read(struct rtl8139_state * nic_state) {
861 uint32_t ret = nic_state->regs.cmd9346;
862 uint32_t opmode = ret & 0xc0;
864 if (opmode == 0x80) {
866 int eedo = prom9346_get_wire(nic_state);
874 PrintDebug("RTL8139: 9346CR read val=0x%02x\n", ret);
880 static inline int rtl8139_receiver_enabled(struct rtl8139_state * nic_state) {
881 return nic_state->regs.cmd & CMD_Re;
884 static inline int rtl8139_rxwrap(struct rtl8139_state * nic_state) {
885 // wrapping enabled; assume 1.5k more buffer space if size < 64K
886 return (nic_state->regs.rcr & (1 << 7));
889 static void rtl8139_rxbuf_write(struct rtl8139_state * nic_state,
892 struct rtl8139_regs *regs = &(nic_state->regs);
894 addr_t guestpa, host_rxbuf;
896 guestpa = (addr_t)regs->rbstart;
897 v3_gpa_to_hva(&(nic_state->vm->cores[0]), guestpa, &host_rxbuf);
899 //wrap to the front of rx buffer
900 if (regs->cbr + size > nic_state->rx_bufsize){
901 wrap = MOD2(regs->cbr + size, nic_state->rx_bufsize);
903 if (wrap && !(nic_state->rx_bufsize < 64*1024 && rtl8139_rxwrap(nic_state))){
904 PrintDebug("RTL8139: rx packet wrapped in buffer at %d\n", size-wrap);
907 memcpy((void *)(host_rxbuf + regs->cbr), buf, size-wrap);
910 // reset buffer pointer
913 memcpy((void *)(host_rxbuf + regs->cbr), buf + (size-wrap), wrap);
921 memcpy((void *)(host_rxbuf + regs->cbr), buf, size);
926 #define POLYNOMIAL 0x04c11db6
929 static inline int compute_mcast_idx(const uint8_t *ep) {
935 for (i = 0; i < 6; i++) {
937 for (j = 0; j < 8; j++) {
938 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
942 crc = ((crc ^ POLYNOMIAL) | carry);
950 static int rx_one_pkt(struct rtl8139_state * nic_state,
953 struct rtl8139_regs *regs = &(nic_state->regs);
954 uint_t rxbufsize = nic_state->rx_bufsize;
955 uint32_t header, val;
956 uint8_t bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
958 if (regs->rcr & AcceptAllPhys) {
959 PrintDebug("RTL8139: packet received in promiscuous mode\n");
961 if (!memcmp(pkt, bcast_addr, 6)) {
962 if (!(regs->rcr & AcceptBroadcast)){
963 PrintDebug("RTL8139: broadcast packet rejected\n");
966 header |= Rx_Broadcast;
967 PrintDebug("RTL8139: broadcast packet received\n");
968 } else if (pkt[0] & 0x01) {
970 if (!(regs->rcr & AcceptMulticast)){
971 PrintDebug("RTL8139: multicast packet rejected\n");
975 int mcast_idx = compute_mcast_idx(pkt);
977 if (!(regs->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))){
978 PrintDebug("RTL8139: multicast address mismatch\n");
981 header |= Rx_Multicast;
982 PrintDebug("RTL8139: multicast packet received\n");
983 } else if (!compare_ethaddr(regs->id, pkt)){
984 if (!(regs->rcr & AcceptMyPhys)){
985 PrintDebug("RTL8139: rejecting physical address matching packet\n");
989 header |= Rx_Physical;
990 PrintDebug("RTL8139: physical address matching packet received\n");
992 PrintDebug("RTL8139: unknown packet\n");
998 PrintDebug("RTL8139: in ring Rx mode\n");
1000 int avail = MOD2(rxbufsize + regs->capr - regs->cbr, rxbufsize);
1002 if (avail != 0 && len + 8 >= avail){
1003 PrintError("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n",
1004 rxbufsize, regs->cbr, regs->capr, avail, len + 8);
1006 regs->isr |= ISR_Rxovw;
1008 rtl8139_update_irq(nic_state);
1013 header |= ((len << 16) & 0xffff0000);
1015 rtl8139_rxbuf_write(nic_state, (uint8_t *)&header, 4);
1017 rtl8139_rxbuf_write(nic_state, pkt, len);
1020 val = v3_crc32(0, pkt, len);
1022 rtl8139_rxbuf_write(nic_state, (uint8_t *)&val, 4);
1024 // correct buffer write pointer
1025 regs->cbr = MOD2((regs->cbr + 3) & ~0x3, rxbufsize);
1027 PrintDebug("RTL8139: received: rx buffer length %d CBR: 0x%04x CAPR: 0x%04x\n",
1028 rxbufsize, regs->cbr, regs->capr);
1031 regs->isr |= ISR_Rok;
1033 nic_state->statistic.rx_pkts ++;
1034 nic_state->statistic.rx_bytes += len;
1036 rtl8139_update_irq(nic_state);
1041 static int rtl8139_rx(uint8_t * pkt, uint32_t len, void * private_data) {
1042 struct rtl8139_state *nic_state = (struct rtl8139_state *)private_data;
1044 if (!rtl8139_receiver_enabled(nic_state)){
1045 PrintDebug("RTL8139: receiver disabled\n");
1046 nic_state->statistic.rx_dropped ++;
1051 if(rx_one_pkt(nic_state, pkt, len) >= 0){
1052 nic_state->statistic.rx_pkts ++;
1053 nic_state->statistic.rx_bytes += len;
1055 nic_state->statistic.rx_dropped ++;
1061 static void rtl8139_rcr_write(struct rtl8139_state * nic_state, uint32_t val) {
1062 PrintDebug("RTL8139: RCR write val=0x%08x\n", val);
1064 val = SET_MASKED(val, 0xf0fc0040, nic_state->regs.rcr);
1065 nic_state->regs.rcr = val;
1068 uchar_t rblen = (regs->rcr >> 11) & 0x3;
1071 rxbufsize = 1024 * 8 + 16;
1074 rxbufsize = 1024 * 16 + 16;
1077 rxbufsize = 1024 * 32 + 16;
1080 rxbufsize = 1024 * 64 + 16;
1085 // reset buffer size and read/write pointers
1086 rtl8139_reset_rxbuf(nic_state, 8192 << ((nic_state->regs.rcr >> 11) & 0x3));
1088 PrintDebug("RTL8139: RCR write reset buffer size to %d\n", nic_state->rx_bufsize);
1094 static int rtl8139_config_writeable(struct vm_device *dev)
1096 struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
1098 if (nic_state->regs.cmd9346 & CMD9346_Unlock)
1103 PrintDebug("RTL8139: Configuration registers are unwriteable\n");
1110 static inline int transmitter_enabled(struct rtl8139_state * nic_state){
1111 return nic_state->regs.cmd & CMD_Te;
1114 static int rxbufempty(struct rtl8139_state * nic_state){
1115 struct rtl8139_regs *regs = &(nic_state->regs);
1118 unread = MOD2(regs->cbr + nic_state->rx_bufsize - regs->capr, nic_state->rx_bufsize);
1121 PrintDebug("RTL8139: receiver buffer data available 0x%04x\n", unread);
1125 PrintDebug("RTL8139: receiver buffer is empty\n");
1130 static void rtl8139_cmd_write(struct rtl8139_state * nic_state, uint32_t val){
1133 PrintDebug("RTL8139: Cmd write val=0x%08x\n", val);
1136 PrintDebug("RTL8139: Cmd reset\n");
1137 rtl8139_reset(nic_state);
1140 PrintDebug("RTL8139: Cmd enable receiver\n");
1143 PrintDebug("RTL8139: Cmd enable transmitter\n");
1146 val = SET_MASKED(val, 0xe3, nic_state->regs.cmd);
1149 nic_state->regs.cmd = val;
1152 static int tx_one_packet(struct rtl8139_state * nic_state, int descriptor){
1153 struct rtl8139_regs *regs = &(nic_state->regs);
1156 addr_t pkt_gpa = 0, hostva = 0;
1158 if (!transmitter_enabled(nic_state)){
1159 PrintError("RTL8139: fail to send from descriptor %d: transmitter disabled\n", descriptor);
1163 if (regs->tsd[descriptor] & TSD_Own){
1164 PrintError("RTL8139: fail to send from descriptor %d: owned by host\n", descriptor);
1168 txsize = regs->tsd[descriptor] & 0x1fff;
1169 pkt_gpa = (addr_t) regs->tsad[descriptor];
1171 PrintDebug("RTL8139: sending %d bytes from guest memory at 0x%08x\n", txsize, regs->tsad[descriptor]);
1173 v3_gpa_to_hva(&(nic_state->vm->cores[0]), (addr_t)pkt_gpa, &hostva);
1174 pkt = (uchar_t *)hostva;
1176 #ifdef V3_CONFIG_DEBUG_RTL8139
1177 v3_hexdump(pkt, txsize, NULL, 0);
1180 if (TxLoopBack == (regs->tcr & TxLoopBack)){ /* loopback test */
1181 PrintDebug(("RTL8139: transmit loopback mode\n"));
1182 rx_one_pkt(nic_state, pkt, txsize);
1184 if (nic_state->net_ops->send(pkt, txsize, nic_state->backend_data) == 0){
1185 PrintDebug("RTL8139: Sent %d bytes from descriptor %d\n", txsize, descriptor);
1186 nic_state->statistic.tx_pkts ++;
1187 nic_state->statistic.tx_bytes += txsize;
1189 PrintError("Rtl8139: Sending packet error: 0x%p\n", pkt);
1190 nic_state->statistic.tx_dropped ++;
1194 regs->tsd[descriptor] |= TSD_Tok;
1195 regs->tsd[descriptor] |= TSD_Own;
1197 nic_state->regs.isr |= ISR_Tok;
1198 rtl8139_update_irq(nic_state);
1203 /*transmit status registers*/
1204 static void rtl8139_tsd_write(struct rtl8139_state * nic_state,
1207 if (!transmitter_enabled(nic_state)){
1208 PrintDebug("RTL8139: TxStatus write val=0x%08x descriptor=%d, Transmitter not enabled\n", val, descriptor);
1213 PrintDebug("RTL8139: TSD write val=0x%08x descriptor=%d\n", val, descriptor);
1215 // mask read-only bits
1217 val = SET_MASKED(val, 0x00c00000, nic_state->regs.tsd[descriptor]);
1219 nic_state->regs.tsd[descriptor] = val;
1221 tx_one_packet(nic_state, descriptor);
1224 /* transmit status of all descriptors */
1225 static uint16_t rtl8139_txsad_read(struct rtl8139_state * nic_state){
1227 struct rtl8139_regs *regs = &(nic_state->regs);
1229 ret = ((regs->tsd[3] & TSD_Tok)?TSAD_TOK3:0)
1230 |((regs->tsd[2] & TSD_Tok)?TSAD_TOK2:0)
1231 |((regs->tsd[1] & TSD_Tok)?TSAD_TOK1:0)
1232 |((regs->tsd[0] & TSD_Tok)?TSAD_TOK0:0)
1234 |((regs->tsd[3] & TSD_Tun)?TSAD_TUN3:0)
1235 |((regs->tsd[2] & TSD_Tun)?TSAD_TUN2:0)
1236 |((regs->tsd[1] & TSD_Tun)?TSAD_TUN1:0)
1237 |((regs->tsd[0] & TSD_Tun)?TSAD_TUN0:0)
1239 |((regs->tsd[3] & TSD_Tabt)?TSAD_TABT3:0)
1240 |((regs->tsd[2] & TSD_Tabt)?TSAD_TABT2:0)
1241 |((regs->tsd[1] & TSD_Tabt)?TSAD_TABT1:0)
1242 |((regs->tsd[0] & TSD_Tabt)?TSAD_TABT0:0)
1244 |((regs->tsd[3] & TSD_Own)?TSAD_OWN3:0)
1245 |((regs->tsd[2] & TSD_Own)?TSAD_OWN2:0)
1246 |((regs->tsd[1] & TSD_Own)?TSAD_OWN1:0)
1247 |((regs->tsd[0] & TSD_Own)?TSAD_OWN0:0) ;
1249 PrintDebug("RTL8139: txsad read val=0x%04x\n", (int)ret);
1254 static inline void rtl8139_isr_write(struct rtl8139_state * nic_state, uint32_t val) {
1255 struct rtl8139_regs *regs = &(nic_state->regs);
1257 PrintDebug("RTL8139: ISR write val=0x%04x\n", val);
1259 uint16_t newisr = regs->isr & ~val;
1261 /* mask unwriteable bits */
1262 newisr = SET_MASKED(newisr, 0x1e00, regs->isr);
1264 /* writing 1 to interrupt status register bit clears it */
1266 rtl8139_update_irq(nic_state);
1269 rtl8139_update_irq(nic_state);
1272 static int rtl8139_mmio_write(struct guest_info * core,
1279 struct rtl8139_state *nic_state = (struct rtl8139_state *)(priv_data);
1281 idx = guest_addr & 0xff;
1283 memcpy(&val, src, length);
1285 PrintDebug("rtl8139 mmio write: addr:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
1288 case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
1289 nic_state->regs.id[idx - RTL8139_IDR0] = val & 0xff;
1292 case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
1293 nic_state->regs.mult[idx - RTL8139_MAR0] = val & 0xff;
1300 rtl8139_tsd_write(nic_state, (idx - RTL8139_TSD0)/4, val);
1307 nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4] = val;
1310 case RTL8139_RBSTART:
1311 nic_state->regs.rbstart = val;
1314 nic_state->regs.erbcr = val & 0xffff;
1317 //nic_state->regs.ersr = val & 0xff;
1318 nic_state->regs.ersr &= (~val) & 0x0c;
1321 rtl8139_cmd_write(nic_state, val);
1326 /* this value is off by 16 */
1327 nic_state->regs.capr = MOD2(val + 0x10, nic_state->rx_bufsize);
1329 PrintDebug("RTL 8139: CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
1330 nic_state->rx_bufsize, nic_state->regs.cbr, nic_state->regs.capr);
1333 case RTL8139_CBR: /* read only */
1334 //nic_state->regs.cbr = val & 0xffff;
1338 PrintDebug("RTL8139: IMR write val=0x%04x\n", val);
1340 /* mask unwriteable bits */
1341 val = SET_MASKED(val, 0x1e00, nic_state->regs.imr);
1342 nic_state->regs.imr = val;
1343 rtl8139_update_irq(nic_state);
1347 rtl8139_isr_write(nic_state, val);
1350 nic_state->regs.tcr = val;
1353 rtl8139_rcr_write(nic_state, val);
1356 nic_state->regs.tctr = 0; /* write clear current tick */
1359 nic_state->regs.mpc = 0; /* clear on write */
1361 case RTL8139_9346CR:
1362 rtl8139_9346cr_write(nic_state, val);
1364 case RTL8139_CONFIG0:
1365 nic_state->regs.config[0] = val & 0xff;
1367 case RTL8139_CONFIG1:
1368 nic_state->regs.config[1] = val & 0xff;
1370 case RTL8139_TimerInt:
1371 nic_state->regs.timer_int = val;
1374 nic_state->regs.msr = val & 0xff;
1376 case RTL8139_CONFIG3:
1377 nic_state->regs.config3[0] = val & 0xff;
1379 case RTL8139_CONFIG4:
1380 nic_state->regs.config3[1] = val & 0xff;
1383 case RTL8139_MULINT:
1384 nic_state->regs.mulint = val & 0xffff;
1387 nic_state->regs.rerid = val & 0xffff;
1390 nic_state->regs.txsad = val & 0xffff;
1393 nic_state->regs.bmcr = val & 0xffff;
1396 nic_state->regs.bmsr = val & 0xffff;
1399 nic_state->regs.anar = val & 0xffff;
1401 case RTL8139_ANLPAR:
1402 nic_state->regs.anlpar = val & 0xffff;
1405 nic_state->regs.aner = val & 0xffff;
1408 nic_state->regs.dis = val & 0xffff;
1411 nic_state->regs.fcsc = val & 0xffff;
1413 case RTL8139_NWAYTR:
1414 nic_state->regs.nwaytr = val & 0xffff;
1417 nic_state->regs.rec = val & 0xffff;
1421 nic_state->regs.cscr = val;
1423 case RTL8139_PHY1_PARM:
1424 nic_state->regs.phy1_parm = val;
1426 case RTL8139_TW_PARM:
1427 nic_state->regs.tw_parm = val & 0xffff;
1429 case RTL8139_PHY2_PARM:
1430 nic_state->regs.phy2_parm = val;
1432 case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
1433 nic_state->regs.crc[idx - RTL8139_CRC0] = val & 0xff;
1436 case RTL8139_Config5:
1437 nic_state->regs.config5 = val & 0xff;
1440 PrintDebug("rtl8139 write error: invalid port: 0x%x\n", idx);
1446 static int rtl8139_mmio_read(struct guest_info * core,
1453 struct rtl8139_state *nic_state = (struct rtl8139_state *)priv_data;
1455 idx = guest_addr & 0xff;
1458 case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
1459 val = nic_state->regs.id[idx - RTL8139_IDR0];
1462 case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
1463 val = nic_state->regs.mult[idx - RTL8139_MAR0];
1470 val = nic_state->regs.tsd[(idx - RTL8139_TSD0)/4];
1477 val = nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4];
1480 case RTL8139_RBSTART:
1481 val = nic_state->regs.rbstart;
1484 val = nic_state->regs.erbcr;
1487 val = nic_state->regs.ersr;
1491 val = nic_state->regs.cmd;
1492 if (rxbufempty(nic_state)){
1498 /* this value is off by 16 -- don't know why - Lei*/
1499 val = nic_state->regs.capr - 0x10;
1502 val = nic_state->regs.cbr;
1505 val = nic_state->regs.imr;
1508 val = (uint32_t)nic_state->regs.isr;
1511 val = nic_state->regs.tcr;
1514 val = nic_state->regs.rcr;
1517 val = nic_state->regs.tctr;
1520 val = nic_state->regs.mpc;
1522 case RTL8139_9346CR:
1523 val = rtl8139_9346cr_read(nic_state);
1525 case RTL8139_CONFIG0:
1526 val = nic_state->regs.config[0];
1528 case RTL8139_CONFIG1:
1529 val = nic_state->regs.config[1];
1531 case RTL8139_TimerInt:
1532 val = nic_state->regs.timer_int;
1535 val = nic_state->regs.msr;
1537 case RTL8139_CONFIG3:
1538 val = nic_state->regs.config3[0];
1540 case RTL8139_CONFIG4:
1541 val = nic_state->regs.config3[1];
1543 case RTL8139_MULINT:
1544 val = nic_state->regs.mulint;
1547 val = nic_state->regs.rerid;
1550 val = rtl8139_txsad_read(nic_state);
1553 val = nic_state->regs.bmcr;
1556 val = nic_state->regs.bmsr;
1559 val = nic_state->regs.anar;
1561 case RTL8139_ANLPAR:
1562 val = nic_state->regs.anlpar;
1565 val = nic_state->regs.aner;
1568 val = nic_state->regs.dis;
1571 val = nic_state->regs.fcsc;
1573 case RTL8139_NWAYTR:
1574 val = nic_state->regs.nwaytr;
1577 val = nic_state->regs.rec;
1580 val = nic_state->regs.cscr;
1582 case RTL8139_PHY1_PARM:
1583 val = nic_state->regs.phy1_parm;
1585 case RTL8139_TW_PARM:
1586 val = nic_state->regs.tw_parm;
1588 case RTL8139_PHY2_PARM:
1589 val = nic_state->regs.phy2_parm;
1591 case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
1592 val = nic_state->regs.crc[idx - RTL8139_CRC0];
1594 case RTL8139_Config5:
1595 val = nic_state->regs.config5;
1602 memcpy(dst, &val, length);
1604 PrintDebug("rtl8139 mmio read: port:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
1610 static int rtl8139_ioport_write(struct guest_info * core,
1614 void * private_data) {
1615 return rtl8139_mmio_write(core, (addr_t)port,
1616 src, length, private_data);
1619 static int rtl8139_ioport_read(struct guest_info * core,
1623 void * private_data) {
1624 return rtl8139_mmio_read(core, (addr_t)port,
1625 dst, length, private_data);
1629 static int rtl8139_init_state(struct rtl8139_state *nic_state) {
1630 PrintDebug("rtl8139: init_state\n");
1632 nic_state->regs.tsd[0] = nic_state->regs.tsd[1] = nic_state->regs.tsd[2] = nic_state->regs.tsd[3] = TSD_Own;
1634 nic_state->regs.rerid = RTL8139_PCI_REVID_8139;
1635 nic_state->regs.tcr |= ((0x1d << 26) | (0x1 << 22));
1637 rtl8139_reset(nic_state);
1644 static inline int rtl8139_reset_device(struct rtl8139_state * nic_state) {
1645 nic_state->regs.cmd |= CMD_Rst;
1646 rtl8139_init_state(nic_state);
1647 nic_state->regs.cmd &= ~CMD_Rst;
1652 static inline int rtl8139_start_device(struct rtl8139_state * nic_state) {
1653 nic_state->regs.cmd |= CMD_Re | CMD_Te;
1658 static int rtl8139_stop_device(struct rtl8139_state * nic_state) {
1659 PrintDebug("rtl8139: stop device\n");
1661 nic_state->regs.cmd &= ~(CMD_Re | CMD_Te);
1666 static int rtl8139_hook_iospace(struct rtl8139_state * nic_state,
1673 if (base_addr <= 0){
1674 PrintError("In RTL8139: Fail to Hook IO Space, base address 0x%x\n", (int) base_addr);
1678 if (type == PCI_BAR_IO){
1679 PrintDebug("In RTL8139: Hook IO ports starting from %x, size %d\n", (int) base_addr, size);
1681 for (i = 0; i < 0xff; i++){
1682 v3_dev_hook_io(nic_state->dev, base_addr + i, &rtl8139_ioport_read, &rtl8139_ioport_write);
1684 } else if (type == PCI_BAR_MEM32) {
1685 PrintDebug("In RTL8139: Hook memory space starting from %x, size %d\n", (int) base_addr, size);
1687 //hook memory mapped I/O
1688 v3_hook_full_mem(nic_state->vm, nic_state->vm->cores[0].cpu_id, base_addr, base_addr + 0xff,
1689 &rtl8139_mmio_read, &rtl8139_mmio_write, nic_state);
1691 PrintError("In RTL8139: unknown memory type: start %x, size %d\n", (int) base_addr, size);
1698 static int register_dev(struct rtl8139_state * nic_state) {
1701 if (nic_state->pci_bus == NULL) {
1702 PrintError("RTL8139: Not attached to any PCI bus\n");
1707 struct v3_pci_bar bars[6];
1708 struct pci_device * pci_dev = NULL;
1710 for (i = 0; i < 6; i++) {
1711 bars[i].type = PCI_BAR_NONE;
1714 bars[0].type = PCI_BAR_IO;
1715 bars[0].default_base_port = 0xc100;
1716 bars[0].num_ports = 0x100;
1718 bars[0].io_read = rtl8139_ioport_read;
1719 bars[0].io_write = rtl8139_ioport_write;
1720 bars[0].private_data = nic_state;
1723 bars[1].type = PCI_BAR_MEM32;
1724 bars[1].default_base_addr = -1;
1725 bars[1].num_pages = 1;
1727 bars[1].mem_read = rtl8139_mmio_read;
1728 bars[1].mem_write = rtl8139_mmio_write;
1729 bars[1].private_data = nic_state;
1732 pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
1734 NULL, NULL, NULL, nic_state);
1737 if (pci_dev == NULL) {
1738 PrintError("RTL8139: Could not register PCI Device\n");
1742 pci_dev->config_header.vendor_id = 0x10ec;
1743 pci_dev->config_header.device_id = 0x8139;
1744 pci_dev->config_header.command = 0x05;
1746 pci_dev->config_header.revision = RTL8139_PCI_REVID_8139;
1748 pci_dev->config_header.subclass = 0x00;
1749 pci_dev->config_header.class = 0x02;
1750 pci_dev->config_header.header_type = 0x00;
1752 pci_dev->config_header.intr_line = 12;
1753 pci_dev->config_header.intr_pin = 1;
1754 pci_dev->config_space[0x34] = 0xdc;
1756 nic_state->pci_dev = pci_dev;
1761 static int connect_fn(struct v3_vm_info * info,
1762 void * frontend_data,
1763 struct v3_dev_net_ops * ops,
1764 v3_cfg_tree_t * cfg,
1765 void * private_data) {
1766 struct rtl8139_state * nic_state = (struct rtl8139_state *)frontend_data;
1768 rtl8139_init_state(nic_state);
1769 register_dev(nic_state);
1771 nic_state->net_ops = ops;
1772 nic_state->backend_data = private_data;
1774 ops->recv = rtl8139_rx;
1776 ops->config.frontend_data = nic_state;
1777 memcpy(ops->config.fnt_mac, nic_state->mac, ETH_ALEN);
1783 static int rtl8139_free(void * private_data) {
1784 struct rtl8139_state * nic_state = (struct rtl8139_state *)private_data;
1786 /* dettached from backend */
1788 /* unregistered from PCI? */
1796 static struct v3_device_ops dev_ops = {
1797 .free = rtl8139_free,
1801 static int rtl8139_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1802 struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
1803 struct rtl8139_state * nic_state = NULL;
1804 char * dev_id = v3_cfg_val(cfg, "ID");
1805 char * macstr = v3_cfg_val(cfg, "mac");
1807 nic_state = (struct rtl8139_state *)V3_Malloc(sizeof(struct rtl8139_state));
1808 memset(nic_state, 0, sizeof(struct rtl8139_state));
1810 nic_state->pci_bus = pci_bus;
1813 if (macstr != NULL && !str2mac(macstr, nic_state->mac)) {
1814 PrintDebug("RTL8139: Mac specified %s\n", macstr);
1816 PrintDebug("RTL8139: MAC not specified\n");
1817 random_ethaddr(nic_state->mac);
1820 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, nic_state);
1823 PrintError("RTL8139: Could not attach device %s\n", dev_id);
1828 nic_state->dev = dev;
1830 if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)nic_state) == -1) {
1831 PrintError("RTL8139: Could not register %s as net frontend\n", dev_id);
1832 v3_remove_device(dev);
1840 device_register("RTL8139", rtl8139_init)