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 uint16_t rx_bad_align : 1;
176 uint16_t rx_crc_err : 1;
177 uint16_t rx_too_long : 1;
178 uint16_t rx_runt : 1;
179 uint16_t rx_bad_sym : 1;
180 uint16_t reserved : 7;
181 uint16_t rx_brdcast : 1;
182 uint16_t rx_phys : 1;
183 uint16_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 uint16_t pun_linkchg : 1;
279 uint16_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);
586 nic_state->statistic.tx_interrupts ++;
590 static void prom9346_decode_command(struct EEprom9346 * eeprom, uint8_t command) {
591 PrintDebug("RTL8139: eeprom command 0x%02x\n", command);
593 switch (command & Chip9346_op_mask) {
594 case Chip9346_op_read:
596 eeprom->address = command & EEPROM_9346_ADDR_MASK;
597 eeprom->output = eeprom->contents[eeprom->address];
600 eeprom->mode = Chip9346_data_read;
601 PrintDebug("RTL8139: eeprom read from address 0x%02x data=0x%04x\n",
602 eeprom->address, eeprom->output);
606 case Chip9346_op_write:
608 eeprom->address = command & EEPROM_9346_ADDR_MASK;
611 eeprom->mode = Chip9346_none; /* Chip9346_data_write */
612 PrintDebug("RTL8139: eeprom begin write to address 0x%02x\n",
617 eeprom->mode = Chip9346_none;
618 switch (command & Chip9346_op_ext_mask) {
619 case Chip9346_op_write_enable:
620 PrintDebug("RTL8139: eeprom write enabled\n");
622 case Chip9346_op_write_all:
623 PrintDebug("RTL8139: eeprom begin write all\n");
625 case Chip9346_op_write_disable:
626 PrintDebug("RTL8139: eeprom write disabled\n");
633 static void prom9346_shift_clock(struct EEprom9346 * eeprom) {
634 int bit = eeprom->eedi?1:0;
638 PrintDebug("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo);
640 switch (eeprom->mode) {
641 case Chip9346_enter_command_mode:
643 eeprom->mode = Chip9346_read_command;
646 PrintDebug("eeprom: +++ synchronized, begin command read\n");
650 case Chip9346_read_command:
651 eeprom->input = (eeprom->input << 1) | (bit & 1);
652 if (eeprom->tick == 8) {
653 prom9346_decode_command(eeprom, eeprom->input & 0xff);
657 case Chip9346_data_read:
658 eeprom->eedo = (eeprom->output & 0x8000)?1:0;
659 eeprom->output <<= 1;
660 if (eeprom->tick == 16){
662 // the FreeBSD drivers (rl and re) don't explicitly toggle
663 // CS between reads (or does setting Cfg9346 to 0 count too?),
664 // so we need to enter wait-for-command state here
665 eeprom->mode = Chip9346_enter_command_mode;
669 PrintDebug("eeprom: +++ end of read, awaiting next command\n");
671 // original behaviour
673 eeprom->address &= EEPROM_9346_ADDR_MASK;
674 eeprom->output = eeprom->contents[eeprom->address];
677 DEBUG_PRINT(("eeprom: +++ read next address 0x%02x data=0x%04x\n",
678 eeprom->address, eeprom->output));
683 case Chip9346_data_write:
684 eeprom->input = (eeprom->input << 1) | (bit & 1);
685 if (eeprom->tick == 16) {
686 PrintDebug("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
687 eeprom->address, eeprom->input);
689 eeprom->contents[eeprom->address] = eeprom->input;
690 eeprom->mode = Chip9346_none; /* waiting for next command after CS cycle */
696 case Chip9346_data_write_all:
697 eeprom->input = (eeprom->input << 1) | (bit & 1);
698 if (eeprom->tick == 16) {
700 for (i = 0; i < EEPROM_9346_SIZE; i++)
702 eeprom->contents[i] = eeprom->input;
704 PrintDebug("RTL8139: eeprom filled with data=0x%04x\n",
707 eeprom->mode = Chip9346_enter_command_mode;
718 static int prom9346_get_wire(struct rtl8139_state * nic_state) {
719 struct EEprom9346 *eeprom = &(nic_state->eeprom);
721 if (eeprom->eecs == 0)
727 static void prom9346_set_wire(struct rtl8139_state * nic_state,
731 struct EEprom9346 *eeprom = &(nic_state->eeprom);
732 uint8_t old_eecs = eeprom->eecs;
733 uint8_t old_eesk = eeprom->eesk;
739 PrintDebug("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
740 eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo);
742 if (old_eecs == 0 && eecs) {
743 /* Synchronize start */
747 eeprom->mode = Chip9346_enter_command_mode;
749 PrintDebug("=== eeprom: begin access, enter command mode\n");
753 PrintDebug("=== eeprom: end access\n");
757 if (!old_eesk && eesk) {
759 prom9346_shift_clock(eeprom);
764 static inline void rtl8139_reset_rxbuf(struct rtl8139_state * nic_state, uint32_t bufsize) {
765 nic_state->rx_bufsize = bufsize;
766 nic_state->regs.capr = 0;
767 nic_state->regs.cbr = 0;
771 static void rtl8139_reset(struct rtl8139_state *nic_state) {
772 struct rtl8139_regs *regs = &(nic_state->regs);
775 PrintDebug("Rtl8139: Reset\n");
777 /* restore MAC address */
778 memcpy(regs->id, nic_state->mac, ETH_ALEN);
779 memset(regs->mult, 0xff, 8);
781 rtl8139_update_irq(nic_state);
784 nic_state->eeprom.contents[0] = 0x8129;
786 // PCI vendor and device ID
787 nic_state->eeprom.contents[1] = 0x10ec;
788 nic_state->eeprom.contents[2] = 0x8139;
790 nic_state->eeprom.contents[7] = nic_state->mac[0] | nic_state->mac[1] << 8;
791 nic_state->eeprom.contents[8] = nic_state->mac[2] | nic_state->mac[3] << 8;
792 nic_state->eeprom.contents[9] = nic_state->mac[4] | nic_state->mac[5] << 8;
794 for (i = 0; i < 4; ++i) {
795 regs->tsd[i] = TSD_Own;
798 rtl8139_reset_rxbuf(nic_state, 1024*8);
803 regs->tcr |= ((0x1d << 26) | (0x1 << 22)); // RTL-8139D
804 regs->rerid = RTL8139_PCI_REVID_8139;
806 regs->cmd = CMD_Rst; //RxBufEmpty bit is calculated on read from ChipCmd
808 regs->config[0] = 0x0 | (1 << 4); // No boot ROM
809 regs->config[1] = 0xC; //IO mapped and MEM mapped registers available
810 //regs->config[1] = 0x4; //Only IO mapped registers available
811 regs->config3[0] = 0x1; // fast back-to-back compatible
812 regs->config3[1] = 0x0;
815 regs->cscr = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
817 //0x3100 : 100Mbps, full duplex, autonegotiation. 0x2100 : 100Mbps, full duplex
818 regs->bmcr = 0x1000; // autonegotiation
821 regs->bmsr |= 0x0020; // autonegotiation completed
822 regs->bmsr |= 0x0004; // link is up
824 regs->anar = 0x05e1; // all modes, full duplex
825 regs->anlpar = 0x05e1; // all modes, full duplex
826 regs->aner = 0x0001; // autonegotiation supported
828 // reset timer and disable timer interrupt
835 static void rtl8139_9346cr_write(struct rtl8139_state * nic_state, uint32_t val) {
838 PrintDebug("RTL8139: 9346CR write val=0x%02x\n", val);
840 /* mask unwriteable bits */
841 val = SET_MASKED(val, 0x31, nic_state->regs.cmd9346);
843 uint32_t opmode = val & 0xc0;
844 uint32_t eeprom_val = val & 0xf;
846 if (opmode == 0x80) {
848 int eecs = (eeprom_val & 0x08)?1:0;
849 int eesk = (eeprom_val & 0x04)?1:0;
850 int eedi = (eeprom_val & 0x02)?1:0;
851 prom9346_set_wire(nic_state, eecs, eesk, eedi);
852 } else if (opmode == 0x40) {
855 rtl8139_reset(nic_state);
858 nic_state->regs.cmd9346 = val;
861 static uint32_t rtl8139_9346cr_read(struct rtl8139_state * nic_state) {
862 uint32_t ret = nic_state->regs.cmd9346;
863 uint32_t opmode = ret & 0xc0;
865 if (opmode == 0x80) {
867 int eedo = prom9346_get_wire(nic_state);
875 PrintDebug("RTL8139: 9346CR read val=0x%02x\n", ret);
881 static inline int rtl8139_receiver_enabled(struct rtl8139_state * nic_state) {
882 return nic_state->regs.cmd & CMD_Re;
885 static inline int rtl8139_rxwrap(struct rtl8139_state * nic_state) {
886 // wrapping enabled; assume 1.5k more buffer space if size < 64K
887 return (nic_state->regs.rcr & (1 << 7));
890 static void rtl8139_rxbuf_write(struct rtl8139_state * nic_state,
893 struct rtl8139_regs *regs = &(nic_state->regs);
895 addr_t guestpa, host_rxbuf;
897 guestpa = (addr_t)regs->rbstart;
898 v3_gpa_to_hva(&(nic_state->vm->cores[0]), guestpa, &host_rxbuf);
900 //wrap to the front of rx buffer
901 if (regs->cbr + size > nic_state->rx_bufsize){
902 wrap = MOD2(regs->cbr + size, nic_state->rx_bufsize);
904 if (wrap && !(nic_state->rx_bufsize < 64*1024 && rtl8139_rxwrap(nic_state))){
905 PrintDebug("RTL8139: rx packet wrapped in buffer at %d\n", size-wrap);
908 memcpy((void *)(host_rxbuf + regs->cbr), buf, size-wrap);
911 // reset buffer pointer
914 memcpy((void *)(host_rxbuf + regs->cbr), buf + (size-wrap), wrap);
922 memcpy((void *)(host_rxbuf + regs->cbr), buf, size);
927 #define POLYNOMIAL 0x04c11db6
930 static inline int compute_mcast_idx(const uint8_t *ep) {
936 for (i = 0; i < 6; i++) {
938 for (j = 0; j < 8; j++) {
939 carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
943 crc = ((crc ^ POLYNOMIAL) | carry);
951 static int rx_one_pkt(struct rtl8139_state * nic_state,
954 struct rtl8139_regs *regs = &(nic_state->regs);
955 uint_t rxbufsize = nic_state->rx_bufsize;
956 uint32_t header, val;
957 uint8_t bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
959 if (regs->rcr & AcceptAllPhys) {
960 PrintDebug("RTL8139: packet received in promiscuous mode\n");
962 if (!memcmp(pkt, bcast_addr, 6)) {
963 if (!(regs->rcr & AcceptBroadcast)){
964 PrintDebug("RTL8139: broadcast packet rejected\n");
967 header |= Rx_Broadcast;
968 PrintDebug("RTL8139: broadcast packet received\n");
969 } else if (pkt[0] & 0x01) {
971 if (!(regs->rcr & AcceptMulticast)){
972 PrintDebug("RTL8139: multicast packet rejected\n");
976 int mcast_idx = compute_mcast_idx(pkt);
978 if (!(regs->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))){
979 PrintDebug("RTL8139: multicast address mismatch\n");
982 header |= Rx_Multicast;
983 PrintDebug("RTL8139: multicast packet received\n");
984 } else if (!compare_ethaddr(regs->id, pkt)){
985 if (!(regs->rcr & AcceptMyPhys)){
986 PrintDebug("RTL8139: rejecting physical address matching packet\n");
990 header |= Rx_Physical;
991 PrintDebug("RTL8139: physical address matching packet received\n");
993 PrintDebug("RTL8139: unknown packet\n");
999 PrintDebug("RTL8139: in ring Rx mode\n");
1001 int avail = MOD2(rxbufsize + regs->capr - regs->cbr, rxbufsize);
1003 if (avail != 0 && len + 8 >= avail){
1004 PrintError("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n",
1005 rxbufsize, regs->cbr, regs->capr, avail, len + 8);
1007 regs->isr |= ISR_Rxovw;
1009 rtl8139_update_irq(nic_state);
1014 header |= ((len << 16) & 0xffff0000);
1016 rtl8139_rxbuf_write(nic_state, (uint8_t *)&header, 4);
1018 rtl8139_rxbuf_write(nic_state, pkt, len);
1021 val = v3_crc32(0, pkt, len);
1023 rtl8139_rxbuf_write(nic_state, (uint8_t *)&val, 4);
1025 // correct buffer write pointer
1026 regs->cbr = MOD2((regs->cbr + 3) & ~0x3, rxbufsize);
1028 PrintDebug("RTL8139: received: rx buffer length %d CBR: 0x%04x CAPR: 0x%04x\n",
1029 rxbufsize, regs->cbr, regs->capr);
1032 regs->isr |= ISR_Rok;
1034 nic_state->statistic.rx_pkts ++;
1035 nic_state->statistic.rx_bytes += len;
1037 rtl8139_update_irq(nic_state);
1042 static int rtl8139_rx(uint8_t * pkt, uint32_t len, void * private_data) {
1043 struct rtl8139_state *nic_state = (struct rtl8139_state *)private_data;
1045 if (!rtl8139_receiver_enabled(nic_state)){
1046 PrintDebug("RTL8139: receiver disabled\n");
1047 nic_state->statistic.rx_dropped ++;
1052 if(rx_one_pkt(nic_state, pkt, len) >= 0){
1053 nic_state->statistic.rx_pkts ++;
1054 nic_state->statistic.rx_bytes += len;
1056 nic_state->statistic.rx_dropped ++;
1062 static void rtl8139_rcr_write(struct rtl8139_state * nic_state, uint32_t val) {
1063 PrintDebug("RTL8139: RCR write val=0x%08x\n", val);
1065 val = SET_MASKED(val, 0xf0fc0040, nic_state->regs.rcr);
1066 nic_state->regs.rcr = val;
1069 uchar_t rblen = (regs->rcr >> 11) & 0x3;
1072 rxbufsize = 1024 * 8 + 16;
1075 rxbufsize = 1024 * 16 + 16;
1078 rxbufsize = 1024 * 32 + 16;
1081 rxbufsize = 1024 * 64 + 16;
1086 // reset buffer size and read/write pointers
1087 rtl8139_reset_rxbuf(nic_state, 8192 << ((nic_state->regs.rcr >> 11) & 0x3));
1089 PrintDebug("RTL8139: RCR write reset buffer size to %d\n", nic_state->rx_bufsize);
1095 static int rtl8139_config_writeable(struct vm_device *dev)
1097 struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
1099 if (nic_state->regs.cmd9346 & CMD9346_Unlock)
1104 PrintDebug("RTL8139: Configuration registers are unwriteable\n");
1111 static inline int transmitter_enabled(struct rtl8139_state * nic_state){
1112 return nic_state->regs.cmd & CMD_Te;
1115 static int rxbufempty(struct rtl8139_state * nic_state){
1116 struct rtl8139_regs *regs = &(nic_state->regs);
1119 unread = MOD2(regs->cbr + nic_state->rx_bufsize - regs->capr, nic_state->rx_bufsize);
1122 PrintDebug("RTL8139: receiver buffer data available 0x%04x\n", unread);
1126 PrintDebug("RTL8139: receiver buffer is empty\n");
1131 static void rtl8139_cmd_write(struct rtl8139_state * nic_state, uint32_t val){
1134 PrintDebug("RTL8139: Cmd write val=0x%08x\n", val);
1137 PrintDebug("RTL8139: Cmd reset\n");
1138 rtl8139_reset(nic_state);
1141 PrintDebug("RTL8139: Cmd enable receiver\n");
1144 PrintDebug("RTL8139: Cmd enable transmitter\n");
1147 val = SET_MASKED(val, 0xe3, nic_state->regs.cmd);
1150 nic_state->regs.cmd = val;
1153 static int tx_one_packet(struct rtl8139_state * nic_state, int descriptor){
1154 struct rtl8139_regs *regs = &(nic_state->regs);
1157 addr_t pkt_gpa = 0, hostva = 0;
1159 if (!transmitter_enabled(nic_state)){
1160 PrintError("RTL8139: fail to send from descriptor %d: transmitter disabled\n", descriptor);
1164 if (regs->tsd[descriptor] & TSD_Own){
1165 PrintError("RTL8139: fail to send from descriptor %d: owned by host\n", descriptor);
1169 txsize = regs->tsd[descriptor] & 0x1fff;
1170 pkt_gpa = (addr_t) regs->tsad[descriptor];
1172 PrintDebug("RTL8139: sending %d bytes from guest memory at 0x%08x\n", txsize, regs->tsad[descriptor]);
1174 v3_gpa_to_hva(&(nic_state->vm->cores[0]), (addr_t)pkt_gpa, &hostva);
1175 pkt = (uchar_t *)hostva;
1177 #ifdef V3_CONFIG_DEBUG_RTL8139
1178 v3_hexdump(pkt, txsize, NULL, 0);
1181 if (TxLoopBack == (regs->tcr & TxLoopBack)){ /* loopback test */
1182 PrintDebug(("RTL8139: transmit loopback mode\n"));
1183 rx_one_pkt(nic_state, pkt, txsize);
1185 if (nic_state->net_ops->send(pkt, txsize, nic_state->backend_data) == 0){
1186 PrintDebug("RTL8139: Sent %d bytes from descriptor %d\n", txsize, descriptor);
1187 nic_state->statistic.tx_pkts ++;
1188 nic_state->statistic.tx_bytes += txsize;
1190 PrintError("Rtl8139: Sending packet error: 0x%p\n", pkt);
1191 nic_state->statistic.tx_dropped ++;
1195 regs->tsd[descriptor] |= TSD_Tok;
1196 regs->tsd[descriptor] |= TSD_Own;
1198 nic_state->regs.isr |= ISR_Tok;
1199 rtl8139_update_irq(nic_state);
1204 /*transmit status registers*/
1205 static void rtl8139_tsd_write(struct rtl8139_state * nic_state,
1208 if (!transmitter_enabled(nic_state)){
1209 PrintDebug("RTL8139: TxStatus write val=0x%08x descriptor=%d, Transmitter not enabled\n", val, descriptor);
1214 PrintDebug("RTL8139: TSD write val=0x%08x descriptor=%d\n", val, descriptor);
1216 // mask read-only bits
1218 val = SET_MASKED(val, 0x00c00000, nic_state->regs.tsd[descriptor]);
1220 nic_state->regs.tsd[descriptor] = val;
1222 tx_one_packet(nic_state, descriptor);
1225 /* transmit status of all descriptors */
1226 static uint16_t rtl8139_txsad_read(struct rtl8139_state * nic_state){
1228 struct rtl8139_regs *regs = &(nic_state->regs);
1230 ret = ((regs->tsd[3] & TSD_Tok)?TSAD_TOK3:0)
1231 |((regs->tsd[2] & TSD_Tok)?TSAD_TOK2:0)
1232 |((regs->tsd[1] & TSD_Tok)?TSAD_TOK1:0)
1233 |((regs->tsd[0] & TSD_Tok)?TSAD_TOK0:0)
1235 |((regs->tsd[3] & TSD_Tun)?TSAD_TUN3:0)
1236 |((regs->tsd[2] & TSD_Tun)?TSAD_TUN2:0)
1237 |((regs->tsd[1] & TSD_Tun)?TSAD_TUN1:0)
1238 |((regs->tsd[0] & TSD_Tun)?TSAD_TUN0:0)
1240 |((regs->tsd[3] & TSD_Tabt)?TSAD_TABT3:0)
1241 |((regs->tsd[2] & TSD_Tabt)?TSAD_TABT2:0)
1242 |((regs->tsd[1] & TSD_Tabt)?TSAD_TABT1:0)
1243 |((regs->tsd[0] & TSD_Tabt)?TSAD_TABT0:0)
1245 |((regs->tsd[3] & TSD_Own)?TSAD_OWN3:0)
1246 |((regs->tsd[2] & TSD_Own)?TSAD_OWN2:0)
1247 |((regs->tsd[1] & TSD_Own)?TSAD_OWN1:0)
1248 |((regs->tsd[0] & TSD_Own)?TSAD_OWN0:0) ;
1250 PrintDebug("RTL8139: txsad read val=0x%04x\n", (int)ret);
1255 static inline void rtl8139_isr_write(struct rtl8139_state * nic_state, uint32_t val) {
1256 struct rtl8139_regs *regs = &(nic_state->regs);
1258 PrintDebug("RTL8139: ISR write val=0x%04x\n", val);
1260 uint16_t newisr = regs->isr & ~val;
1262 /* mask unwriteable bits */
1263 newisr = SET_MASKED(newisr, 0x1e00, regs->isr);
1265 /* writing 1 to interrupt status register bit clears it */
1267 rtl8139_update_irq(nic_state);
1270 rtl8139_update_irq(nic_state);
1273 static int rtl8139_mmio_write(struct guest_info * core,
1280 struct rtl8139_state *nic_state = (struct rtl8139_state *)(priv_data);
1282 idx = guest_addr & 0xff;
1284 memcpy(&val, src, length);
1286 PrintDebug("rtl8139 mmio write: addr:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
1289 case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
1290 nic_state->regs.id[idx - RTL8139_IDR0] = val & 0xff;
1293 case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
1294 nic_state->regs.mult[idx - RTL8139_MAR0] = val & 0xff;
1301 rtl8139_tsd_write(nic_state, (idx - RTL8139_TSD0)/4, val);
1308 nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4] = val;
1311 case RTL8139_RBSTART:
1312 nic_state->regs.rbstart = val;
1315 nic_state->regs.erbcr = val & 0xffff;
1318 //nic_state->regs.ersr = val & 0xff;
1319 nic_state->regs.ersr &= (~val) & 0x0c;
1322 rtl8139_cmd_write(nic_state, val);
1327 /* this value is off by 16 */
1328 nic_state->regs.capr = MOD2(val + 0x10, nic_state->rx_bufsize);
1330 PrintDebug("RTL 8139: CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
1331 nic_state->rx_bufsize, nic_state->regs.cbr, nic_state->regs.capr);
1334 case RTL8139_CBR: /* read only */
1335 //nic_state->regs.cbr = val & 0xffff;
1339 PrintDebug("RTL8139: IMR write val=0x%04x\n", val);
1341 /* mask unwriteable bits */
1342 val = SET_MASKED(val, 0x1e00, nic_state->regs.imr);
1343 nic_state->regs.imr = val;
1344 rtl8139_update_irq(nic_state);
1348 rtl8139_isr_write(nic_state, val);
1351 nic_state->regs.tcr = val;
1354 rtl8139_rcr_write(nic_state, val);
1357 nic_state->regs.tctr = 0; /* write clear current tick */
1360 nic_state->regs.mpc = 0; /* clear on write */
1362 case RTL8139_9346CR:
1363 rtl8139_9346cr_write(nic_state, val);
1365 case RTL8139_CONFIG0:
1366 nic_state->regs.config[0] = val & 0xff;
1368 case RTL8139_CONFIG1:
1369 nic_state->regs.config[1] = val & 0xff;
1371 case RTL8139_TimerInt:
1372 nic_state->regs.timer_int = val;
1375 nic_state->regs.msr = val & 0xff;
1377 case RTL8139_CONFIG3:
1378 nic_state->regs.config3[0] = val & 0xff;
1380 case RTL8139_CONFIG4:
1381 nic_state->regs.config3[1] = val & 0xff;
1384 case RTL8139_MULINT:
1385 nic_state->regs.mulint = val & 0xffff;
1388 nic_state->regs.rerid = val & 0xffff;
1391 nic_state->regs.txsad = val & 0xffff;
1394 nic_state->regs.bmcr = val & 0xffff;
1397 nic_state->regs.bmsr = val & 0xffff;
1400 nic_state->regs.anar = val & 0xffff;
1402 case RTL8139_ANLPAR:
1403 nic_state->regs.anlpar = val & 0xffff;
1406 nic_state->regs.aner = val & 0xffff;
1409 nic_state->regs.dis = val & 0xffff;
1412 nic_state->regs.fcsc = val & 0xffff;
1414 case RTL8139_NWAYTR:
1415 nic_state->regs.nwaytr = val & 0xffff;
1418 nic_state->regs.rec = val & 0xffff;
1422 nic_state->regs.cscr = val;
1424 case RTL8139_PHY1_PARM:
1425 nic_state->regs.phy1_parm = val;
1427 case RTL8139_TW_PARM:
1428 nic_state->regs.tw_parm = val & 0xffff;
1430 case RTL8139_PHY2_PARM:
1431 nic_state->regs.phy2_parm = val;
1433 case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
1434 nic_state->regs.crc[idx - RTL8139_CRC0] = val & 0xff;
1437 case RTL8139_Config5:
1438 nic_state->regs.config5 = val & 0xff;
1441 PrintDebug("rtl8139 write error: invalid port: 0x%x\n", idx);
1447 static int rtl8139_mmio_read(struct guest_info * core,
1454 struct rtl8139_state *nic_state = (struct rtl8139_state *)priv_data;
1456 idx = guest_addr & 0xff;
1459 case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
1460 val = nic_state->regs.id[idx - RTL8139_IDR0];
1463 case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
1464 val = nic_state->regs.mult[idx - RTL8139_MAR0];
1471 val = nic_state->regs.tsd[(idx - RTL8139_TSD0)/4];
1478 val = nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4];
1481 case RTL8139_RBSTART:
1482 val = nic_state->regs.rbstart;
1485 val = nic_state->regs.erbcr;
1488 val = nic_state->regs.ersr;
1492 val = nic_state->regs.cmd;
1493 if (rxbufempty(nic_state)){
1499 /* this value is off by 16 -- don't know why - Lei*/
1500 val = nic_state->regs.capr - 0x10;
1503 val = nic_state->regs.cbr;
1506 val = nic_state->regs.imr;
1509 val = (uint32_t)nic_state->regs.isr;
1512 val = nic_state->regs.tcr;
1515 val = nic_state->regs.rcr;
1518 val = nic_state->regs.tctr;
1521 val = nic_state->regs.mpc;
1523 case RTL8139_9346CR:
1524 val = rtl8139_9346cr_read(nic_state);
1526 case RTL8139_CONFIG0:
1527 val = nic_state->regs.config[0];
1529 case RTL8139_CONFIG1:
1530 val = nic_state->regs.config[1];
1532 case RTL8139_TimerInt:
1533 val = nic_state->regs.timer_int;
1536 val = nic_state->regs.msr;
1538 case RTL8139_CONFIG3:
1539 val = nic_state->regs.config3[0];
1541 case RTL8139_CONFIG4:
1542 val = nic_state->regs.config3[1];
1544 case RTL8139_MULINT:
1545 val = nic_state->regs.mulint;
1548 val = nic_state->regs.rerid;
1551 val = rtl8139_txsad_read(nic_state);
1554 val = nic_state->regs.bmcr;
1557 val = nic_state->regs.bmsr;
1560 val = nic_state->regs.anar;
1562 case RTL8139_ANLPAR:
1563 val = nic_state->regs.anlpar;
1566 val = nic_state->regs.aner;
1569 val = nic_state->regs.dis;
1572 val = nic_state->regs.fcsc;
1574 case RTL8139_NWAYTR:
1575 val = nic_state->regs.nwaytr;
1578 val = nic_state->regs.rec;
1581 val = nic_state->regs.cscr;
1583 case RTL8139_PHY1_PARM:
1584 val = nic_state->regs.phy1_parm;
1586 case RTL8139_TW_PARM:
1587 val = nic_state->regs.tw_parm;
1589 case RTL8139_PHY2_PARM:
1590 val = nic_state->regs.phy2_parm;
1592 case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
1593 val = nic_state->regs.crc[idx - RTL8139_CRC0];
1595 case RTL8139_Config5:
1596 val = nic_state->regs.config5;
1603 memcpy(dst, &val, length);
1605 PrintDebug("rtl8139 mmio read: port:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
1611 static int rtl8139_ioport_write(struct guest_info * core,
1615 void * private_data) {
1616 return rtl8139_mmio_write(core, (addr_t)port,
1617 src, length, private_data);
1620 static int rtl8139_ioport_read(struct guest_info * core,
1624 void * private_data) {
1625 return rtl8139_mmio_read(core, (addr_t)port,
1626 dst, length, private_data);
1630 static int rtl8139_init_state(struct rtl8139_state *nic_state) {
1631 PrintDebug("rtl8139: init_state\n");
1633 nic_state->regs.tsd[0] = nic_state->regs.tsd[1] = nic_state->regs.tsd[2] = nic_state->regs.tsd[3] = TSD_Own;
1635 nic_state->regs.rerid = RTL8139_PCI_REVID_8139;
1636 nic_state->regs.tcr |= ((0x1d << 26) | (0x1 << 22));
1638 rtl8139_reset(nic_state);
1645 static inline int rtl8139_reset_device(struct rtl8139_state * nic_state) {
1646 nic_state->regs.cmd |= CMD_Rst;
1647 rtl8139_init_state(nic_state);
1648 nic_state->regs.cmd &= ~CMD_Rst;
1653 static inline int rtl8139_start_device(struct rtl8139_state * nic_state) {
1654 nic_state->regs.cmd |= CMD_Re | CMD_Te;
1659 static int rtl8139_stop_device(struct rtl8139_state * nic_state) {
1660 PrintDebug("rtl8139: stop device\n");
1662 nic_state->regs.cmd &= ~(CMD_Re | CMD_Te);
1667 static int rtl8139_hook_iospace(struct rtl8139_state * nic_state,
1674 if (base_addr <= 0){
1675 PrintError("In RTL8139: Fail to Hook IO Space, base address 0x%x\n", (int) base_addr);
1679 if (type == PCI_BAR_IO){
1680 PrintDebug("In RTL8139: Hook IO ports starting from %x, size %d\n", (int) base_addr, size);
1682 for (i = 0; i < 0xff; i++){
1683 v3_dev_hook_io(nic_state->dev, base_addr + i, &rtl8139_ioport_read, &rtl8139_ioport_write);
1685 } else if (type == PCI_BAR_MEM32) {
1686 PrintDebug("In RTL8139: Hook memory space starting from %x, size %d\n", (int) base_addr, size);
1688 //hook memory mapped I/O
1689 v3_hook_full_mem(nic_state->vm, nic_state->vm->cores[0].cpu_id, base_addr, base_addr + 0xff,
1690 &rtl8139_mmio_read, &rtl8139_mmio_write, nic_state);
1692 PrintError("In RTL8139: unknown memory type: start %x, size %d\n", (int) base_addr, size);
1699 static int register_dev(struct rtl8139_state * nic_state) {
1702 if (nic_state->pci_bus == NULL) {
1703 PrintError("RTL8139: Not attached to any PCI bus\n");
1708 struct v3_pci_bar bars[6];
1709 struct pci_device * pci_dev = NULL;
1711 for (i = 0; i < 6; i++) {
1712 bars[i].type = PCI_BAR_NONE;
1715 bars[0].type = PCI_BAR_IO;
1716 bars[0].default_base_port = 0xc100;
1717 bars[0].num_ports = 0x100;
1719 bars[0].io_read = rtl8139_ioport_read;
1720 bars[0].io_write = rtl8139_ioport_write;
1721 bars[0].private_data = nic_state;
1724 bars[1].type = PCI_BAR_MEM32;
1725 bars[1].default_base_addr = -1;
1726 bars[1].num_pages = 1;
1728 bars[1].mem_read = rtl8139_mmio_read;
1729 bars[1].mem_write = rtl8139_mmio_write;
1730 bars[1].private_data = nic_state;
1733 pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
1735 NULL, NULL, NULL, nic_state);
1738 if (pci_dev == NULL) {
1739 PrintError("RTL8139: Could not register PCI Device\n");
1743 pci_dev->config_header.vendor_id = 0x10ec;
1744 pci_dev->config_header.device_id = 0x8139;
1745 pci_dev->config_header.command = 0x05;
1747 pci_dev->config_header.revision = RTL8139_PCI_REVID_8139;
1749 pci_dev->config_header.subclass = 0x00;
1750 pci_dev->config_header.class = 0x02;
1751 pci_dev->config_header.header_type = 0x00;
1753 pci_dev->config_header.intr_line = 12;
1754 pci_dev->config_header.intr_pin = 1;
1755 pci_dev->config_space[0x34] = 0xdc;
1757 nic_state->pci_dev = pci_dev;
1762 static int connect_fn(struct v3_vm_info * info,
1763 void * frontend_data,
1764 struct v3_dev_net_ops * ops,
1765 v3_cfg_tree_t * cfg,
1766 void * private_data) {
1767 struct rtl8139_state * nic_state = (struct rtl8139_state *)frontend_data;
1769 rtl8139_init_state(nic_state);
1770 register_dev(nic_state);
1772 nic_state->net_ops = ops;
1773 nic_state->backend_data = private_data;
1775 ops->recv = rtl8139_rx;
1777 ops->config.frontend_data = nic_state;
1778 ops->config.fnt_mac = nic_state->mac;
1784 static int rtl8139_free(void * private_data) {
1785 struct rtl8139_state * nic_state = (struct rtl8139_state *)private_data;
1787 /* dettached from backend */
1789 /* unregistered from PCI? */
1797 static struct v3_device_ops dev_ops = {
1798 .free = rtl8139_free,
1802 static int rtl8139_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1803 struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
1804 struct rtl8139_state * nic_state = NULL;
1805 char * dev_id = v3_cfg_val(cfg, "ID");
1806 char * macstr = v3_cfg_val(cfg, "mac");
1808 nic_state = (struct rtl8139_state *)V3_Malloc(sizeof(struct rtl8139_state));
1809 memset(nic_state, 0, sizeof(struct rtl8139_state));
1811 nic_state->pci_bus = pci_bus;
1814 if (macstr != NULL && !str2mac(macstr, nic_state->mac)) {
1815 PrintDebug("RTL8139: Mac specified %s\n", macstr);
1817 PrintDebug("RTL8139: MAC not specified\n");
1818 random_ethaddr(nic_state->mac);
1821 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, nic_state);
1824 PrintError("RTL8139: Could not attach device %s\n", dev_id);
1829 nic_state->dev = dev;
1831 if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)nic_state) == -1) {
1832 PrintError("RTL8139: Could not register %s as net frontend\n", dev_id);
1833 v3_remove_device(dev);
1841 device_register("RTL8139", rtl8139_init)