* redistribute, and modify it as specified in the file "V3VEE_LICENSE".
*/
-#include <devices/ethernet.h>
#include <devices/pci.h>
#include <palacios/vmm.h>
#include <palacios/vmm_types.h>
#include <palacios/vmm_io.h>
#include <palacios/vmm_debug.h>
#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_ethernet.h>
+#include <palacios/vmm_sprintf.h>
+
#ifndef CONFIG_DEBUG_RTL8139
#define PrintDebug(fmts, args...)
#endif
-
-
-#define NIC_BASE_ADDR 0xc100
-#define NIC_IRQ 11
-
-#define RTL8139_IDR0 (0x00) /* ID Registers */
-#define RTL8139_IDR1 (0x01)
-#define RTL8139_IDR2 (0x02)
-#define RTL8139_IDR3 (0x03)
-#define RTL8139_IDR4 (0x04)
-#define RTL8139_IDR5 (0x05)
-
-#define RTL8139_MAR0 (0x08) /* Mulicast Registers*/
-#define RTL8139_MAR1 (0x09)
-#define RTL8139_MAR2 (0x0a)
-#define RTL8139_MAR3 (0x0b)
-#define RTL8139_MAR4 (0x0c)
-#define RTL8139_MAR5 (0x0d)
-#define RTL8139_MAR6 (0x0e)
-#define RTL8139_MAR7 (0x0f)
+#define RTL8139_IDR0 (0x00) /* ID Registers start, len 6*1bytes */
+#define RTL8139_MAR0 (0x08) /* Mulicast Registers start, len 8*1bytes */
#define RTL8139_TSD0 (0x10) /* Tx Status of Descriptors */
#define RTL8139_TSD1 (0x14)
#define RTL8139_CONFIG4 (0x5a)
#define RTL8139_MULINT (0x5c) /* Multiple Intrpt Select */
#define RTL8139_RERID (0x5e)
-#define RTL8139_TSAD (0x60) /* Tx Status of All Descriptors */
+#define RTL8139_TXSAD (0x60) /* Tx Status of All Descriptors */
#define RTL8139_BMCR (0x62) /* Basic Mode Control Register */
#define RTL8139_BMSR (0x64) /* Basic Mode Status Register */
#define RTL8139_ANAR (0x66) /* Auto-Negotiation Advertisement Register */
#define RTL8139_TW_PARM (0x7c) /* Twister parameter */
#define RTL8139_PHY2_PARM (0x80)
-#define RTL8139_CRC0 (0x84) /* Power Management CRC Reg for wakeup frame */
-#define RTL8139_CRC1 (0x85)
-#define RTL8139_CRC2 (0x86)
-#define RTL8139_CRC3 (0x87)
-#define RTL8139_CRC4 (0x88)
-#define RTL8139_CRC5 (0x89)
-#define RTL8139_CRC6 (0x8a)
-#define RTL8139_CRC7 (0x8b)
+#define RTL8139_CRC0 (0x84) /* Power Management CRC Reg for wakeup frame 8*1bytes */
#define RTL8139_Wakeup0 (0x8c) /* Power Management wakeup frame */
#define RTL8139_Wakeup1 (0x94)
typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
-enum TxStatusBits
-{
- TSD_Own = 0x2000,
- TSD_Tun = 0x4000,
- TSD_Tok = 0x8000,
- TSD_Cdh = 0x10000000,
- TSD_Owc = 0x20000000,
- TSD_Tabt = 0x40000000,
- TSD_Crs = 0x80000000,
+enum TxStatusBits {
+ TSD_Own = 1<<13,
+ TSD_Tun = 1<<14,
+ TSD_Tok = 1<<15,
+ TSD_Cdh = 1<<28,
+ TSD_Owc = 1<<29,
+ TSD_Tabt = 1<<30,
+ TSD_Crs = 1<<31,
};
+/* Transmit Status Register (TSD0-3) Offset: 0x10-0x1F */
+struct tx_status_reg {
+ union {
+ uint16_t val;
+ struct {
+ uint16_t size : 13;
+ uint8_t own : 1;
+ uint8_t tun : 1;
+ uint8_t tok : 1;
+ uint8_t er_tx_th : 6;
+ uint8_t reserved : 2;
+ uint8_t ncc : 4;
+ uint8_t cdh : 1;
+ uint8_t owc : 1;
+ uint8_t tabt : 1;
+ uint8_t crs : 1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
enum RxStatusBits {
- Rx_Multicast = 0x8000,
- Rx_Physical = 0x4000,
- Rx_Broadcast = 0x2000,
- Rx_BadSymbol = 0x0020,
- Rx_Runt = 0x0010,
- Rx_TooLong = 0x0008,
- Rx_CRCErr = 0x0004,
- Rx_BadAlign = 0x0002,
- Rx_StatusOK = 0x0001,
+ Rx_Multicast = 1<<15,
+ Rx_Physical = 1<<14,
+ Rx_Broadcast = 1<<13,
+ Rx_BadSymbol = 1<<5,
+ Rx_Runt = 1<<4,
+ Rx_TooLong = 1<<3,
+ Rx_CRCErr = 1<<2,
+ Rx_BadAlign = 1<<1,
+ Rx_OK = 1<<0,
};
+/* Receive Status Register in RX Packet Header */
+struct rx_status_reg {
+ union {
+ uint16_t val;
+ struct {
+ uint8_t rx_ok : 1;
+ uint8_t rx_bad_align : 1;
+ uint8_t rx_crc_err : 1;
+ uint8_t rx_too_long : 1;
+ uint8_t rx_runt : 1;
+ uint8_t rx_bad_sym : 1;
+ uint8_t reserved : 7;
+ uint8_t rx_brdcast : 1;
+ uint8_t rx_phys : 1;
+ uint8_t rx_multi : 1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+/* ERSR - Early Rx Status Register Offset: 0x36*/
+struct errx_status_reg{
+ union {
+ uint8_t val;
+ struct {
+ uint8_t er_rx_ok : 1;
+ uint8_t er_rx_ovw : 1;
+ uint8_t er_rx_bad_pkt : 1;
+ uint8_t er_rx_good : 1;
+ uint8_t reserved : 4;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
/* Transmit Status of All Descriptors (TSAD) Register */
enum TSAD_bits {
- TSAD_TOK3 = 1<<15, // TOK bit of Descriptor 3
- TSAD_TOK2 = 1<<14, // TOK bit of Descriptor 2
- TSAD_TOK1 = 1<<13, // TOK bit of Descriptor 1
- TSAD_TOK0 = 1<<12, // TOK bit of Descriptor 0
- TSAD_TUN3 = 1<<11, // TUN bit of Descriptor 3
- TSAD_TUN2 = 1<<10, // TUN bit of Descriptor 2
- TSAD_TUN1 = 1<<9, // TUN bit of Descriptor 1
- TSAD_TUN0 = 1<<8, // TUN bit of Descriptor 0
- TSAD_TABT3 = 1<<07, // TABT bit of Descriptor 3
- TSAD_TABT2 = 1<<06, // TABT bit of Descriptor 2
- TSAD_TABT1 = 1<<05, // TABT bit of Descriptor 1
- TSAD_TABT0 = 1<<04, // TABT bit of Descriptor 0
- TSAD_OWN3 = 1<<03, // OWN bit of Descriptor 3
- TSAD_OWN2 = 1<<02, // OWN bit of Descriptor 2
- TSAD_OWN1 = 1<<01, // OWN bit of Descriptor 1
- TSAD_OWN0 = 1<<00, // OWN bit of Descriptor 0
+ TSAD_TOK3 = 1<<15, /* TOK bits of Descriptors*/
+ TSAD_TOK2 = 1<<14,
+ TSAD_TOK1 = 1<<13,
+ TSAD_TOK0 = 1<<12,
+ TSAD_TUN3 = 1<<11, /* TUN bits of Descriptors */
+ TSAD_TUN2 = 1<<10,
+ TSAD_TUN1 = 1<<9,
+ TSAD_TUN0 = 1<<8,
+ TSAD_TABT3 = 1<<7, /* TABT bits of Descriptors */
+ TSAD_TABT2 = 1<<6,
+ TSAD_TABT1 = 1<<5,
+ TSAD_TABT0 = 1<<4,
+ TSAD_OWN3 = 1<<3, /* OWN bits of Descriptors */
+ TSAD_OWN2 = 1<<2,
+ TSAD_OWN1 = 1<<1,
+ TSAD_OWN0 = 1<<0,
};
-enum ISRBits
-{
- ISR_Rok = 0x1,
- ISR_Rer = 0x2,
- ISR_Tok = 0x4,
- ISR_Ter = 0x8,
- ISR_Rxovw = 0x10,
- ISR_Pun = 0x20,
- ISR_Fovw = 0x40,
- ISR_Lenchg = 0x2000,
- ISR_Timeout = 0x4000,
- ISR_Serr = 0x8000,
+
+/* Transmit Status of All Descriptors (TSAD) Register Offset: 0x60-0x61*/
+struct txsad_reg {
+ union {
+ uint16_t val;
+ struct {
+ uint8_t own0 : 1;
+ uint8_t own1 : 1;
+ uint8_t own2 : 1;
+ uint8_t own3 : 1;
+ uint8_t tabt0 : 1;
+ uint8_t tabt1 : 1;
+ uint8_t tabt2 : 1;
+ uint8_t tabt3 : 1;
+ uint8_t tun0 : 1;
+ uint8_t tun1 : 1;
+ uint8_t tun2 : 1;
+ uint8_t tun3 : 1;
+ uint8_t tok0 : 1;
+ uint8_t tok1 : 1;
+ uint8_t tok2 : 1;
+ uint8_t tok3 : 1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+enum ISRBits {
+ ISR_Rok = 1<<0,
+ ISR_Rer = 1<<1,
+ ISR_Tok = 1<<2,
+ ISR_Ter = 1<<3,
+ ISR_Rxovw = 1<<4,
+ ISR_Pun = 1<<5,
+ ISR_Fovw = 1<<6,
+ ISR_Lenchg = 1<<13,
+ ISR_Timeout = 1<<14,
+ ISR_Serr = 1<<15,
};
-enum CMDBits
-{
- CMD_Bufe = 0x1,
- CMD_Te = 0x4,
- CMD_Re = 0x8,
- CMD_Rst = 0x10,
+/*
+ * Interrupt Status Register (ISR) Offset: ox3e-0x3f
+ * Interrupt Mask Register (IMR 0x3c-0x3d) shares the same structure
+ */
+struct isr_imr_reg {
+ union {
+ uint16_t val;
+ struct {
+ uint8_t rx_ok :1;
+ uint8_t rx_err : 1;
+ uint8_t tx_ok : 1;
+ uint8_t tx_err : 1;
+ uint8_t rx_ovw : 1;
+ uint8_t pun_linkchg : 1;
+ uint8_t rx_fifo_ovw : 1;
+ uint8_t reservd: 6;
+ uint8_t lenchg :1;
+ uint8_t timeout :1;
+ uint8_t syserr :1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+enum CMDBits {
+ CMD_Bufe = 1<<0,
+ CMD_Te = 1<<2,
+ CMD_Re = 1<<3,
+ CMD_Rst = 1<<4,
};
+
+/* Commmand Register Offset: 0x37 */
+struct cmd_reg {
+ union {
+ uint8_t val;
+ struct {
+ uint8_t cmd_bufe : 1;
+ uint8_t reservd_1 : 1;
+ uint8_t cmd_te : 1;
+ uint8_t cmd_re : 1;
+ uint8_t cmd_rst : 1;
+ uint8_t reservd_2 : 3;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
enum CMD9346Bits {
- CMD9346_Lock = 0x00,
- CMD9346_Unlock = 0xC0,
+ CMD9346_Lock = 0x00,
+ CMD9346_Unlock = 0xC0,
};
+
+
+/* 93C46 Commmand Register Offset: 0x50 */
+struct cmd9346_reg {
+ union {
+ uint8_t val;
+ struct {
+ uint8_t eedo : 1;
+ uint8_t eedi : 1;
+ uint8_t eesk : 1;
+ uint8_t eecs : 1;
+ uint8_t reserved : 2;
+ uint8_t eem : 2;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+
// Bits in TxConfig.
enum TXConfig_bits{
/* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
- TxIFGShift = 24,
- TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
- TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
- TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
- TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
-
- TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
- TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
- TxClearAbt = (1 << 0), /* Clear abort (WO) */
- TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */
- TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */
-
- TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
+ TxIFGShift = 24,
+ TxIFG84 = (0 << TxIFGShift), /* 8.4us / 840ns (10 / 100Mbps) */
+ TxIFG88 = (1 << TxIFGShift), /* 8.8us / 880ns (10 / 100Mbps) */
+ TxIFG92 = (2 << TxIFGShift), /* 9.2us / 920ns (10 / 100Mbps) */
+ TxIFG96 = (3 << TxIFGShift), /* 9.6us / 960ns (10 / 100Mbps) */
+
+ TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
+ TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */
+ TxClearAbt = (1 << 0), /* Clear abort (WO) */
+ TxDMAShift = 8, /* DMA burst value (0-7) is shifted this many bits */
+ TxRetryShift = 4, /* TXRR value (0-15) is shifted this many bits */
+
+ TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
};
+
+/* Transmit Configuration Register (TCR) Offset: 0x40-0x43 */
+struct tx_config_reg {
+ union {
+ uint32_t val;
+ struct {
+ uint8_t clr_abort :1;
+ uint8_t reserved_1 : 3;
+ uint8_t tx_retry_cnt : 4;
+ uint8_t max_dma : 3;
+ uint8_t reserved_2 : 5;
+ uint8_t tx_crc : 1;
+ uint8_t loop_test : 2;
+ uint8_t reservd_3: 3;
+ uint8_t hw_verid_b :2;
+ uint8_t ifg :2;
+ uint8_t hw_verid_a :5;
+ uint8_t reservd_4 :1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
enum CSCRBits {
CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */
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*/
CSCR_PASS_SCR = 1<<0, /* Bypass Scramble, def 0*/
};
+
+/* CS Configuration Register (CSCR) Offset: 0x74-0x75 */
+struct cscr_reg {
+ union {
+ uint16_t val;
+ struct {
+ uint8_t pass_scr :1;
+ uint8_t reserved_1 : 1;
+ uint8_t con_status_en : 1;
+ uint8_t con_status : 1;
+ uint8_t reserved_2 : 1;
+ uint8_t f_connect : 1;
+ uint8_t f_link_100 : 1;
+ uint8_t jben: 1;
+ uint8_t heart_beat :1;
+ uint8_t ld :1;
+ uint8_t reservd_3 :5;
+ uint8_t test_fun :1;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
/* Bits in RxConfig. */
enum rx_mode_bits {
- AcceptErr = 0x20,
- AcceptRunt = 0x10,
- AcceptBroadcast = 0x08,
- AcceptMulticast = 0x04,
- AcceptMyPhys = 0x02,
- AcceptAllPhys = 0x01,
+ AcceptErr = 0x20,
+ AcceptRunt = 0x10,
+ AcceptBroadcast = 0x08,
+ AcceptMulticast = 0x04,
+ AcceptMyPhys = 0x02,
+ AcceptAllPhys = 0x01,
};
+
+/* Receive Configuration Register (RCR) Offset: 0x44-0x47 */
+struct rx_config_reg {
+ union {
+ uint32_t val;
+ struct {
+ uint8_t all_phy : 1;
+ uint8_t my_phy : 1;
+ uint8_t all_multi : 1;
+ uint8_t all_brdcast : 1;
+ uint8_t acpt_runt : 1;
+ uint8_t acpt_err : 1;
+ uint8_t reserved_1 : 1;
+ uint8_t wrap : 1;
+ uint8_t max_dma: 3;
+ uint8_t rx_buf_len :2;
+ uint8_t rx_fifo_thresd :3;
+ uint8_t rer8 :1;
+ uint8_t mul_er_intr :1;
+ uint8_t reserved_2 : 6;
+ uint8_t eraly_rx_thresd :4;
+ uint8_t reserved_3 : 4;
+ } __attribute__((packed));
+ } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
#define RTL8139_PCI_REVID_8139 0x10
#define SET_MASKED(input, mask, curr) \
Chip9346_op_write_disable = 0x00, /* 00 00zzzz */
};
-enum Chip9346Mode
-{
+enum Chip9346Mode {
Chip9346_none = 0,
Chip9346_enter_command_mode,
Chip9346_read_command,
Chip9346_data_write_all, /* to input register, then filling contents */
};
-struct EEprom9346
-{
+struct EEprom9346 {
uint16_t contents[EEPROM_9346_SIZE];
int mode;
uint32_t tick;
-struct rtl8139_state
-{
+struct rtl8139_state {
nic_state_t dev_state;
struct v3_vm_info * vm;
void * backend_data;
};
-
-static void rtl8139_reset(struct vm_device *dev);
-
-static void dump_state(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
- PrintDebug("====RTL8139: Dumping State Begin==========\n");
- PrintDebug("Registers\n");
- int i;
- uchar_t *reg;
- reg = (uchar_t *)&nic_state->regs;
-
- for(i = 0; i < sizeof(struct nic_regs); i++)
- {
- PrintDebug("Register[%d] = 0x%2x\n", i, (int)reg[i]);
- }
-
- PrintDebug("====RTL8139: Dumping State End==========\n");
-}
-
-static void rtl8139_update_irq(struct rtl8139_state *nic_state)
-{
- struct pci_device *pdev = nic_state->pci_dev;
- int irq_line;
-
- irq_line = pdev->configs[PCI_INTERRUPT_LINE];
+static inline void rtl8139_update_irq(struct rtl8139_state * nic_state) {
int isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0xffff);
- if(isr & 0xffff)
- {
- if (irq_line != 0){
- v3_raise_irq(dev->vm, irq_line);
- PrintDebug("VNIC: RaiseIrq %d: isr: 0x%04x imr : 0x%04x\n", irq_line, nic_state->regs.isr, nic_state->regs.imr);
- } else {
- PrintError("RTL8139: IRQ_Line: %d\n", irq_line);
- }
+ if(isr & 0xffff){
+ v3_pci_raise_irq(nic_state->pci_bus, 0, nic_state->pci_dev);
+ nic_state->statistic.interrupts ++;
}
}
-#if 1
-
-static void prom9346_decode_command(struct EEprom9346 *eeprom, uint8_t command)
-{
+static void prom9346_decode_command(struct EEprom9346 * eeprom, uint8_t command) {
PrintDebug("RTL8139: eeprom command 0x%02x\n", command);
- switch (command & Chip9346_op_mask)
- {
+ switch (command & Chip9346_op_mask) {
case Chip9346_op_read:
- {
+ {
eeprom->address = command & EEPROM_9346_ADDR_MASK;
eeprom->output = eeprom->contents[eeprom->address];
eeprom->eedo = 0;
break;
default:
eeprom->mode = Chip9346_none;
- switch (command & Chip9346_op_ext_mask)
- {
+ switch (command & Chip9346_op_ext_mask) {
case Chip9346_op_write_enable:
PrintDebug("RTL8139: eeprom write enabled\n");
break;
PrintDebug("RTL8139: eeprom write disabled\n");
break;
}
- break;
+ break;
}
}
-static void prom9346_shift_clock(struct EEprom9346 *eeprom)
-{
+static void prom9346_shift_clock(struct EEprom9346 * eeprom) {
int bit = eeprom->eedi?1:0;
++ eeprom->tick;
PrintDebug("eeprom: tick %d eedi=%d eedo=%d\n", eeprom->tick, eeprom->eedi, eeprom->eedo);
- switch (eeprom->mode)
- {
+ switch (eeprom->mode) {
case Chip9346_enter_command_mode:
- if (bit)
- {
+ if (bit) {
eeprom->mode = Chip9346_read_command;
eeprom->tick = 0;
eeprom->input = 0;
case Chip9346_read_command:
eeprom->input = (eeprom->input << 1) | (bit & 1);
- if (eeprom->tick == 8)
- {
+ if (eeprom->tick == 8) {
prom9346_decode_command(eeprom, eeprom->input & 0xff);
}
break;
case Chip9346_data_read:
eeprom->eedo = (eeprom->output & 0x8000)?1:0;
eeprom->output <<= 1;
- if (eeprom->tick == 16)
- {
+ if (eeprom->tick == 16){
#if 1
// the FreeBSD drivers (rl and re) don't explicitly toggle
// CS between reads (or does setting Cfg9346 to 0 count too?),
case Chip9346_data_write:
eeprom->input = (eeprom->input << 1) | (bit & 1);
- if (eeprom->tick == 16)
- {
+ if (eeprom->tick == 16) {
PrintDebug("RTL8139: eeprom write to address 0x%02x data=0x%04x\n",
eeprom->address, eeprom->input);
case Chip9346_data_write_all:
eeprom->input = (eeprom->input << 1) | (bit & 1);
- if (eeprom->tick == 16)
- {
+ if (eeprom->tick == 16) {
int i;
for (i = 0; i < EEPROM_9346_SIZE; i++)
{
}
}
-static int prom9346_get_wire(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
+static int prom9346_get_wire(struct rtl8139_state * nic_state) {
struct EEprom9346 *eeprom = &(nic_state->eeprom);
- if (!eeprom->eecs)
+ if (eeprom->eecs == 0)
return 0;
return eeprom->eedo;
}
-static void prom9346_set_wire(struct vm_device *dev, int eecs, int eesk, int eedi)
-{
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
+static void prom9346_set_wire(struct rtl8139_state * nic_state,
+ int eecs,
+ int eesk,
+ int eedi) {
struct EEprom9346 *eeprom = &(nic_state->eeprom);
uint8_t old_eecs = eeprom->eecs;
uint8_t old_eesk = eeprom->eesk;
PrintDebug("eeprom: +++ wires CS=%d SK=%d DI=%d DO=%d\n",
eeprom->eecs, eeprom->eesk, eeprom->eedi, eeprom->eedo);
- if (!old_eecs && eecs)
- {
+ if (old_eecs == 0 && eecs) {
/* Synchronize start */
eeprom->tick = 0;
eeprom->input = 0;
PrintDebug("=== eeprom: begin access, enter command mode\n");
}
- if (!eecs)
- {
+ if (eecs == 0) {
PrintDebug("=== eeprom: end access\n");
return;
}
- if (!old_eesk && eesk)
- {
+ if (!old_eesk && eesk) {
/* SK front rules */
prom9346_shift_clock(eeprom);
}
}
-static void rtl8139_9346cr_write(struct vm_device *dev, uint32_t val)
-{
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
+static inline void rtl8139_reset_rxbuf(struct rtl8139_state * nic_state, uint32_t bufsize) {
+ nic_state->rx_bufsize = bufsize;
+ nic_state->regs.capr = 0;
+ nic_state->regs.cbr = 0;
+}
+
+
+static void rtl8139_reset(struct rtl8139_state *nic_state) {
+ struct rtl8139_regs *regs = &(nic_state->regs);
+ int i;
+
+ PrintDebug("Rtl8139: Reset\n");
+
+ /* restore MAC address */
+ memcpy(regs->id, nic_state->mac, ETH_ALEN);
+ memset(regs->mult, 0xff, 8);
+
+ rtl8139_update_irq(nic_state);
+
+ // prepare eeprom
+ nic_state->eeprom.contents[0] = 0x8129;
+
+ // PCI vendor and device ID
+ nic_state->eeprom.contents[1] = 0x10ec;
+ nic_state->eeprom.contents[2] = 0x8139;
+ //Mac address
+ nic_state->eeprom.contents[7] = nic_state->mac[0] | nic_state->mac[1] << 8;
+ nic_state->eeprom.contents[8] = nic_state->mac[2] | nic_state->mac[3] << 8;
+ nic_state->eeprom.contents[9] = nic_state->mac[4] | nic_state->mac[5] << 8;
+
+ for (i = 0; i < 4; ++i) {
+ regs->tsd[i] = TSD_Own;
+ }
+
+ rtl8139_reset_rxbuf(nic_state, 1024*8);
+
+ /* ACK the reset */
+ regs->tcr = 0;
+
+ regs->tcr |= ((0x1d << 26) | (0x1 << 22)); // RTL-8139D
+ regs->rerid = RTL8139_PCI_REVID_8139;
+
+ regs->cmd = CMD_Rst; //RxBufEmpty bit is calculated on read from ChipCmd
+
+ regs->config[0] = 0x0 | (1 << 4); // No boot ROM
+ regs->config[1] = 0xC; //IO mapped and MEM mapped registers available
+ //regs->config[1] = 0x4; //Only IO mapped registers available
+ regs->config3[0] = 0x1; // fast back-to-back compatible
+ regs->config3[1] = 0x0;
+ regs->config5 = 0x0;
+
+ regs->cscr = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
+
+ //0x3100 : 100Mbps, full duplex, autonegotiation. 0x2100 : 100Mbps, full duplex
+ regs->bmcr = 0x1000; // autonegotiation
+
+ regs->bmsr = 0x7809;
+ regs->bmsr |= 0x0020; // autonegotiation completed
+ regs->bmsr |= 0x0004; // link is up
+
+ regs->anar = 0x05e1; // all modes, full duplex
+ regs->anlpar = 0x05e1; // all modes, full duplex
+ regs->aner = 0x0001; // autonegotiation supported
+
+ // reset timer and disable timer interrupt
+ regs->tctr = 0;
+ regs->timer_int = 0;
+}
+
+
+
+static void rtl8139_9346cr_write(struct rtl8139_state * nic_state, uint32_t val) {
val &= 0xff;
PrintDebug("RTL8139: 9346CR write val=0x%02x\n", val);
int eecs = (eeprom_val & 0x08)?1:0;
int eesk = (eeprom_val & 0x04)?1:0;
int eedi = (eeprom_val & 0x02)?1:0;
- prom9346_set_wire(dev, eecs, eesk, eedi);
+ prom9346_set_wire(nic_state, eecs, eesk, eedi);
} else if (opmode == 0x40) {
/* Reset. */
val = 0;
- rtl8139_reset(dev);
+ rtl8139_reset(nic_state);
}
nic_state->regs.cmd9346 = val;
}
-static uint32_t rtl8139_9346cr_read(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
+static uint32_t rtl8139_9346cr_read(struct rtl8139_state * nic_state) {
uint32_t ret = nic_state->regs.cmd9346;
uint32_t opmode = ret & 0xc0;
- if (opmode == 0x80)
- {
+ if (opmode == 0x80) {
/* eeprom access */
- int eedo = prom9346_get_wire(dev);
- if (eedo)
- {
+ int eedo = prom9346_get_wire(nic_state);
+ if (eedo){
ret |= 0x01;
- }
- else
- {
+ } else {
ret &= ~0x01;
}
}
return ret;
}
-#endif
-
-static int rtl8139_receiver_enabled(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
+static inline int rtl8139_receiver_enabled(struct rtl8139_state * nic_state) {
return nic_state->regs.cmd & CMD_Re;
}
-static int rtl8139_rxwrap(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static inline int rtl8139_rxwrap(struct rtl8139_state * nic_state) {
// wrapping enabled; assume 1.5k more buffer space if size < 64K
return (nic_state->regs.rcr & (1 << 7));
}
-static void rtl8139_rxbuf_write(struct vm_device *dev, const void *buf, int size)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- struct nic_regs *regs = &(nic_state->regs);
+static void rtl8139_rxbuf_write(struct rtl8139_state * nic_state,
+ const void * buf,
+ int size) {
+ struct rtl8139_regs *regs = &(nic_state->regs);
int wrap;
addr_t guestpa, host_rxbuf;
guestpa = (addr_t)regs->rbstart;
- guest_pa_to_host_va(dev->vm, guestpa, &host_rxbuf);
+ v3_gpa_to_hva(&(nic_state->vm->cores[0]), guestpa, &host_rxbuf);
//wrap to the front of rx buffer
- if (regs->cbr + size > nic_state->rx_bufsize)
- {
+ if (regs->cbr + size > nic_state->rx_bufsize){
wrap = MOD2(regs->cbr + size, nic_state->rx_bufsize);
- if (wrap && !(nic_state->rx_bufsize < 64*1024 && rtl8139_rxwrap(dev)))
- {
+ if (wrap && !(nic_state->rx_bufsize < 64*1024 && rtl8139_rxwrap(nic_state))){
PrintDebug("RTL8139: rx packet wrapped in buffer at %d\n", size-wrap);
- if (size > wrap)
- {
+ if (size > wrap){
memcpy((void *)(host_rxbuf + regs->cbr), buf, size-wrap);
}
#define POLYNOMIAL 0x04c11db6
/* From FreeBSD */
-static int compute_mcast_idx(const uint8_t *ep)
-{
+static inline int compute_mcast_idx(const uint8_t *ep) {
uint32_t crc;
int carry, i, j;
uint8_t b;
carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
crc <<= 1;
b >>= 1;
- if (carry)
+ if (carry){
crc = ((crc ^ POLYNOMIAL) | carry);
+ }
}
}
return (crc >> 26);
}
-static void vnic_receive(struct vm_device *dev, const uchar_t *pkt, uint_t length)
-{
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
- struct nic_regs *regs = &(nic_state->regs);
+
+
+static int rx_one_pkt(struct rtl8139_state * nic_state,
+ uint8_t * pkt,
+ uint32_t len){
+ struct rtl8139_regs *regs = &(nic_state->regs);
uint_t rxbufsize = nic_state->rx_bufsize;
uint32_t header, val;
uint8_t bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
if (regs->rcr & AcceptAllPhys) {
- PrintDebug("RTL8139: packet received in promiscuous mode\n");
+ PrintDebug("RTL8139: packet received in promiscuous mode\n");
} else {
- if (!memcmp(pkt, bcast_addr, 6)) {
- if (!(regs->rcr & AcceptBroadcast))
- {
- PrintDebug("RTL8139: broadcast packet rejected\n");
- return;
- }
- header |= Rx_Broadcast;
- PrintDebug("RTL8139: broadcast packet received\n");
- } else if (pkt[0] & 0x01) {
+ if (!memcmp(pkt, bcast_addr, 6)) {
+ if (!(regs->rcr & AcceptBroadcast)){
+ PrintDebug("RTL8139: broadcast packet rejected\n");
+ return -1;
+ }
+ header |= Rx_Broadcast;
+ PrintDebug("RTL8139: broadcast packet received\n");
+ } else if (pkt[0] & 0x01) {
// multicast
- if (!(regs->rcr & AcceptMulticast))
- {
+ if (!(regs->rcr & AcceptMulticast)){
PrintDebug("RTL8139: multicast packet rejected\n");
- return;
+ return -1;
}
int mcast_idx = compute_mcast_idx(pkt);
- if (!(regs->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
- {
+ if (!(regs->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))){
PrintDebug("RTL8139: multicast address mismatch\n");
- return;
+ return -1;
}
header |= Rx_Multicast;
PrintDebug("RTL8139: multicast packet received\n");
- } else if (regs->id[0] == pkt[0] &&
- regs->id[1] == pkt[1] &&
- regs->id[2] == pkt[2] &&
- regs->id[3] == pkt[3] &&
- regs->id[4] == pkt[4] &&
- regs->id[5] == pkt[5]) {
- if (!(regs->rcr & AcceptMyPhys))
- {
+ } else if (!compare_ethaddr(regs->id, pkt)){
+ if (!(regs->rcr & AcceptMyPhys)){
PrintDebug("RTL8139: rejecting physical address matching packet\n");
- return;
+ return -1;
}
header |= Rx_Physical;
PrintDebug("RTL8139: physical address matching packet received\n");
} else {
PrintDebug("RTL8139: unknown packet\n");
- return;
+ return -1;
}
}
if(1){
- PrintDebug("RTL8139: in ring Rx mode\n");
+ PrintDebug("RTL8139: in ring Rx mode\n");
- int avail = MOD2(rxbufsize + regs->capr - regs->cbr, rxbufsize);
+ int avail = MOD2(rxbufsize + regs->capr - regs->cbr, rxbufsize);
- if (avail != 0 && length + 8 >= avail)
- {
+ if (avail != 0 && len + 8 >= avail){
PrintError("rx overflow: rx buffer length %d head 0x%04x read 0x%04x === available 0x%04x need 0x%04x\n",
- rxbufsize, regs->cbr, regs->capr, avail, length + 8);
+ rxbufsize, regs->cbr, regs->capr, avail, len + 8);
regs->isr |= ISR_Rxovw;
++ regs->mpc;
- rtl8139_update_irq(dev);
- return;
+ rtl8139_update_irq(nic_state);
+ return -1;
}
- header |= Rx_StatusOK;
- header |= ((length << 16) & 0xffff0000);
+ header |= Rx_OK;
+ header |= ((len << 16) & 0xffff0000);
- rtl8139_rxbuf_write(dev, (uint8_t *)&header, 4);
+ rtl8139_rxbuf_write(nic_state, (uint8_t *)&header, 4);
- rtl8139_rxbuf_write(dev, pkt, length);
+ rtl8139_rxbuf_write(nic_state, pkt, len);
- val = V3_Crc32(0, (char *)pkt, length);
+ /* CRC checksum */
+ val = v3_crc32(0, pkt, len);
- rtl8139_rxbuf_write(dev, (uint8_t *)&val, 4);
+ rtl8139_rxbuf_write(nic_state, (uint8_t *)&val, 4);
// correct buffer write pointer
regs->cbr = MOD2((regs->cbr + 3) & ~0x3, rxbufsize);
regs->isr |= ISR_Rok;
- nic_state->pkts_rcvd++;
+ nic_state->statistic.rx_pkts ++;
+ nic_state->statistic.rx_bytes += len;
- rtl8139_update_irq(dev);
+ rtl8139_update_irq(nic_state);
+
+ return 0;
}
-static int netif_input(uchar_t *pkt, uint_t size)
-{
- PrintDebug("RTL8139: packet received!\n");
+static int rtl8139_rx(uint8_t * pkt, uint32_t len, void * private_data) {
+ struct rtl8139_state *nic_state = (struct rtl8139_state *)private_data;
- if (!rtl8139_receiver_enabled(current_vnic)){
- PrintDebug("RTL8139: receiver disabled\n");
- return 0;
+ if (!rtl8139_receiver_enabled(nic_state)){
+ PrintDebug("RTL8139: receiver disabled\n");
+ nic_state->statistic.rx_dropped ++;
+
+ return 0;
+ }
+
+ if(rx_one_pkt(nic_state, pkt, len) >= 0){
+ nic_state->statistic.rx_pkts ++;
+ nic_state->statistic.rx_bytes += len;
+ }else {
+ nic_state->statistic.rx_dropped ++;
}
- vnic_receive(current_vnic, pkt, size);
return 0;
}
-static void rtl8139_reset_rxbuf(struct vm_device *dev, uint32_t bufsize)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- struct nic_regs *regs = &(nic_state->regs);
-
- nic_state->rx_bufsize = bufsize;
- regs->capr = 0;
- regs->cbr = 0;
-}
-
-static void rtl8139_rcr_write(struct vm_device *dev, uint32_t val)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static void rtl8139_rcr_write(struct rtl8139_state * nic_state, uint32_t val) {
PrintDebug("RTL8139: RCR write val=0x%08x\n", val);
val = SET_MASKED(val, 0xf0fc0040, nic_state->regs.rcr);
-
nic_state->regs.rcr = val;
#if 0
uchar_t rblen = (regs->rcr >> 11) & 0x3;
- switch(rblen)
- {
+ switch(rblen) {
case 0x0:
rxbufsize = 1024 * 8 + 16;
break;
#endif
// reset buffer size and read/write pointers
- rtl8139_reset_rxbuf(dev, 8192 << ((nic_state->regs.rcr >> 11) & 0x3));
+ rtl8139_reset_rxbuf(nic_state, 8192 << ((nic_state->regs.rcr >> 11) & 0x3));
PrintDebug("RTL8139: RCR write reset buffer size to %d\n", nic_state->rx_bufsize);
}
-static void rtl8139_reset(struct rtl8139_state *nic_state)
-{
- struct rtl8139_regs *regs = &(nic_state->regs);
- int i;
-
- PrintDebug("Rtl8139: Reset\n");
-
- /* restore MAC address */
- memcpy(regs->id, nic_state->mac, ETH_ALEN);
- memset(regs->mult, 0xff, 8);
-
- regs->isr = 0;
- regs->imr = 0;
-
- rtl8139_update_irq(nic_state);
-
- // prepare eeprom
- nic_state->eeprom.contents[0] = 0x8129;
-
- // PCI vendor and device ID
- nic_state->eeprom.contents[1] = 0x10ec;
- nic_state->eeprom.contents[2] = 0x8139;
- //Mac address
- nic_state->eeprom.contents[7] = nic_state->mac[0] | nic_state->mac[1] << 8;
- nic_state->eeprom.contents[8] = nic_state->mac[2] | nic_state->mac[3] << 8;
- nic_state->eeprom.contents[9] = nic_state->mac[4] | nic_state->mac[5] << 8;
-
- for (i = 0; i < 4; ++i)
- {
- regs->tsd[i] = TSD_Own;
- }
-
- regs->rbstart = 0;
-
- rtl8139_reset_rxbuf(nic_state, 1024*8);
-
- /* ACK the reset */
- regs->tcr = 0;
-
- regs->tcr |= ((0x1d << 26) | (0x1 << 22)); // RTL-8139D
- regs->rerid = RTL8139_PCI_REVID_8139;
-
- regs->cmd = CMD_Rst; //RxBufEmpty bit is calculated on read from ChipCmd
-
- regs->config[0] = 0x0 | (1 << 4); // No boot ROM
- regs->config[1] = 0xC; //IO mapped and MEM mapped registers available
- //regs->config[1] = 0x4; //Only IO mapped registers available
- regs->config3[0] = 0x1; // fast back-to-back compatible
- regs->config3[1] = 0x0;
- regs->config5 = 0x0;
-
- regs->cscr = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
-
- //0x3100 : 100Mbps, full duplex, autonegotiation. 0x2100 : 100Mbps, full duplex
- regs->bmcr = 0x1000; // autonegotiation
-
- regs->bmsr = 0x7809;
- regs->bmsr |= 0x0020; // autonegotiation completed
- regs->bmsr |= 0x0004; // link is up
-
- regs->anar = 0x05e1; // all modes, full duplex
- regs->anlpar = 0x05e1; // all modes, full duplex
- regs->aner = 0x0001; // autonegotiation supported
-
- // reset timer and disable timer interrupt
- regs->tctr = 0;
- regs->timer_int = 0;
-
- nic_state->pkts_rcvd = 0;
-}
-
-static void init_rtl8139_regs(struct rtl8139_state *nic_state)
-{
- nic_state->regs.imr = 0x00;
- nic_state->regs.tsd[0] = nic_state->regs.tsd[1] = nic_state->regs.tsd[2] = nic_state->regs.tsd[3] = TSD_Own;
- nic_state->pkts_rcvd = 0;
-
- int i;
- for(i = 0; i < 6; i++)
- nic_state->regs.id[i] = nic_state->mac_addr[i] = mac[i];
- for(i = 0; i < 8; i++)
- nic_state->regs.mult[i] = 0xff;
-
- nic_state->regs.rerid = RTL8139_PCI_REVID_8139;
- nic_state->regs.tcr |= ((0x1d << 26) | (0x1 << 22));
-
- rtl8139_reset(dev);
-}
-
#if 0
#endif
-static int rtl8139_transmitter_enabled(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static inline int transmitter_enabled(struct rtl8139_state * nic_state){
return nic_state->regs.cmd & CMD_Te;
}
-static bool rtl8139_rxbufempty(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- struct nic_regs *regs = &(nic_state->regs);
+static int rxbufempty(struct rtl8139_state * nic_state){
+ struct rtl8139_regs *regs = &(nic_state->regs);
int unread;
unread = MOD2(regs->cbr + nic_state->rx_bufsize - regs->capr, nic_state->rx_bufsize);
- if (unread != 0)
- {
+ if (unread != 0){
PrintDebug("RTL8139: receiver buffer data available 0x%04x\n", unread);
- return false;
+ return 0;
}
PrintDebug("RTL8139: receiver buffer is empty\n");
- return true;
+ return 1;
}
-static uint32_t rtl8139_cmd_read(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- uint32_t ret = nic_state->regs.cmd;
-
- if (rtl8139_rxbufempty(dev))
- ret |= CMD_Bufe;
-
- PrintDebug("RTL8139: Cmd read val=0x%04x\n", ret);
-
- return ret;
-}
-
-static void rtl8139_cmd_write(struct vm_device *dev, uint32_t val)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
+static void rtl8139_cmd_write(struct rtl8139_state * nic_state, uint32_t val){
val &= 0xff;
PrintDebug("RTL8139: Cmd write val=0x%08x\n", val);
- if (val & CMD_Rst)
- {
+ if (val & CMD_Rst){
PrintDebug("RTL8139: Cmd reset\n");
- rtl8139_reset(dev);
+ rtl8139_reset(nic_state);
}
- if (val & CMD_Re)
- {
+ if (val & CMD_Re){
PrintDebug("RTL8139: Cmd enable receiver\n");
-
- //s->currCPlusRxDesc = 0;
}
- if (val & CMD_Te)
- {
+ if (val & CMD_Te){
PrintDebug("RTL8139: Cmd enable transmitter\n");
-
- //s->currCPlusTxDesc = 0;
}
val = SET_MASKED(val, 0xe3, nic_state->regs.cmd);
nic_state->regs.cmd = val;
}
-static int rtl8139_send_packet(struct vm_device *dev, int descriptor)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- struct nic_regs *regs = &(nic_state->regs);
+static int tx_one_packet(struct rtl8139_state * nic_state, int descriptor){
+ struct rtl8139_regs *regs = &(nic_state->regs);
int txsize;
uint8_t *pkt;
addr_t pkt_gpa = 0, hostva = 0;
- int i;
- if (!rtl8139_transmitter_enabled(dev))
- {
+ if (!transmitter_enabled(nic_state)){
PrintError("RTL8139: fail to send from descriptor %d: transmitter disabled\n", descriptor);
return 0;
}
- if (regs->tsd[descriptor] & TSD_Own)
- {
+ if (regs->tsd[descriptor] & TSD_Own){
PrintError("RTL8139: fail to send from descriptor %d: owned by host\n", descriptor);
return 0;
}
pkt_gpa = (addr_t) regs->tsad[descriptor];
PrintDebug("RTL8139: sending %d bytes from guest memory at 0x%08x\n", txsize, regs->tsad[descriptor]);
-
- guest_pa_to_host_va(dev->vm, (addr_t)pkt_gpa, &hostva);
+
+ v3_gpa_to_hva(&(nic_state->vm->cores[0]), (addr_t)pkt_gpa, &hostva);
pkt = (uchar_t *)hostva;
- for(i = 0; i < txsize; i++)
- {
- PrintDebug("%x ", pkt[i]);
- }
- PrintDebug("\n");
+#ifdef CONFIG_DEBUG_RTL8139
+ v3_hexdump(pkt, txsize, NULL, 0);
+#endif
- if (TxLoopBack == (regs->tcr & TxLoopBack)){ //loopback test
+ if (TxLoopBack == (regs->tcr & TxLoopBack)){ /* loopback test */
PrintDebug(("RTL8139: transmit loopback mode\n"));
- vnic_receive(dev, pkt, txsize);
+ rx_one_pkt(nic_state, pkt, txsize);
} else{
- if (V3_SEND_PKT(pkt, txsize) == 0){
- PrintDebug("RTL8139: Sent %d bytes from descriptor %d\n", txsize, descriptor);
- } else {
- PrintError("Rtl8139: Sending packet error: 0x%p\n", pkt);
- }
+ if (nic_state->net_ops->send(pkt, txsize, nic_state->backend_data) == 0){
+ PrintDebug("RTL8139: Sent %d bytes from descriptor %d\n", txsize, descriptor);
+ nic_state->statistic.tx_pkts ++;
+ nic_state->statistic.tx_bytes += txsize;
+ } else {
+ PrintError("Rtl8139: Sending packet error: 0x%p\n", pkt);
+ nic_state->statistic.tx_dropped ++;
+ }
}
regs->tsd[descriptor] |= TSD_Tok;
regs->tsd[descriptor] |= TSD_Own;
nic_state->regs.isr |= ISR_Tok;
- rtl8139_update_irq(dev);
+ rtl8139_update_irq(nic_state);
return 0;
}
-//write to transmit status registers
-static void rtl8139_tsd_write(struct vm_device *dev, uint8_t descriptor, uint32_t val)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
-#if 0
- if (rtl8139_transmitter_enabled(dev))
- {
- PrintDebug("RTL8139: TxStatus write val=0x%08x descriptor=%d\n", val, descriptor);
-
- nic_state->regs.tsd[descriptor] = val;
-
+/*transmit status registers*/
+static void rtl8139_tsd_write(struct rtl8139_state * nic_state,
+ uint8_t descriptor,
+ uint32_t val){
+ if (!transmitter_enabled(nic_state)){
+ PrintDebug("RTL8139: TxStatus write val=0x%08x descriptor=%d, Transmitter not enabled\n", val, descriptor);
+
return;
}
-#endif
PrintDebug("RTL8139: TSD write val=0x%08x descriptor=%d\n", val, descriptor);
nic_state->regs.tsd[descriptor] = val;
- rtl8139_send_packet(dev, descriptor);
+ tx_one_packet(nic_state, descriptor);
}
-//transmit status of all descriptors
-static uint16_t rtl8139_tsad_read(struct vm_device *dev)
-{
+/* transmit status of all descriptors */
+static uint16_t rtl8139_txsad_read(struct rtl8139_state * nic_state){
uint16_t ret = 0;
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- struct nic_regs *regs = &(nic_state->regs);
+ struct rtl8139_regs *regs = &(nic_state->regs);
- ret = ((regs->tsd[3] & TSD_Tok)?TSD_Tok:0)
+ ret = ((regs->tsd[3] & TSD_Tok)?TSAD_TOK3:0)
|((regs->tsd[2] & TSD_Tok)?TSAD_TOK2:0)
|((regs->tsd[1] & TSD_Tok)?TSAD_TOK1:0)
|((regs->tsd[0] & TSD_Tok)?TSAD_TOK0:0)
|((regs->tsd[1] & TSD_Own)?TSAD_OWN1:0)
|((regs->tsd[0] & TSD_Own)?TSAD_OWN0:0) ;
-
- PrintDebug("RTL8139: tsad read val=0x%04x\n", (int)ret);
+ PrintDebug("RTL8139: txsad read val=0x%04x\n", (int)ret);
return ret;
}
-//interrupt mask register
-static void rtl8139_imr_write(struct vm_device *dev, uint32_t val)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
- PrintDebug("RTL8139: IMR write val=0x%04x\n", val);
-
- /* mask unwriteable bits */
- val = SET_MASKED(val, 0x1e00, nic_state->regs.imr);
-
- nic_state->regs.imr = val;
-
- rtl8139_update_irq(dev);
-}
-
-static void rtl8139_isr_write(struct vm_device *dev, uint32_t val)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- struct nic_regs *regs = &(nic_state->regs);
+static inline void rtl8139_isr_write(struct rtl8139_state * nic_state, uint32_t val) {
+ struct rtl8139_regs *regs = &(nic_state->regs);
PrintDebug("RTL8139: ISR write val=0x%04x\n", val);
-#if 0
-
- // writing to ISR has no effect
-
- return;
-
-#else
uint16_t newisr = regs->isr & ~val;
/* mask unwriteable bits */
/* writing 1 to interrupt status register bit clears it */
regs->isr = 0;
- rtl8139_update_irq(dev);
+ rtl8139_update_irq(nic_state);
regs->isr = newisr;
- rtl8139_update_irq(dev);
-#endif
-}
-
-static uint32_t rtl8139_isr_read(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
- uint32_t ret = (uint32_t)nic_state->regs.isr;
-
- PrintDebug("RTL8139: ISR read val=0x%04x\n", ret);
-
-#if 0
- // reading ISR clears all interrupts
- nic_state->regs.isr = 0;
-
- rtl8139_update_irq(dev);
-
-#endif
-
- return ret;
-}
-
-static void rtl8139_capr_write(struct vm_device *dev, uint32_t val)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
- PrintDebug("RTL8139: CAPR write val=0x%04x\n", val);
-
- // this value is off by 16
- nic_state->regs.capr = MOD2(val + 0x10, nic_state->rx_bufsize);
-
- PrintDebug("RTL 8139: CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
- nic_state->rx_bufsize, nic_state->regs.cbr, nic_state->regs.capr);
-}
-
-static uint32_t rtl8139_capr_read(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
- /* this value is off by 16 */
- uint32_t ret = nic_state->regs.capr - 0x10;
-
- PrintDebug("RTL8139: CAPR read val=0x%04x\n", ret);
-
- return ret;
-}
-
-typedef enum {read, write} opr_t;
-static bool need_hook(int port, opr_t op)
-{
- if (op == read){
- switch (port) {
- case RTL8139_IMR:
- case RTL8139_ISR:
- return true;
- default:
- break;
- }
- }
- if (op == write){
- switch (port) {
- case RTL8139_TSD0:
- case RTL8139_TSD1:
- case RTL8139_TSD2:
- case RTL8139_TSD3:
- case RTL8139_CR:
- case RTL8139_IMR:
- case RTL8139_ISR:
- case RTL8139_TCR:
- case RTL8139_RCR:
- case RTL8139_CSCR:
- case RTL8139_Config5:
- return true;
- default:
- break;
- }
- }
-
- return false;
+ rtl8139_update_irq(nic_state);
}
-static int rtl8139_mmio_write(addr_t guest_addr, void * src, uint_t length, void * priv_data)
-{
- int port;
+static int rtl8139_mmio_write(struct guest_info * core,
+ addr_t guest_addr,
+ void * src,
+ uint_t length,
+ void * priv_data) {
+ int idx;
uint32_t val;
- struct vm_device *dev = (struct vm_device *)priv_data;
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
+ struct rtl8139_state *nic_state = (struct rtl8139_state *)(priv_data);
- port = guest_addr & 0xff;
+ idx = guest_addr & 0xff;
memcpy(&val, src, length);
PrintDebug("rtl8139 mmio write: addr:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
- switch(port) {
- case RTL8139_IDR0:
- nic_state->regs.id[0] = val & 0xff;
- break;
- case RTL8139_IDR1:
- nic_state->regs.id[1] = val & 0xff;
- break;
- case RTL8139_IDR2:
- nic_state->regs.id[2] = val & 0xff;
- break;
- case RTL8139_IDR3:
- nic_state->regs.id[3] = val & 0xff;
- break;
- case RTL8139_IDR4:
- nic_state->regs.id[4] = val & 0xff;
- break;
- case RTL8139_IDR5:
- nic_state->regs.id[5] = val & 0xff;
- break;
- case RTL8139_MAR0:
- nic_state->regs.mult[0] = val & 0xff;
- break;
- case RTL8139_MAR1:
- nic_state->regs.mult[1] = val & 0xff;
- break;
- case RTL8139_MAR2:
- nic_state->regs.mult[2] = val & 0xff;
- break;
- case RTL8139_MAR3:
- nic_state->regs.mult[3] = val & 0xff;
- break;
- case RTL8139_MAR4:
- nic_state->regs.mult[4] = val & 0xff;
- break;
- case RTL8139_MAR5:
- nic_state->regs.mult[5] = val & 0xff;
- break;
- case RTL8139_MAR6:
- nic_state->regs.mult[6] = val & 0xff;
- break;
- case RTL8139_MAR7:
- nic_state->regs.mult[7] = val & 0xff;
- break;
- case RTL8139_TSD0:
- case RTL8139_TSD1:
- case RTL8139_TSD2:
- case RTL8139_TSD3:
- rtl8139_tsd_write(dev, (port - RTL8139_TSD0)/4, val);
- break;
- case RTL8139_TSAD0:
- case RTL8139_TSAD1:
- case RTL8139_TSAD2:
- case RTL8139_TSAD3:
- nic_state->regs.tsad[(port - RTL8139_TSAD0)/4] = val;
- break;
- case RTL8139_RBSTART:
- nic_state->regs.rbstart = val;
- break;
- case RTL8139_ERBCR:
- nic_state->regs.erbcr = val & 0xffff;
- break;
- case RTL8139_ERSR:
- //nic_state->regs.ersr = val & 0xff;
- nic_state->regs.ersr &= (~val) & 0x0c;
- break;
- case RTL8139_CR:
- rtl8139_cmd_write(dev, val);
- break;
- case RTL8139_CAPR:
- rtl8139_capr_write(dev, val & 0xffff);
- break;
- case RTL8139_CBR: //this is read only =====
- //nic_state->regs.cbr = val & 0xffff;
- break;
- case RTL8139_IMR:
- rtl8139_imr_write(dev, val);
- break;
- case RTL8139_ISR:
- rtl8139_isr_write(dev, val);
- break;
- case RTL8139_TCR:
- nic_state->regs.tcr = val;
- break;
- case RTL8139_RCR:
- rtl8139_rcr_write(dev, val);
- break;
- case RTL8139_TCTR:
- nic_state->regs.tctr = 0; //write clear current tick
- break;
- case RTL8139_MPC:
- nic_state->regs.mpc = 0; //clear on write
- break;
- case RTL8139_9346CR:
- rtl8139_9346cr_write(dev, val);
- break;
- case RTL8139_CONFIG0:
- nic_state->regs.config[0] = val & 0xff;
- break;
- case RTL8139_CONFIG1:
- nic_state->regs.config[1] = val & 0xff;
- break;
- case RTL8139_TimerInt:
- nic_state->regs.timer_int = val;
- break;
- case RTL8139_MSR:
- nic_state->regs.msr = val & 0xff;
- break;
- case RTL8139_CONFIG3:
- nic_state->regs.config3[0] = val & 0xff;
- break;
- case RTL8139_CONFIG4:
- nic_state->regs.config3[1] = val & 0xff;
- break;
- case RTL8139_MULINT:
- nic_state->regs.mulint = val & 0xffff;
- break;
- case RTL8139_RERID:
- nic_state->regs.rerid = val & 0xffff;
- break;
- case RTL8139_TSAD:
- nic_state->regs.txsad = val & 0xffff;
- break;
- case RTL8139_BMCR:
- nic_state->regs.bmcr = val & 0xffff;
- break;
- case RTL8139_BMSR:
- nic_state->regs.bmsr = val & 0xffff;
- break;
- case RTL8139_ANAR:
- nic_state->regs.anar = val & 0xffff;
- break;
- case RTL8139_ANLPAR:
- nic_state->regs.anlpar = val & 0xffff;
- break;
- case RTL8139_ANER:
- nic_state->regs.aner = val & 0xffff;
- break;
- case RTL8139_DIS:
- nic_state->regs.dis = val & 0xffff;
- break;
- case RTL8139_FCSC:
- nic_state->regs.fcsc = val & 0xffff;
- break;
- case RTL8139_NWAYTR:
- nic_state->regs.nwaytr = val & 0xffff;
- break;
- case RTL8139_REC:
- nic_state->regs.rec = val & 0xffff;
- break;
- case RTL8139_CSCR:
- nic_state->regs.cscr = val;
- break;
- case RTL8139_PHY1_PARM:
- nic_state->regs.phy1_parm = val;
- break;
- case RTL8139_TW_PARM:
- nic_state->regs.tw_parm = val & 0xffff;
- break;
- case RTL8139_PHY2_PARM:
- nic_state->regs.phy2_parm = val;
- break;
- case RTL8139_CRC0:
- nic_state->regs.crc[0] = val & 0xff;
- break;
- case RTL8139_CRC1:
- nic_state->regs.crc[1] = val & 0xff;
- break;
- case RTL8139_CRC2:
- nic_state->regs.crc[2] = val & 0xff;
- break;
- case RTL8139_CRC3:
- nic_state->regs.crc[3] = val & 0xff;
- break;
- case RTL8139_CRC4:
- nic_state->regs.crc[4] = val & 0xff;
- break;
- case RTL8139_CRC5:
- nic_state->regs.crc[5] = val & 0xff;
- break;
- case RTL8139_CRC6:
- nic_state->regs.crc[6] = val & 0xff;
- break;
- case RTL8139_CRC7:
- nic_state->regs.crc[7] = val & 0xff;
- break;
- case RTL8139_Config5:
- nic_state->regs.config5 = val & 0xff;
- break;
- default:
- PrintDebug("rtl8139 write error: invalid port: 0x%x\n", port);
+ switch(idx) {
+ case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
+ nic_state->regs.id[idx - RTL8139_IDR0] = val & 0xff;
+ break;
+
+ case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
+ nic_state->regs.mult[idx - RTL8139_MAR0] = val & 0xff;
+ break;
+
+ case RTL8139_TSD0:
+ case RTL8139_TSD1:
+ case RTL8139_TSD2:
+ case RTL8139_TSD3:
+ rtl8139_tsd_write(nic_state, (idx - RTL8139_TSD0)/4, val);
+ break;
+
+ case RTL8139_TSAD0:
+ case RTL8139_TSAD1:
+ case RTL8139_TSAD2:
+ case RTL8139_TSAD3:
+ nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4] = val;
+ break;
+
+ case RTL8139_RBSTART:
+ nic_state->regs.rbstart = val;
+ break;
+ case RTL8139_ERBCR:
+ nic_state->regs.erbcr = val & 0xffff;
+ break;
+ case RTL8139_ERSR:
+ //nic_state->regs.ersr = val & 0xff;
+ nic_state->regs.ersr &= (~val) & 0x0c;
+ break;
+ case RTL8139_CR:
+ rtl8139_cmd_write(nic_state, val);
+ break;
+ case RTL8139_CAPR:
+ {
+ val &= 0xffff;
+ /* this value is off by 16 */
+ nic_state->regs.capr = MOD2(val + 0x10, nic_state->rx_bufsize);
+
+ PrintDebug("RTL 8139: CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
+ nic_state->rx_bufsize, nic_state->regs.cbr, nic_state->regs.capr);
+ }
+ break;
+ case RTL8139_CBR: /* read only */
+ //nic_state->regs.cbr = val & 0xffff;
+ break;
+ case RTL8139_IMR:
+ {
+ PrintDebug("RTL8139: IMR write val=0x%04x\n", val);
+
+ /* mask unwriteable bits */
+ val = SET_MASKED(val, 0x1e00, nic_state->regs.imr);
+ nic_state->regs.imr = val;
+ rtl8139_update_irq(nic_state);
+ }
+ break;
+ case RTL8139_ISR:
+ rtl8139_isr_write(nic_state, val);
+ break;
+ case RTL8139_TCR:
+ nic_state->regs.tcr = val;
+ break;
+ case RTL8139_RCR:
+ rtl8139_rcr_write(nic_state, val);
+ break;
+ case RTL8139_TCTR:
+ nic_state->regs.tctr = 0; /* write clear current tick */
+ break;
+ case RTL8139_MPC:
+ nic_state->regs.mpc = 0; /* clear on write */
+ break;
+ case RTL8139_9346CR:
+ rtl8139_9346cr_write(nic_state, val);
+ break;
+ case RTL8139_CONFIG0:
+ nic_state->regs.config[0] = val & 0xff;
+ break;
+ case RTL8139_CONFIG1:
+ nic_state->regs.config[1] = val & 0xff;
+ break;
+ case RTL8139_TimerInt:
+ nic_state->regs.timer_int = val;
+ break;
+ case RTL8139_MSR:
+ nic_state->regs.msr = val & 0xff;
+ break;
+ case RTL8139_CONFIG3:
+ nic_state->regs.config3[0] = val & 0xff;
+ break;
+ case RTL8139_CONFIG4:
+ nic_state->regs.config3[1] = val & 0xff;
+ break;
+
+ case RTL8139_MULINT:
+ nic_state->regs.mulint = val & 0xffff;
+ break;
+ case RTL8139_RERID:
+ nic_state->regs.rerid = val & 0xffff;
+ break;
+ case RTL8139_TXSAD:
+ nic_state->regs.txsad = val & 0xffff;
+ break;
+ case RTL8139_BMCR:
+ nic_state->regs.bmcr = val & 0xffff;
+ break;
+ case RTL8139_BMSR:
+ nic_state->regs.bmsr = val & 0xffff;
+ break;
+ case RTL8139_ANAR:
+ nic_state->regs.anar = val & 0xffff;
+ break;
+ case RTL8139_ANLPAR:
+ nic_state->regs.anlpar = val & 0xffff;
+ break;
+ case RTL8139_ANER:
+ nic_state->regs.aner = val & 0xffff;
+ break;
+ case RTL8139_DIS:
+ nic_state->regs.dis = val & 0xffff;
+ break;
+ case RTL8139_FCSC:
+ nic_state->regs.fcsc = val & 0xffff;
+ break;
+ case RTL8139_NWAYTR:
+ nic_state->regs.nwaytr = val & 0xffff;
+ break;
+ case RTL8139_REC:
+ nic_state->regs.rec = val & 0xffff;
+ break;
+
+ case RTL8139_CSCR:
+ nic_state->regs.cscr = val;
+ break;
+ case RTL8139_PHY1_PARM:
+ nic_state->regs.phy1_parm = val;
+ break;
+ case RTL8139_TW_PARM:
+ nic_state->regs.tw_parm = val & 0xffff;
+ break;
+ case RTL8139_PHY2_PARM:
+ nic_state->regs.phy2_parm = val;
+ break;
+ case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
+ nic_state->regs.crc[idx - RTL8139_CRC0] = val & 0xff;
+ break;
+
+ case RTL8139_Config5:
+ nic_state->regs.config5 = val & 0xff;
+ break;
+ default:
+ PrintDebug("rtl8139 write error: invalid port: 0x%x\n", idx);
}
-
-
-#if TEST_PERFORMANCE
- if (need_hook(port, read))
- io_hooked ++;
- if (( ++io_total) % 50 == 0)
- PrintError("RTL8139: Total IO: %d, Hooked: %d, INT: %d\n", io_total, io_hooked, int_total);
-#endif
return length;
}
-static int rtl8139_mmio_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data)
-{
- ulong_t port;
+static int rtl8139_mmio_read(struct guest_info * core,
+ addr_t guest_addr,
+ void * dst,
+ uint_t length,
+ void * priv_data) {
+ uint16_t idx;
uint32_t val;
- struct vm_device *dev = (struct vm_device *)priv_data;
- struct nic_context *nic_state = (struct nic_context *)(dev->private_data);
-
- port = guest_addr & 0xff;
-
- switch(port) {
- case RTL8139_IDR0:
- val = nic_state->regs.id[0];
- break;
- case RTL8139_IDR1:
- val = nic_state->regs.id[1];
- break;
- case RTL8139_IDR2:
- val = nic_state->regs.id[2];
- break;
- case RTL8139_IDR3:
- val = nic_state->regs.id[3];
- break;
- case RTL8139_IDR4:
- val = nic_state->regs.id[4];
- break;
- case RTL8139_IDR5:
- val = nic_state->regs.id[5];
- break;
- case RTL8139_MAR0:
- val = nic_state->regs.mult[0];
- break;
- case RTL8139_MAR1:
- val = nic_state->regs.mult[1];
- break;
- case RTL8139_MAR2:
- val = nic_state->regs.mult[2];
- break;
- case RTL8139_MAR3:
- val = nic_state->regs.mult[3];
- break;
- case RTL8139_MAR4:
- val = nic_state->regs.mult[4];
- break;
- case RTL8139_MAR5:
- val = nic_state->regs.mult[5];
- break;
- case RTL8139_MAR6:
- val = nic_state->regs.mult[6];
- break;
- case RTL8139_MAR7:
- val = nic_state->regs.mult[7];
- break;
- case RTL8139_TSD0:
- val = nic_state->regs.tsd[0];
- break;
- case RTL8139_TSD1:
- val = nic_state->regs.tsd[1];
- break;
- case RTL8139_TSD2:
- val = nic_state->regs.tsd[2];
- break;
- case RTL8139_TSD3:
- val = nic_state->regs.tsd[3];
- break;
- case RTL8139_TSAD0:
- val = nic_state->regs.tsad[0];
- break;
- case RTL8139_TSAD1:
- val = nic_state->regs.tsad[1];
- break;
- case RTL8139_TSAD2:
- val = nic_state->regs.tsad[2];
- break;
- case RTL8139_TSAD3:
- val = nic_state->regs.tsad[3];
- break;
- case RTL8139_RBSTART:
- val = nic_state->regs.rbstart;
- break;
- case RTL8139_ERBCR:
- val = nic_state->regs.erbcr;
- break;
- case RTL8139_ERSR:
- val = nic_state->regs.ersr;
- break;
- case RTL8139_CR:
- val = rtl8139_cmd_read(dev);
- break;
- case RTL8139_CAPR:
- val = rtl8139_capr_read(dev);
- break;
- case RTL8139_CBR:
- val = nic_state->regs.cbr;
- break;
- case RTL8139_IMR:
- val = nic_state->regs.imr;
- break;
- case RTL8139_ISR:
- val = rtl8139_isr_read(dev);
- break;
- case RTL8139_TCR:
- val = nic_state->regs.tcr;
- break;
- case RTL8139_RCR:
- val = nic_state->regs.rcr;
- break;
- case RTL8139_TCTR:
- val = nic_state->regs.tctr;
- break;
- case RTL8139_MPC:
- val = nic_state->regs.mpc;
- break;
- case RTL8139_9346CR:
- val = rtl8139_9346cr_read(dev);
- break;
- case RTL8139_CONFIG0:
- val = nic_state->regs.config[0];
- break;
- case RTL8139_CONFIG1:
- val = nic_state->regs.config[1];
- break;
- case RTL8139_TimerInt:
- val = nic_state->regs.timer_int;
- break;
- case RTL8139_MSR:
- val = nic_state->regs.msr;
- break;
- case RTL8139_CONFIG3:
- val = nic_state->regs.config3[0];
- break;
- case RTL8139_CONFIG4:
- val = nic_state->regs.config3[1];
- break;
- case RTL8139_MULINT:
- val = nic_state->regs.mulint;
- break;
- case RTL8139_RERID:
- val = nic_state->regs.rerid;
- break;
- case RTL8139_TSAD:
- val = rtl8139_tsad_read(dev);
- break;
- case RTL8139_BMCR:
- val = nic_state->regs.bmcr;
- break;
- case RTL8139_BMSR:
- val = nic_state->regs.bmsr;
- break;
- case RTL8139_ANAR:
- val = nic_state->regs.anar;
- break;
- case RTL8139_ANLPAR:
- val = nic_state->regs.anlpar;
- break;
- case RTL8139_ANER:
- val = nic_state->regs.aner;
- break;
- case RTL8139_DIS:
- val = nic_state->regs.dis;
- break;
- case RTL8139_FCSC:
- val = nic_state->regs.fcsc;
- break;
- case RTL8139_NWAYTR:
- val = nic_state->regs.nwaytr;
- break;
- case RTL8139_REC:
- val = nic_state->regs.rec;
- break;
- case RTL8139_CSCR:
- val = nic_state->regs.cscr;
- break;
- case RTL8139_PHY1_PARM:
- val = nic_state->regs.phy1_parm;
- break;
- case RTL8139_TW_PARM:
- val = nic_state->regs.tw_parm;
- break;
- case RTL8139_PHY2_PARM:
- val = nic_state->regs.phy2_parm;
- break;
- case RTL8139_CRC0:
- val = nic_state->regs.crc[0];
- break;
- case RTL8139_CRC1:
- val = nic_state->regs.crc[1];
- break;
- case RTL8139_CRC2:
- val = nic_state->regs.crc[2];
- break;
- case RTL8139_CRC3:
- val = nic_state->regs.crc[3];
- break;
- case RTL8139_CRC4:
- val = nic_state->regs.crc[4];
- break;
- case RTL8139_CRC5:
- val = nic_state->regs.crc[5];
- break;
- case RTL8139_CRC6:
- val = nic_state->regs.crc[6];
- break;
- case RTL8139_CRC7:
- val = nic_state->regs.crc[7];
- break;
- case RTL8139_Config5:
- val = nic_state->regs.config5;
- break;
- default:
- val = 0x0;
- break;
+ struct rtl8139_state *nic_state = (struct rtl8139_state *)priv_data;
+
+ idx = guest_addr & 0xff;
+
+ switch(idx) {
+ case RTL8139_IDR0 ... RTL8139_IDR0 + 5:
+ val = nic_state->regs.id[idx - RTL8139_IDR0];
+ break;
+
+ case RTL8139_MAR0 ... RTL8139_MAR0 + 7:
+ val = nic_state->regs.mult[idx - RTL8139_MAR0];
+ break;
+
+ case RTL8139_TSD0:
+ case RTL8139_TSD1:
+ case RTL8139_TSD2:
+ case RTL8139_TSD3:
+ val = nic_state->regs.tsd[(idx - RTL8139_TSD0)/4];
+ break;
+
+ case RTL8139_TSAD0:
+ case RTL8139_TSAD1:
+ case RTL8139_TSAD2:
+ case RTL8139_TSAD3:
+ val = nic_state->regs.tsad[(idx - RTL8139_TSAD0)/4];
+ break;
+
+ case RTL8139_RBSTART:
+ val = nic_state->regs.rbstart;
+ break;
+ case RTL8139_ERBCR:
+ val = nic_state->regs.erbcr;
+ break;
+ case RTL8139_ERSR:
+ val = nic_state->regs.ersr;
+ break;
+ case RTL8139_CR:
+ {
+ val = nic_state->regs.cmd;
+ if (rxbufempty(nic_state)){
+ val |= CMD_Bufe;
+ }
+ }
+ break;
+ case RTL8139_CAPR:
+ /* this value is off by 16 -- don't know why - Lei*/
+ val = nic_state->regs.capr - 0x10;
+ break;
+ case RTL8139_CBR:
+ val = nic_state->regs.cbr;
+ break;
+ case RTL8139_IMR:
+ val = nic_state->regs.imr;
+ break;
+ case RTL8139_ISR:
+ val = (uint32_t)nic_state->regs.isr;
+ break;
+ case RTL8139_TCR:
+ val = nic_state->regs.tcr;
+ break;
+ case RTL8139_RCR:
+ val = nic_state->regs.rcr;
+ break;
+ case RTL8139_TCTR:
+ val = nic_state->regs.tctr;
+ break;
+ case RTL8139_MPC:
+ val = nic_state->regs.mpc;
+ break;
+ case RTL8139_9346CR:
+ val = rtl8139_9346cr_read(nic_state);
+ break;
+ case RTL8139_CONFIG0:
+ val = nic_state->regs.config[0];
+ break;
+ case RTL8139_CONFIG1:
+ val = nic_state->regs.config[1];
+ break;
+ case RTL8139_TimerInt:
+ val = nic_state->regs.timer_int;
+ break;
+ case RTL8139_MSR:
+ val = nic_state->regs.msr;
+ break;
+ case RTL8139_CONFIG3:
+ val = nic_state->regs.config3[0];
+ break;
+ case RTL8139_CONFIG4:
+ val = nic_state->regs.config3[1];
+ break;
+ case RTL8139_MULINT:
+ val = nic_state->regs.mulint;
+ break;
+ case RTL8139_RERID:
+ val = nic_state->regs.rerid;
+ break;
+ case RTL8139_TXSAD:
+ val = rtl8139_txsad_read(nic_state);
+ break;
+ case RTL8139_BMCR:
+ val = nic_state->regs.bmcr;
+ break;
+ case RTL8139_BMSR:
+ val = nic_state->regs.bmsr;
+ break;
+ case RTL8139_ANAR:
+ val = nic_state->regs.anar;
+ break;
+ case RTL8139_ANLPAR:
+ val = nic_state->regs.anlpar;
+ break;
+ case RTL8139_ANER:
+ val = nic_state->regs.aner;
+ break;
+ case RTL8139_DIS:
+ val = nic_state->regs.dis;
+ break;
+ case RTL8139_FCSC:
+ val = nic_state->regs.fcsc;
+ break;
+ case RTL8139_NWAYTR:
+ val = nic_state->regs.nwaytr;
+ break;
+ case RTL8139_REC:
+ val = nic_state->regs.rec;
+ break;
+ case RTL8139_CSCR:
+ val = nic_state->regs.cscr;
+ break;
+ case RTL8139_PHY1_PARM:
+ val = nic_state->regs.phy1_parm;
+ break;
+ case RTL8139_TW_PARM:
+ val = nic_state->regs.tw_parm;
+ break;
+ case RTL8139_PHY2_PARM:
+ val = nic_state->regs.phy2_parm;
+ break;
+ case RTL8139_CRC0 ... RTL8139_CRC0 + 7:
+ val = nic_state->regs.crc[idx - RTL8139_CRC0];
+ break;
+ case RTL8139_Config5:
+ val = nic_state->regs.config5;
+ break;
+ default:
+ val = 0x0;
+ break;
}
memcpy(dst, &val, length);
PrintDebug("rtl8139 mmio read: port:0x%x (%u bytes): 0x%x\n", (int)guest_addr, length, val);
-#if TEST_PERFORMANCE
- if (need_hook(port, read))
- io_hooked ++;
- if (( ++io_total) % 50 == 0)
- PrintError("RTL8139: Total IO: %d, Hooked: %d, INT: %d\n", io_total, io_hooked, int_total);
-#endif
-
return length;
}
-static int rtl8139_ioport_write(struct guest_info * core, uint16_t port, void *src, uint_t length, void * private_data)
-{
- PrintDebug("rtl8139 pio write: port:0x%x (%u bytes)\n", port, length);
-
- rtl8139_mmio_write((addr_t)port, src, length, private_data);
-
- return length;
+static int rtl8139_ioport_write(struct guest_info * core,
+ uint16_t port,
+ void *src,
+ uint_t length,
+ void * private_data) {
+ return rtl8139_mmio_write(core, (addr_t)port,
+ src, length, private_data);
}
-static int rtl8139_ioport_read(uint16_t port, void *dst, uint_t length, struct vm_device *dev)
-{
- PrintDebug("rtl8139 pio read: port:0x%x (%u bytes)\n", port, length);
-
- rtl8139_mmio_read((addr_t)port, dst, length, (void *)dev);
-
- return length;
+static int rtl8139_ioport_read(struct guest_info * core,
+ uint16_t port,
+ void *dst,
+ uint_t length,
+ void * private_data) {
+ return rtl8139_mmio_read(core, (addr_t)port,
+ dst, length, private_data);
}
-static int rtl8139_reset_device(struct vm_device *dev)
-{
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
- struct nic_regs *regs = &(nic_state->regs);
- regs->cmd |= CMD_Rst;
- init_rtl8139(dev);
- regs->cmd &= ~CMD_Rst;
+
+static int rtl8139_init_state(struct rtl8139_state *nic_state) {
+ PrintDebug("rtl8139: init_state\n");
+
+ nic_state->regs.tsd[0] = nic_state->regs.tsd[1] = nic_state->regs.tsd[2] = nic_state->regs.tsd[3] = TSD_Own;
+
+ nic_state->regs.rerid = RTL8139_PCI_REVID_8139;
+ nic_state->regs.tcr |= ((0x1d << 26) | (0x1 << 22));
+
+ rtl8139_reset(nic_state);
+
return 0;
}
-static int rtl8139_start_device(struct vm_device *dev)
-{
- PrintDebug("rtl8139: start device\n");
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
- struct nic_regs *regs = &(nic_state->regs);
- regs->cmd |= CMD_Re | CMD_Te;
+
+#if 0
+static inline int rtl8139_reset_device(struct rtl8139_state * nic_state) {
+ nic_state->regs.cmd |= CMD_Rst;
+ rtl8139_init_state(nic_state);
+ nic_state->regs.cmd &= ~CMD_Rst;
+
return 0;
}
-static int rtl8139_stop_device(struct vm_device *dev)
-{
- PrintDebug("rtl8139: stop device\n");
- struct nic_context *nic_state = (struct nic_context *)dev->private_data;
- struct nic_regs *regs = &(nic_state->regs);
- regs->cmd &= ~(CMD_Re | CMD_Te);
+static inline int rtl8139_start_device(struct rtl8139_state * nic_state) {
+ nic_state->regs.cmd |= CMD_Re | CMD_Te;
+
return 0;
}
-static void init_phy_network()
-{
- V3_REGISTER_PKT_DELIVERY(&netif_input);
+static int rtl8139_stop_device(struct rtl8139_state * nic_state) {
+ PrintDebug("rtl8139: stop device\n");
+
+ nic_state->regs.cmd &= ~(CMD_Re | CMD_Te);
+
+ return 0;
}
-static int rtl8139_hook_iospace(struct vm_device *vmdev, addr_t base_addr, int size, int type, void *data)
-{
+static int rtl8139_hook_iospace(struct rtl8139_state * nic_state,
+ addr_t base_addr,
+ int size,
+ int type,
+ void *data) {
int i;
- if (base_addr <= 0)
- {
+ if (base_addr <= 0){
PrintError("In RTL8139: Fail to Hook IO Space, base address 0x%x\n", (int) base_addr);
return -1;
}
- if (type == PCI_ADDRESS_SPACE_IO){
+ if (type == PCI_BAR_IO){
PrintDebug("In RTL8139: Hook IO ports starting from %x, size %d\n", (int) base_addr, size);
- for (i = 0; i < 0xff; i++)
- {
- v3_dev_hook_io(vmdev, base_addr + i, &rtl8139_ioport_read, &rtl8139_ioport_write);
+ for (i = 0; i < 0xff; i++){
+ v3_dev_hook_io(nic_state->dev, base_addr + i, &rtl8139_ioport_read, &rtl8139_ioport_write);
}
- } else if (type == PCI_ADDRESS_SPACE_MEM) {
+ } else if (type == PCI_BAR_MEM32) {
PrintDebug("In RTL8139: Hook memory space starting from %x, size %d\n", (int) base_addr, size);
//hook memory mapped I/O
- v3_hook_full_mem(vmdev->vm, base_addr, base_addr + 0xff,
- &rtl8139_mmio_read, &rtl8139_mmio_write, vmdev);
+ v3_hook_full_mem(nic_state->vm, nic_state->vm->cores[0].cpu_id, base_addr, base_addr + 0xff,
+ &rtl8139_mmio_read, &rtl8139_mmio_write, nic_state);
} else {
PrintError("In RTL8139: unknown memory type: start %x, size %d\n", (int) base_addr, size);
}
return 0;
}
+#endif
-static int rtl8139_unhook_iospace()
-{
-
- return 0;
-}
-
-
-static struct pci_device * rtl8139_pci_init(struct vm_device *vmdev, struct pci_bus *bus, int devfn)
-{
- uchar_t *pci_conf;
- struct pci_device *pdev;
+static int register_dev(struct rtl8139_state * nic_state) {
+ int i;
- pdev = v3_pci_register_device(vmdev, bus, "REALTEK8139", devfn, NULL, NULL);
+ if (nic_state->pci_bus == NULL) {
+ PrintError("RTL8139: Not attached to any PCI bus\n");
- if (pdev == NULL)
- {
- PrintError("NIC: Register to PCI bus failed\n");
- return NULL;
+ return -1;
}
- pci_conf = pdev->configs;
-
- pci_conf[0x00] = 0xec;
- pci_conf[0x01] = 0x10;
- pci_conf[0x02] = 0x39;
- pci_conf[0x03] = 0x81;
- pci_conf[0x04] = 0x05; /* command = I/O space, Bus Master */
- pci_conf[0x08] = RTL8139_PCI_REVID_8139; /* PCI revision ID; >=0x20 is for 8139C+ */
- pci_conf[0x0a] = 0x00; // ethernet network controller
- pci_conf[0x0b] = 0x02;
- pci_conf[0x0e] = 0x00; // header_type
- pci_conf[0x3d] = 1; // interrupt pin 0
- pci_conf[0x3c] = 12;
- pci_conf[0x34] = 0xdc;
-
- pdev->vmdev = vmdev;
-
- v3_pci_register_io_region(pdev, 0, 0x100, PCI_ADDRESS_SPACE_IO, &rtl8139_hook_iospace);
- v3_pci_register_io_region(pdev, 1, 0x100, PCI_ADDRESS_SPACE_MEM, &rtl8139_hook_iospace);
-
- return pdev;
-}
+ struct v3_pci_bar bars[6];
+ struct pci_device * pci_dev = NULL;
-static int rtl8139_init_state(struct rtl8139_state *nic_state)
-{
- PrintDebug("rtl8139: init_state\n");
-
- init_phy_network();
- init_rtl8139(dev);
- current_vnic = dev;
- bus = v3_get_pcibus(dev->vm, 0);
-
- if (bus != NULL)
- {
- PrintDebug("Find PCI bus in guest, attach nic to the bus %p\n", bus);
- pdev = rtl8139_pci_init(dev, bus, -1);
- if (pdev == NULL)
- PrintError("Failure to attach nic to the bus %p\n", bus);
+ for (i = 0; i < 6; i++) {
+ bars[i].type = PCI_BAR_NONE;
}
- nic_state->pci_dev = pdev;
-
- //rtl8139_hook_iospace(dev, 0x2000, 0x100, 1, NULL);
-
- return 0;
-}
+ bars[0].type = PCI_BAR_IO;
+ bars[0].default_base_port = 0xc100;
+ bars[0].num_ports = 0x100;
-static int rtl8139_deinit_device(struct vm_device *dev)
-{
-
- rtl8139_unhook_iospace();
+ bars[0].io_read = rtl8139_ioport_read;
+ bars[0].io_write = rtl8139_ioport_write;
+ bars[0].private_data = nic_state;
- return 0;
-}
-
-static struct vm_device_ops dev_ops =
-{
- .init = rtl8139_init_device,
- .deinit = rtl8139_deinit_device,
- .reset = rtl8139_reset_device,
- .start = rtl8139_start_device,
- .stop = rtl8139_stop_device,
-};
-
-struct vm_device *v3_create_rtl8139()
-{
- struct nic_context *nic_state = V3_Malloc(sizeof(struct nic_context));
- PrintDebug("rtl8139 internal at %p\n", (void *)nic_state);
- struct vm_device *dev = v3_create_device("RTL8139", &dev_ops, nic_state);
- return dev;
-};
-
-
-
-static int register_dev(struct ne2k_state * nic_state)
-{
- int i;
-
- if (nic_state->pci_bus != NULL) {
- struct v3_pci_bar bars[6];
- struct pci_device * pci_dev = NULL;
-
- PrintDebug("NE2000: PCI Enabled\n");
-
- for (i = 0; i < 6; i++) {
- bars[i].type = PCI_BAR_NONE;
- }
-
- bars[0].type = PCI_BAR_IO;
- bars[0].default_base_port = NIC_REG_BASE_PORT;
- bars[0].num_ports = 256;
+/*
+ bars[1].type = PCI_BAR_MEM32;
+ bars[1].default_base_addr = -1;
+ bars[1].num_pages = 1;
- bars[0].io_read = ne2k_pci_read;
- bars[0].io_write = ne2k_pci_write;
- bars[0].private_data = nic_state;
+ bars[1].mem_read = rtl8139_mmio_read;
+ bars[1].mem_write = rtl8139_mmio_write;
+ bars[1].private_data = nic_state;
+*/
- pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
- "NE2000", bars,
- pci_config_update, NULL, NULL, nic_state);
+ pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
+ "RTL8139", bars,
+ NULL, NULL, NULL, nic_state);
- if (pci_dev == NULL) {
- PrintError("NE2000: Could not register PCI Device\n");
- return -1;
- }
+ if (pci_dev == NULL) {
+ PrintError("RTL8139: Could not register PCI Device\n");
+ return -1;
+ }
- pci_dev->config_header.vendor_id = 0x10ec;
- pci_dev->config_header.device_id = 0x8029;
- pci_dev->config_header.revision = 0x00;
-
- pci_dev->config_header.subclass = 0x00;
- pci_dev->config_header.class = 0x02;
- pci_dev->config_header.header_type = 0x00;
-
- pci_dev->config_header.intr_line = 11;
- pci_dev->config_header.intr_pin = 1;
-
- nic_state->pci_dev = pci_dev;
- }else {
- PrintDebug("NE2000: Not attached to PCI\n");
-
- v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
-
- for (i = 1; i < 16; i++){
- v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
- }
+ pci_dev->config_header.vendor_id = 0x10ec;
+ pci_dev->config_header.device_id = 0x8139;
+ pci_dev->config_header.command = 0x05;
+
+ pci_dev->config_header.revision = RTL8139_PCI_REVID_8139;
- v3_dev_hook_io(nic_state->dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
- v3_dev_hook_io(nic_state->dev, NIC_RESET_PORT, &ne2k_reset_port_read, &ne2k_reset_port_write);
- }
+ pci_dev->config_header.subclass = 0x00;
+ pci_dev->config_header.class = 0x02;
+ pci_dev->config_header.header_type = 0x00;
+ pci_dev->config_header.intr_line = 12;
+ pci_dev->config_header.intr_pin = 1;
+ pci_dev->config_space[0x34] = 0xdc;
+ nic_state->pci_dev = pci_dev;
+
return 0;
}
struct v3_dev_net_ops * ops,
v3_cfg_tree_t * cfg,
void * private_data) {
- struct ne2k_state * nic_state = (struct ne2k_state *)frontend_data;
+ struct rtl8139_state * nic_state = (struct rtl8139_state *)frontend_data;
rtl8139_init_state(nic_state);
register_dev(nic_state);
nic_state->net_ops = ops;
nic_state->backend_data = private_data;
- ops->recv = ne2k_rx;
+ ops->recv = rtl8139_rx;
ops->poll = NULL;
ops->start_tx = NULL;
ops->stop_tx = NULL;
}
-static int rtl8139_free(struct ne2k_state * nic_state) {
- int i;
+static int rtl8139_free(void * private_data) {
+ struct rtl8139_state * nic_state = (struct rtl8139_state *)private_data;
/* dettached from backend */
- if(nic_state->pci_bus == NULL){
- for (i = 0; i < 16; i++){
- v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + i);
- }
-
- v3_dev_unhook_io(nic_state->dev, NIC_DATA_PORT);
- v3_dev_unhook_io(nic_state->dev, NIC_RESET_PORT);
- }else {
- /* unregistered from PCI? */
- }
-
- return 0;
+ /* unregistered from PCI? */
V3_Free(nic_state);
static struct v3_device_ops dev_ops = {
- .free = (int (*)(void *))rtl8139_free,
+ .free = rtl8139_free,
};
char * macstr = v3_cfg_val(cfg, "mac");
nic_state = (struct rtl8139_state *)V3_Malloc(sizeof(struct rtl8139_state));
- memset(nic_state, 0, sizeof(struct ne2k_state));
+ memset(nic_state, 0, sizeof(struct rtl8139_state));
nic_state->pci_bus = pci_bus;
nic_state->vm = vm;