* redistribute, and modify it as specified in the file "V3VEE_LICENSE".
*/
-/*
-* Virtual NE2K Network Card
-*/
-
#include <devices/pci.h>
-#include <config/ne2k.h>
#include <palacios/vmm.h>
-#include <palacios/vmm_types.h>
#include <palacios/vmm_io.h>
#include <palacios/vmm_debug.h>
#include <palacios/vmm_string.h>
#include <palacios/vmm_dev_mgr.h>
#include <palacios/vmm_intr.h>
+#include <palacios/vmm_ethernet.h>
+#include <palacios/vm_guest.h>
+#include <palacios/vmm_sprintf.h>
#ifndef CONFIG_DEBUG_NE2K
#undef PrintDebug
#endif
-
-
#define NE2K_DEFAULT_IRQ 11
-#define MAX_ETH_FRAME_SIZE 1514
-
-
// What the hell is this crap?
#define NE2K_PMEM_SIZE (32 * 1024)
#define NE2K_PMEM_START (16 * 1024)
#define NE2K_PMEM_END (NE2K_PMEM_SIZE + NE2K_PMEM_START)
#define NE2K_MEM_SIZE NE2K_PMEM_END
-#define NIC_REG_BASE_PORT 0xc100 //Command register (for all pages)
-#define NIC_DATA_PORT 0xc110 //Data read/write port
-#define NIC_RESET_PORT 0xc11f //Data read/write port
-
-// Page 0 registers
-#define EN0_CLDALO 0x01 //Low byte of current local dma addr RD
-#define EN0_STARTPG 0x01 //Starting page of ring bfr WR
-#define EN0_CLDAHI 0x02 //High byte of current local dma addr RD
-#define EN0_STOPPG 0x02 //Ending page +1 of ring bfr WR
-#define EN0_BOUNDARY 0x03 //Boundary page of ring bfr RD WR
-#define EN0_TSR 0x04 //Transmit status reg RD
-#define EN0_TPSR 0x04 //Transmit starting page WR
-#define EN0_NCR 0x05 //Number of collision reg RD
-#define EN0_TCNTLO 0x05 //Low byte of tx byte count WR
-#define EN0_FIFO 0x06 //FIFO RD
-#define EN0_TCNTHI 0x06 //High byte of tx byte count WR
-#define EN0_ISR 0x07 //Interrupt status reg RD WR
-#define EN0_CRDALO 0x08 //low byte of current remote dma address RD
-#define EN0_RSARLO 0x08 //Remote start address reg 0
-#define EN0_CRDAHI 0x09 //high byte, current remote dma address RD
-#define EN0_RSARHI 0x09 //Remote start address reg 1
-#define EN0_RCNTLO 0x0a //Remote byte count reg WR
-#define EN0_RTL8029ID0 0x0a //Realtek ID byte #1 RD
-#define EN0_RCNTHI 0x0b //Remote byte count reg WR
-#define EN0_RTL8029ID1 0x0b //Realtek ID byte #2 RD
-#define EN0_RSR 0x0c //rx status reg RD
-#define EN0_RXCR 0x0c //RX configuration reg WR
-#define EN0_TXCR 0x0d //TX configuration reg WR
-#define EN0_COUNTER0 0x0d //Rcv alignment error counter RD
-#define EN0_DCFG 0x0e //Data configuration reg WR
-#define EN0_COUNTER1 0x0e //Rcv CRC error counter RD
-#define EN0_IMR 0x0f //Interrupt mask reg WR
-#define EN0_COUNTER2 0x0f //Rcv missed frame error counter RD
-
-//Page 1 registers
+#define NIC_REG_BASE_PORT 0xc100 /* Command register (for all pages) */
+#define NIC_DATA_PORT 0xc110 /* Data read/write port */
+#define NIC_RESET_PORT 0xc11f /* Reset port */
+
+/* Page 0 registers */
+#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
+#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
+#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
+#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
+#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
+#define EN0_TSR 0x04 /* Transmit status reg RD */
+#define EN0_TPSR 0x04 /* Transmit starting page WR */
+#define EN0_NCR 0x05 /* Number of collision reg RD */
+#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
+#define EN0_FIFO 0x06 /* FIFO RD */
+#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
+#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
+#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
+#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
+#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
+#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
+#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
+#define EN0_RTL8029ID0 0x0a /* Realtek ID byte #1 RD */
+#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
+#define EN0_RTL8029ID1 0x0b /* Realtek ID byte #2 RD */
+#define EN0_RSR 0x0c /* rx status reg RD */
+#define EN0_RXCR 0x0c /* RX configuration reg WR */
+#define EN0_TXCR 0x0d /* TX configuration reg WR */
+#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
+#define EN0_DCFG 0x0e /* Data configuration reg WR */
+#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
+#define EN0_IMR 0x0f /* Interrupt mask reg WR */
+#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
+
+/* Page 1 registers */
#define EN1_PHYS 0x01
#define EN1_CURPAG 0x07
#define EN1_MULT 0x08
-//Page 2 registers
-#define EN2_STARTPG 0x01 //Starting page of ring bfr RD
-#define EN2_STOPPG 0x02 //Ending page +1 of ring bfr RD
-#define EN2_LDMA0 0x01 //Current Local DMA Address 0 WR
-#define EN2_LDMA1 0x02 //Current Local DMA Address 1 WR
-#define EN2_RNPR 0x03 //Remote Next Packet Pointer RD WR
-#define EN2_TPSR 0x04 //Transmit Page Start Address RD
-#define EN2_LNRP 0x05 //Local Next Packet Pointer RD WR
-#define EN2_ACNT0 0x06 //Address Counter Upper WR
-#define EN2_ACNT1 0x07 //Address Counter Lower WR
-#define EN2_RCR 0x0c //Receive Configuration Register RD
-#define EN2_TCR 0x0d //Transmit Configuration Register RD
-#define EN2_DCR 0x0e //Data Configuration Register RD
-#define EN2_IMR 0x0f //Interrupt Mask Register RD
-
-//Page 3 registers
+/* Page 2 registers */
+#define EN2_STARTPG 0x01 /* Starting page of ring bfr RD */
+#define EN2_STOPPG 0x02 /* Ending page +1 of ring bfr RD */
+#define EN2_LDMA0 0x01 /* Current Local DMA Address 0 WR */
+#define EN2_LDMA1 0x02 /* Current Local DMA Address 1 WR */
+#define EN2_RNPR 0x03 /* Remote Next Packet Pointer RD WR */
+#define EN2_TPSR 0x04 /* Transmit Page Start Address RD */
+#define EN2_LNRP 0x05 /* Local Next Packet Pointer RD WR */
+#define EN2_ACNT0 0x06 /* Address Counter Upper WR */
+#define EN2_ACNT1 0x07 /* Address Counter Lower WR */
+#define EN2_RCR 0x0c /* Receive Configuration Register RD */
+#define EN2_TCR 0x0d /* Transmit Configuration Register RD */
+#define EN2_DCR 0x0e /* Data Configuration Register RD */
+#define EN2_IMR 0x0f /* Interrupt Mask Register RD */
+
+/* Page 3 registers */
#define EN3_CONFIG0 0x03
#define EN3_CONFIG1 0x04
#define EN3_CONFIG2 0x05
#define EN3_CONFIG3 0x06
-
-typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
-
struct cmd_reg {
union {
uint8_t val;
uint8_t stop : 1;
uint8_t start : 1;
uint8_t tx_pkt : 1;
- uint8_t rem_dma_cmd : 3; // 0=Not allowed, 1=Read, 2=Write, 3=Send Pkt, 4=Abort/Complete DMA
+ uint8_t rem_dma_cmd : 3; /* 0=Not allowed, 1=Read, 2=Write, 3=Send Pkt, 4=Abort/Complete DMA */
uint8_t pg_sel : 2;
} __attribute__((packed));
} __attribute__((packed));
uint8_t frame_align_err : 1;
uint8_t fifo_overrun : 1;
uint8_t missed_pkt : 1;
- uint8_t phy_match : 1; // 0=Physical Addr Match, 1=MCAST/BCAST Addr Match
+ uint8_t phy_match : 1; /* 0=Physical Addr Match, 1=MCAST/BCAST Addr Match */
uint8_t rx_disabled : 1;
uint8_t deferring : 1;
} __attribute__((packed));
} __attribute__((packed));
-struct ne2k_context {
- struct guest_info * vm;
-
- nic_state_t dev_state;
-
- // Registers
+struct ne2k_registers {
struct cmd_reg cmd;
struct intr_status_reg isr;
struct intr_mask_reg imr;
struct rx_cfg_reg rcr;
struct rx_status_reg rsr;
- uint8_t pgstart; // page start reg
- uint8_t pgstop; // page stop reg
- uint8_t boundary; // boundary ptr
- uint8_t tpsr; // tx page start addr
- uint8_t ncr; // number of collisions
- uint8_t fifo; // FIFO...
+ uint8_t pgstart; /* page start reg */
+ uint8_t pgstop; /* page stop reg */
+ uint8_t boundary; /* boundary ptr */
+ uint8_t tpsr; /* tx page start addr */
+ uint8_t ncr; /* number of collisions */
+ uint8_t fifo; /* FIFO... */
- uint8_t curpag; // current page
- uint8_t rnpp; // rem next pkt ptr
- uint8_t lnpp; // local next pkt ptr
+ uint8_t curpag; /* current page */
+ uint8_t rnpp; /* rem next pkt ptr */
+ uint8_t lnpp; /* local next pkt ptr */
- uint8_t cntr0; // counter 0 (frame alignment errors)
- uint8_t cntr1; // counter 1 (CRC Errors)
- uint8_t cntr2; // counter 2 (missed pkt errors)
+ uint8_t cntr0; /* counter 0 (frame alignment errors) */
+ uint8_t cntr1; /* counter 1 (CRC Errors) */
+ uint8_t cntr2; /* counter 2 (missed pkt errors) */
- union { // current local DMA Addr
+ union { /* current local DMA Addr */
uint16_t clda;
struct {
uint8_t clda0;
} __attribute__((packed));
- union { // current remote DMA addr
+ union { /* current remote DMA addr */
uint16_t crda;
struct {
uint8_t crda0;
} __attribute__((packed));
- union { // Remote Start Addr Reg
+ union { /* Remote Start Addr Reg */
uint16_t rsar;
struct {
uint8_t rsar0;
} __attribute__((packed));
- union { // TX Byte count Reg
+ union { /* TX Byte count Reg */
uint16_t tbcr;
struct {
uint8_t tbcr0;
} __attribute__((packed));
} __attribute__((packed));
- union { // Remote Byte count Reg
+ union { /* Remote Byte count Reg */
uint16_t rbcr;
struct {
uint8_t rbcr0;
} __attribute__((packed));
} __attribute__((packed));
-
-
- union { // Address counter?
+ union { /* Address counter? */
uint16_t addcnt;
struct {
uint8_t addcnt0;
uint8_t addcnt1;
} __attribute__((packed));
} __attribute__((packed));
+};
- uint8_t mcast_addr[8]; // multicast mask array
- uint8_t mac_addr[6]; // MAC Addr
-
- uint8_t mem[NE2K_MEM_SIZE];
-
+struct ne2k_state {
+ struct v3_vm_info * vm;
struct pci_device * pci_dev;
struct vm_device * pci_bus;
-};
-
-#define compare_mac(src, dst) !memcmp(src, dst, 6)
-
-#ifdef CONFIG_DEBUG_NE2K
-static void dump_state(struct vm_device * dev) {
- struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
- int i;
-
-
- PrintDebug("====NE2000: Dumping state Begin ==========\n");
- PrintDebug("Registers:\n");
-
- // JRL: Dump Registers
-
- PrintDebug("Memory:\n");
+ struct vm_device * dev;
- for(i = 0; i < 32; i++) {
- PrintDebug("0x%02x ", nic_state->mem[i]);
- }
-
- PrintDebug("\n");
- PrintDebug("====NE2000: Dumping state End==========\n");
-}
-#endif
+ struct ne2k_registers context;
+ uint8_t mem[NE2K_MEM_SIZE];
+ uint8_t mcast_addr[8];
+ uint8_t mac[ETH_ALEN];
+ struct v3_dev_net_ops *net_ops;
+ void * backend_data;
+};
-static int ne2k_update_irq(struct vm_device *dev) {
- struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
+static int ne2k_update_irq(struct ne2k_state * nic_state) {
struct pci_device * pci_dev = nic_state->pci_dev;
- int irq_line = 0;
-
- if (pci_dev == NULL){
- PrintDebug("Ne2k: Device %p is not attached to any PCI Bus\n", nic_state);
- irq_line = NE2K_DEFAULT_IRQ;
- } else {
- irq_line = pci_dev->config_header.intr_line;
- }
-
- if (irq_line == 0){
- PrintError("Ne2k: IRQ_LINE: %d\n", irq_line);
- return -1;
- }
-
- PrintDebug("ne2k_update_irq: irq_line: %d\n", irq_line);
+ if ((nic_state->context.isr.val & nic_state->context.imr.val) & 0x7f) {
+ if (pci_dev == NULL){
+ v3_raise_virq(&(nic_state->vm->cores[0]), NE2K_DEFAULT_IRQ);
+ } else {
+ v3_pci_raise_irq(nic_state->pci_bus, 0, nic_state->pci_dev);
+ }
- // The top bit of the ISR/IMR is reserved and does not indicate and irq event
- // We mask the bit out of the irq pending check
- if ((nic_state->isr.val & nic_state->imr.val) & 0x7f) {
- v3_raise_virq(nic_state->vm, irq_line);
- PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->isr.val, nic_state->imr.val);
+ PrintDebug("NE2000: Raise IRQ\n");
}
return 0;
}
-
-
-static void ne2k_init_state(struct vm_device * dev) {
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
- int i;
- uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, 0x60};
-
- nic_state->vm = dev->vm;
-
- nic_state->isr.reset_status = 1;
- nic_state->imr.val = 0x00;
- nic_state->cmd.val = 0x22;
-
- for (i = 0; i < 5; i++) {
- nic_state->mac_addr[i] = mac[i];
- }
-
- memset(nic_state->mcast_addr, 0xff, sizeof(nic_state->mcast_addr));
-
- // Not sure what this is about....
- memset(nic_state->mem, 0xff, 32);
-
- memcpy(nic_state->mem, nic_state->mac_addr, 6);
- nic_state->mem[14] = 0x57;
- nic_state->mem[15] = 0x57;
-
-#ifdef CONFIG_DEBUG_NE2K
- dump_state(dev);
-#endif
-
-}
-
-static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length) {
- int i;
-
- PrintDebug("\nNe2k: Sending Packet\n");
-
- for (i = 0; i < length; i++) {
- PrintDebug("%x ",pkt[i]);
- }
-
- PrintDebug("\n");
+static int ne2k_send_packet(struct ne2k_state * nic_state, uchar_t *pkt, uint32_t length) {
- PrintError("Implement Send Packet interface\n");
+#ifdef CONFIG_DEBUG_NE2K
+ PrintDebug("NE2000: Send Packet:\n");
+ v3_hexdump(pkt, length, NULL, 0);
+#endif
- return -1;
+ return nic_state->net_ops->send(pkt, length, nic_state->backend_data);
}
-static int ne2k_rxbuf_full(struct vm_device *dev) {
+static int ne2k_rxbuf_full(struct ne2k_registers * regs) {
int empty;
int index;
int boundary;
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
- index = nic_state->curpag << 8;
- boundary = nic_state->boundary << 8;
+ index = regs->curpag << 8;
+ boundary = regs->boundary << 8;
if (index < boundary) {
empty = boundary - index;
} else {
- empty = ((nic_state->pgstop - nic_state->pgstart) << 8) - (index - boundary);
+ empty = ((regs->pgstop - regs->pgstart) << 8) - (index - boundary);
}
- if (empty < (MAX_ETH_FRAME_SIZE + 4)) {
+ if (empty < (ETHERNET_PACKET_LEN + 4)) {
return 1;
}
// This needs to be completely redone...
-static void ne2k_receive(struct vm_device * dev, const uchar_t * pkt, int length) {
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
+static int rx_one_pkt(struct ne2k_state * nic_state, const uchar_t * pkt, uint32_t length) {
+ struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
uchar_t * p;
uint32_t total_len;
uint32_t next;
uint32_t len;
uint32_t index;
uint32_t empty;
- uchar_t buf[60];
uint32_t start;
uint32_t stop;
- start = nic_state->pgstart << 8;
- stop = nic_state->pgstop << 8;
+ start = regs->pgstart << 8;
+ stop = regs->pgstop << 8;
- if (nic_state->cmd.stop) {
- return;
+ if (regs->cmd.stop) {
+ return -1;
}
- if (ne2k_rxbuf_full(dev)) {
+ if (ne2k_rxbuf_full(regs)) {
PrintError("Ne2k: received buffer overflow\n");
- return;
+ return -1;
}
-
//packet too small, expand it
if (length < MIN_BUF_SIZE) {
+ uchar_t buf[MIN_BUF_SIZE];
+
memcpy(buf, pkt, length);
memset(buf + length, 0, MIN_BUF_SIZE - length);
pkt = buf;
length = MIN_BUF_SIZE;
}
- index = nic_state->curpag << 8;
+ index = regs->curpag << 8;
//header, 4 bytes
total_len = length + 4;
}
p = nic_state->mem + index;
- nic_state->rsr.val = 0;
- nic_state->rsr.pkt_rx_ok = 1;
+ regs->rsr.val = 0;
+ regs->rsr.pkt_rx_ok = 1;
if (pkt[0] & 0x01) {
- nic_state->rsr.phy = 1;
+ regs->rsr.phy_match = 1; /* TODO: Check this back */
}
- p[0] = nic_state->rsr.val;
+ p[0] = regs->rsr.val;
p[1] = next >> 8;
p[2] = total_len;
p[3] = total_len >> 8;
index += 4;
while (length > 0) {
- if (index <= stop) {
- empty = stop - index;
- } else {
- empty = 0;
+ if (index <= stop) {
+ empty = stop - index;
+ } else {
+ empty = 0;
}
- len = length;
+ len = length;
- if (len > empty) {
- len = empty;
+ if (len > empty) {
+ len = empty;
}
- memcpy(nic_state->mem + index, pkt, len);
- pkt += len;
- index += len;
+ memcpy(nic_state->mem + index, pkt, len);
+ pkt += len;
+ index += len;
- if (index == stop) {
- index = start;
+ if (index == stop) {
+ index = start;
}
- length -= len;
+ length -= len;
}
- nic_state->curpag = next >> 8;
-
- nic_state->isr.pkt_rx = 1;
- ne2k_update_irq(dev);
-}
+ regs->curpag = next >> 8;
+ regs->isr.pkt_rx = 1;
+ ne2k_update_irq(nic_state);
+ return 0;
+}
-static int netif_input(uchar_t *pkt, uint_t size) {
- struct ne2k_context * nic_state;
- static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- int i;
+static int ne2k_rx(uint8_t * buf, uint32_t size, void * private_data){
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
#ifdef CONFIG_DEBUG_NE2K
- PrintDebug("\nNe2k: Packet Received:\nSource:");
- for (i = 6; i < 12; i++) {
- PrintDebug("%x ", pkt[i]);
- }
-
- PrintDebug("\n");
-
- for(i = 0; i < size; i++) {
- PrintDebug("%x ", pkt[i]);
- }
- PrintDebug("\n");
+ PrintDebug("\nNe2k: Packet Received:\n");
+ v3_hexdump(buf, size, NULL, 0);
#endif
-
- if (nic_state->rcr.prom_phys_enable == 1) {
- //promiscuous mode
- ne2k_receive(ne2ks[i], pkt, size);
- } else if (compare_mac(pkt, brocast_mac) && (nic_state->rcr.bcast_ok)) {
- //broadcast packet
- ne2k_receive(ne2ks[i], pkt, size);
- } else if ((pkt[0] & 0x01) && (nic_state->rcr.mcast_ok)) {
- //TODO: multicast packet
- ne2k_receive(ne2ks[i], pkt, size);
- } else if (compare_mac(pkt, nic_state->mac_addr)) {
- ne2k_receive(ne2ks[i], pkt, size);
+ if(!rx_one_pkt(nic_state, buf, size)){
+ return 0;
}
- return 0;
+ return -1;
}
-static void ne2k_mem_writeb(struct ne2k_context * nic_state, uint32_t addr, uint32_t val) {
- uchar_t tmp;
-
- tmp = (uchar_t) (val & 0x000000ff);
+static inline void mem_writeb(struct ne2k_state * nic_state,
+ uint32_t addr,
+ uint32_t val) {
+ uchar_t tmp = (uchar_t) (val & 0x000000ff);
if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
nic_state->mem[addr] = tmp;
}
-
- PrintDebug("wmem addr: %x val: %x\n", addr, val);
}
-static void ne2k_mem_writew(struct ne2k_context * nic_state,
+static inline void mem_writew(struct ne2k_state * nic_state,
uint32_t addr,
uint32_t val) {
- addr &= ~1; //XXX: check exact behaviour if not even
+ addr &= ~1;
if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
- *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
+ *(uint16_t *)(nic_state->mem + addr) = val;
}
-
- PrintDebug("wmem addr: %x val: %x\n", addr, val);
}
-static void ne2k_mem_writel(struct ne2k_context *nic_state,
+static inline void mem_writel(struct ne2k_state * nic_state,
uint32_t addr,
uint32_t val) {
- addr &= ~1; // XXX: check exact behaviour if not even
+ addr &= ~1;
if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
- *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
+ *(uint32_t *)(nic_state->mem + addr) = val;
}
-
- PrintDebug("wmem addr: %x val: %x\n", addr, val);
}
-static uchar_t ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr) {
- PrintDebug("rmem addr: %x\n", addr);
+static inline uint8_t mem_readb(struct ne2k_state * nic_state, uint32_t addr) {
if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
return nic_state->mem[addr];
}
}
-static ushort_t ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr) {
- PrintDebug("rmem addr: %x\n", addr);
-
- addr &= ~1; //XXX: check exact behaviour if not even
+static inline uint16_t mem_readw(struct ne2k_state * nic_state, uint32_t addr) {
+ addr &= ~1;
if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
- return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
+ return *(uint16_t *)(nic_state->mem + addr);
} else {
return 0xffff;
}
}
-static uint32_t ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr) {
- PrintDebug("rmem addr: %x\n", addr);
-
- addr &= ~1; //XXX: check exact behaviour if not even
+static uint32_t mem_readl(struct ne2k_state * nic_state, uint32_t addr) {
+ addr &= ~1;
if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
- return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
+ return *(uint32_t *)(nic_state->mem + addr);
} else {
return 0xffffffff;
}
}
-static void ne2k_dma_update(struct vm_device *dev, int len) {
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
-
- nic_state->rsar += len;
+static void dma_update( struct ne2k_state * nic_state, int len) {
+ struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
+
+ regs->rsar += len;
// wrap
- if (nic_state->rsar == nic_state->pgstop) {
- nic_state->rsar = nic_state->pgstart;
+ if (regs->rsar == regs->pgstop) {
+ regs->rsar = regs->pgstart;
}
- if (nic_state->rbcr <= len) {
- nic_state->rbcr = 0;
- nic_state->isr.rem_dma_done = 1;
- ne2k_update_irq(dev);
+ if (regs->rbcr <= len) {
+ regs->rbcr = 0;
+ regs->isr.rem_dma_done = 1;
+ ne2k_update_irq(nic_state);
} else {
- nic_state->rbcr -= len;
+ regs->rbcr -= len;
}
}
-
-//for data port read/write
-static int ne2k_data_read(ushort_t port, void * dst, uint_t length, struct vm_device *dev) {
+static int ne2k_data_read(struct guest_info * core,
+ uint16_t port,
+ void * dst,
+ uint_t length,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
uint32_t val;
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
-
+ struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
+
// current dma address
- uint32_t addr = nic_state->rsar;
+ uint32_t addr = regs->rsar;
switch (length){
case 1:
- val = ne2k_mem_readb(nic_state, addr);
+ val = mem_readb(nic_state, addr);
break;
case 2:
- val = ne2k_mem_readw(nic_state, addr);
+ val = mem_readw(nic_state, addr);
break;
case 4:
- val = ne2k_mem_readl(nic_state, addr);
+ val = mem_readl(nic_state, addr);
break;
default:
PrintError("ne2k_data_read error: invalid length %d\n", length);
val = 0x0;
}
- ne2k_dma_update(dev, length);
-
+ dma_update(nic_state, length);
memcpy(dst, &val, length);
- PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
+ PrintDebug("NE2000 read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
return length;
}
-static int ne2k_data_write(ushort_t port, void * src, uint_t length, struct vm_device *dev) {
+static int ne2k_data_write(struct guest_info * core,
+ uint16_t port,
+ void * src,
+ uint_t length,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
uint32_t val;
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
- uint32_t addr = nic_state->rsar;
-
- if (nic_state->rbcr == 0) {
+ struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
+
+ uint32_t addr = regs->rsar;
+
+ if (regs->rbcr == 0) {
return length;
}
switch (length) {
case 1:
- ne2k_mem_writeb(nic_state, addr, val);
+ mem_writeb(nic_state, addr, val);
break;
case 2:
- ne2k_mem_writew(nic_state, addr, val);
+ mem_writew(nic_state, addr, val);
break;
case 4:
- ne2k_mem_writel(nic_state, addr, val);
+ mem_writel(nic_state, addr, val);
break;
default:
- PrintError("nic_data_write error: invalid length %d\n", length);
+ PrintError("NE2000 port write error: invalid length %d\n", length);
}
- ne2k_dma_update(dev, length);
+ dma_update(nic_state, length);
- PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
+ PrintDebug("NE2000: Write port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
return length;
}
-static int ne2k_reset_device(struct vm_device * dev) {
- PrintDebug("vnic: reset device\n");
- init_ne2k_context(dev);
+static void ne2k_init_state(struct ne2k_state * nic_state) {
- return 0;
+
+ /* Not sure what this is about.... */
+ memset(nic_state->mem, 0xff, 32);
+
+ memcpy(nic_state->mem, nic_state->mac, ETH_ALEN);
+ memset(nic_state->mcast_addr, 0xff, sizeof(nic_state->mcast_addr));
+ nic_state->mem[14] = 0x57;
+ nic_state->mem[15] = 0x57;
+
+ /* initiate registers */
+ nic_state->context.isr.reset_status = 1;
+ nic_state->context.imr.val = 0x00;
+ nic_state->context.cmd.val = 0x22;
}
+static int reset_device(struct ne2k_state * nic_state) {
+ ne2k_init_state(nic_state);
+
+ PrintDebug("NE2000: Reset device\n");
+
+ return 0;
+}
//for 0xc11f port
-static int ne2k_reset_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
- PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x\n", port, length, val);
+static int ne2k_reset_port_read(struct guest_info * core,
+ uint16_t port,
+ void * dst,
+ uint_t length,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
memset(dst, 0, length);
- ne2k_reset_device(dev);
+ reset_device(nic_state);
return length;
}
-static int ne2k_reset_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
- PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port, length, val);
+static int ne2k_reset_port_write(struct guest_info * core,
+ uint16_t port,
+ void * src,
+ uint_t length,
+ void * private_data) {
+
return length;
}
-static int ne2k_cmd_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
+static int ne2k_cmd_write(struct guest_info * core,
+ uint16_t port,
+ void * src,
+ uint_t length,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
+ struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
if (length != 1) {
- PrintError("Invalid write length to ne2k Command register\n");
+ PrintError("Invalid write length to NE2000 Command register\n");
return -1;
}
- nic_state->cmd.val = *(uint8_t *)src;
+ regs->cmd.val = *(uint8_t *)src;
- if (!(nic_state->cmd.stop)) {
- nic_state->isr.reset_status = 0;
+ if (!(regs->cmd.stop)) {
+ regs->isr.reset_status = 0;
-
// if ((send pkt) && (dma byte count == 0))
- if ((nic_state.rem_dma_cmd & 0x3) && (nic_state->rbcr == 0)) {
- nic_state->isr.rem_dma_done = 1;
- ne2k_update_irq(dev);
+ if ((regs->cmd.rem_dma_cmd & 0x3) && (regs->rbcr == 0)) {
+ regs->isr.rem_dma_done = 1;
+ ne2k_update_irq(nic_state);
}
- if (nic_state->cmd.tx_pkt) {
- int offset = (nic_state->tpsr << 8);
+ if (regs->cmd.tx_pkt) {
+ int offset = (regs->tpsr << 8);
if (offset >= NE2K_PMEM_END) {
offset -= NE2K_PMEM_SIZE;
}
- if (offset + nic_state->tbcr <= NE2K_PMEM_END) {
- ne2k_send_packet(dev, nic_state->mem + offset, nic_state->tbcr);
+ if (offset + regs->tbcr <= NE2K_PMEM_END) {
+ ne2k_send_packet(nic_state, nic_state->mem + offset, regs->tbcr);
}
-
- nic_state->tsr.val = 0; // clear the tx status reg
- nic_state->tsr.pkt_tx_ok = 1; // indicate successful tx
+ regs->tsr.val = 0; /* clear the tx status reg */
+ regs->tsr.pkt_tx_ok = 1; /* indicate successful tx */
- nic_state->isr.pkt_tx = 1; // irq due to pkt tx
- nic_state->cmd.tx_pkt = 0; // reset cmd bit
- ne2k_update_irq(dev);
+ regs->isr.pkt_tx = 1; /* irq due to pkt tx */
+ regs->cmd.tx_pkt = 0; /* reset cmd bit */
+
+ ne2k_update_irq(nic_state);
}
} else {
- // stop the controller
+ /* stop the controller */
}
return length;
}
-static int ne2k_cmd_read(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
- *(uint8_t *)dst = nic_state->cmd.val;
+static int ne2k_cmd_read(struct guest_info * core,
+ uint16_t port,
+ void * dst,
+ uint_t length,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
+
+ if (length != 1) {
+ PrintError("Invalid read length to NE2000 Command register\n");
+ return -1;
+ }
+
+ *(uint8_t *)dst = nic_state->context.cmd.val;
PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
return length;
}
-static int ne2k_std_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
- struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
- int index = port & 0x1f;
- uint8_t page = nic_state->cmd.pg_sel;
-
- if (length != 1
- PrintError("ne2k_write error: length %d\n", length);
+static int ne2k_std_write(struct guest_info * core,
+ uint16_t port,
+ void * src,
+ uint_t length,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
+ struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
+ int idx = port & 0x1f;
+ uint8_t page = regs->cmd.pg_sel;
+
+ if (length != 1){
+ PrintError("NE2000 port write error: length %d port 0x%xnot equal to 1\n", length, port);
return -1;
}
- PrintDebug("ne2k_write: port:0x%x val: 0x%x\n", port, (int)val);
+ uint8_t val = *(uint8_t *)src;
+
+ PrintDebug("NE2000: write port:0x%x val: 0x%x\n", port, (uint8_t)val);
-
if (page == 0) {
- switch (port) {
+ switch (idx) {
case EN0_STARTPG:
- nic_state->pgstart = val;
+ regs->pgstart = val;
break;
case EN0_STOPPG:
- nic_state->pgstop = val;
+ regs->pgstop = val;
break;
case EN0_BOUNDARY:
- nic_state->boundary = val;
+ regs->boundary = val;
break;
case EN0_TPSR:
- nic_state->tpsr = val;
+ regs->tpsr = val;
break;
case EN0_TCNTLO:
- nic_state->tbcr0 = val;
+ regs->tbcr0 = val;
break;
case EN0_TCNTHI:
- nic_state->tbcr1 = val;
+ regs->tbcr1 = val;
break;
case EN0_ISR:
- nic_state->isr.val &= ~(val & 0x7f);
- ne2k_update_irq(dev);
+ regs->isr.val &= ~(val & 0x7f);
+ ne2k_update_irq(nic_state);
break;
case EN0_RSARLO:
- nic_state->rsar0 = val;
+ regs->rsar0 = val;
break;
case EN0_RSARHI:
- nic_state->rsar1 = val;
+ regs->rsar1 = val;
break;
case EN0_RCNTLO:
- nic_state->rbcr0 = val;
+ regs->rbcr0 = val;
break;
case EN0_RCNTHI:
- nic_state->rbcr1 = val;
+ regs->rbcr1 = val;
break;
case EN0_RXCR:
- nic_state->rcr.val = val;
+ regs->rcr.val = val;
break;
case EN0_TXCR:
- nic_state->tcr.val = val;
+ regs->tcr.val = val;
break;
case EN0_DCFG:
- nic_state->dcr.val = val;
+ regs->dcr.val = val;
break;
case EN0_IMR:
- nic_state->imr.val = val;
- //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
- ne2k_update_irq(dev);
+ regs->imr.val = val;
+ ne2k_update_irq(nic_state);
break;
+
default:
- PrintError("ne2k_write error: invalid port:0x%x\n", port);
+ PrintError("NE2000 port write error: invalid port:0x%x\n", port);
return -1;
}
} else if (page == 1) {
- switch (port) {
- case EN1_PHYS ... EN1_PHYS + 5:
- nic_state->mac_addr[port - EN1_PHYS] = val;
+ switch (idx) {
+ case EN1_PHYS ... EN1_PHYS + ETH_ALEN -1:
+ nic_state->mac[port - EN1_PHYS] = val;
break;
case EN1_CURPAG:
- nic_state->curpag = val;
+ regs->curpag = val;
break;
case EN1_MULT ... EN1_MULT + 7:
- // PrintError("ne2k_write error: write EN_MULT:0x%x\n", (int)val);
nic_state->mcast_addr[port - EN1_MULT] = val;
break;
+
default:
- PrintError("ne2k_write error: invalid port:0x%x\n", port);
+ PrintError("NE2000 write port error: invalid port:0x%x\n", port);
return -1;
}
} else if (page == 2) {
- switch (port) {
+ switch (idx) {
case EN2_LDMA0:
- nic_state->clda0 = val;
+ regs->clda0 = val;
break;
case EN2_LDMA1:
- nic_state->clda1 = val;
+ regs->clda1 = val;
break;
case EN2_RNPR:
- nic_state->rnpp = val;
+ regs->rnpp = val;
break;
case EN2_LNRP:
- nic_state->lnpp = val;
+ regs->lnpp = val;
break;
case EN2_ACNT0:
- nic_state->addcnt0 = val;
+ regs->addcnt0 = val;
break;
case EN2_ACNT1:
- nic_state->addcnt1 = val;
+ regs->addcnt1 = val;
break;
+
default:
- PrintError("ne2k_write error: invalid port:0x%x\n", port);
+ PrintError("NE2000 write port error: invalid port:0x%x\n", port);
return -1;
}
} else {
- PrintError("Invalid Register Page Value\n");
+ PrintError("NE2000: Invalid Register Page Value\n");
return -1;
}
}
-static int ne2k_std_read(uint16_t port, void * dst, uint_t length, struct vm_device *dev) {
- struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
+static int ne2k_std_read(struct guest_info * core,
+ uint16_t port,
+ void * dst,
+ uint_t length,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
+ struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
uint16_t index = port & 0x1f;
- uint8_t page = nic_state->cmd.pg_sel;
+ uint8_t page = regs->cmd.pg_sel;
if (length > 1) {
PrintError("ne2k_read error: length %d\n", length);
}
if (page == 0) {
-
switch (index) {
case EN0_CLDALO:
- *(uint8_t *)dst = nic_state->clda0;
+ *(uint8_t *)dst = regs->clda0;
break;
case EN0_CLDAHI:
- *(uint8_t *)dst = nic_state->clda1;
+ *(uint8_t *)dst = regs->clda1;
break;
case EN0_BOUNDARY:
- *(uint8_t *)dst = nic_state->boundary;
+ *(uint8_t *)dst = regs->boundary;
break;
case EN0_TSR:
- *(uint8_t *)dst = nic_state->tsr.val;
+ *(uint8_t *)dst = regs->tsr.val;
break;
case EN0_NCR:
- *(uint8_t *)dst = nic_state->ncr;
+ *(uint8_t *)dst = regs->ncr;
break;
case EN0_FIFO:
- *(uint8_t *)dst = nic_state->fifo;
+ *(uint8_t *)dst = regs->fifo;
break;
case EN0_ISR:
- *(uint8_t *)dst = nic_state->isr.val;
- ne2k_update_irq(dev);
+ *(uint8_t *)dst = regs->isr.val;
+ ne2k_update_irq(nic_state);
break;
case EN0_CRDALO:
- *(uint8_t *)dst = nic_state->crda0;
+ *(uint8_t *)dst = regs->crda0;
break;
case EN0_CRDAHI:
- *(uint8_t *)dst = nic_state->crda1;
+ *(uint8_t *)dst = regs->crda1;
break;
case EN0_RSR:
- *(uint8_t *)dst = nic_state->rsr.val;
+ *(uint8_t *)dst = regs->rsr.val;
break;
case EN0_COUNTER0:
- *(uint8_t *)dst = nic_state->cntr0;
+ *(uint8_t *)dst = regs->cntr0;
break;
case EN0_COUNTER1:
- *(uint8_t *)dst = nic_state->cntr1;
+ *(uint8_t *)dst = regs->cntr1;
break;
case EN0_COUNTER2:
- *(uint8_t *)dst = nic_state->cntr2;
+ *(uint8_t *)dst = regs->cntr2;
break;
+
default:
- PrintError("ne2k_read error: invalid port:0x%x\n", port);
+ PrintError("NE2000 port read error: invalid port:0x%x\n", port);
return -1;
}
-
} else if (page == 1) {
-
switch (index) {
- case EN1_PHYS ... EN1_PHYS + 5:
- *(uint8_t *)dst = nic_state->mac_addr[index - EN1_PHYS];
+ case EN1_PHYS ... EN1_PHYS + ETH_ALEN -1:
+ *(uint8_t *)dst = nic_state->mac[index - EN1_PHYS];
break;
case EN1_CURPAG:
- *(uint8_t *)dst = nic_state->curpag;
+ *(uint8_t *)dst = regs->curpag;
break;
case EN1_MULT ... EN1_MULT + 7:
*(uint8_t *)dst = nic_state->mcast_addr[index - EN1_MULT];
break;
+
default:
PrintError("ne2k_read error: invalid port:0x%x\n", port);
return -1;
}
-
} else if (page == 2) {
-
switch (index) {
case EN2_STARTPG:
- *(uint8_t *)dst = nic_state->pgstart;
+ *(uint8_t *)dst = regs->pgstart;
break;
case EN2_STOPPG:
- *(uint8_t *)dst = nic_state->pgstop;
+ *(uint8_t *)dst = regs->pgstop;
break;
case EN2_RNPR:
- *(uint8_t *)dst = nic_state->rnpp;
+ *(uint8_t *)dst = regs->rnpp;
break;
case EN2_LNRP:
- *(uint8_t *)dst = nic_state->lnpp;
+ *(uint8_t *)dst = regs->lnpp;
break;
case EN2_TPSR:
- *(uint8_t *)dst = nic_state->tpsr;
+ *(uint8_t *)dst = regs->tpsr;
break;
case EN2_ACNT0:
- *(uint8_t *)dst = nic_state->addcnt0;
+ *(uint8_t *)dst = regs->addcnt0;
break;
case EN2_ACNT1:
- *(uint8_t *)dst = nic_state->addcnt1;
+ *(uint8_t *)dst = regs->addcnt1;
break;
case EN2_RCR:
- *(uint8_t *)dst = nic_state->rcr.val;
+ *(uint8_t *)dst = regs->rcr.val;
break;
case EN2_TCR:
- *(uint8_t *)dst = nic_state->tcr.val;
+ *(uint8_t *)dst = regs->tcr.val;
break;
case EN2_DCR:
- *(uint8_t *)dst = nic_state->dcr.val;
+ *(uint8_t *)dst = regs->dcr.val;
break;
case EN2_IMR:
- *(uint8_t *)dst = nic_state->imr.val;
+ *(uint8_t *)dst = regs->imr.val;
break;
default:
- PrintError("ne2k_read error: invalid port:0x%x\n", port);
+ PrintError("NE2000 port read error: invalid port:0x%x\n", port);
return -1;
}
} else {
- PrintError("Invalid Register Page Value\n");
+ PrintError("NE2000 port read: Invalid Register Page Value\n");
return -1;
}
-
- PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
+ PrintDebug("NE2000 port read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
return length;
}
-static int ne2k_start_device(struct vm_device * dev) {
- PrintDebug("vnic: start device\n");
-
- return 0;
-}
+static int ne2k_pci_write(struct guest_info * core,
+ uint16_t port,
+ void * src,
+ uint_t length,
+ void * private_data) {
+ uint16_t idx = port & 0x1f;
+ int ret;
-static int ne2k_stop_device(struct vm_device * dev) {
- PrintDebug("vnic: stop device\n");
-
- return 0;
+ switch (idx) {
+ case NIC_REG_BASE_PORT:
+ ret = ne2k_cmd_write(core, port, src, length, private_data);
+ break;
+ case NIC_REG_BASE_PORT+1 ... NIC_REG_BASE_PORT+15:
+ ret = ne2k_std_write(core, port, src, length, private_data);
+ break;
+ case NIC_DATA_PORT:
+ ret = ne2k_data_write(core, port, src, length, private_data);
+ break;
+ case NIC_RESET_PORT:
+ ret = ne2k_reset_port_write(core, port, src, length, private_data);
+ break;
+
+ default:
+ PrintError("NE2000 port write error: invalid port:0x%x\n", port);
+ return -1;
+ }
+
+ return ret;
}
+static int ne2k_pci_read(struct guest_info * core,
+ uint16_t port,
+ void * dst,
+ uint_t length,
+ void * private_data) {
+ uint16_t idx = port & 0x1f;
+ int ret;
+
+ switch (idx) {
+ case NIC_REG_BASE_PORT:
+ ret = ne2k_cmd_read(core, port, dst, length, private_data);
+ break;
+ case NIC_REG_BASE_PORT+1 ... NIC_REG_BASE_PORT+15:
+ ret = ne2k_std_read(core, port, dst, length, private_data);
+ break;
+ case NIC_DATA_PORT:
+ ret = ne2k_data_read(core, port, dst, length, private_data);
+ break;
+ case NIC_RESET_PORT:
+ ret = ne2k_reset_port_read(core, port, dst, length, private_data);
+ break;
+ default:
+ PrintError("NE2000 port read error: invalid port:0x%x\n", port);
+ return -1;
+ }
+ return ret;
-static int ne2k_init_device(struct vm_device * dev) {
- struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
-
- PrintDebug("Initializing NE2K\n");
- init_ne2k_context(dev);
+}
- if (nic_state->pci_bus == NULL) {
- PrintDebug("NE2k: Not attached to pci\n");
+static int pci_config_update(uint_t reg_num,
+ void * src,
+ uint_t length,
+ void * private_data) {
+ PrintDebug("PCI Config Update\n");
- v3_dev_hook_io(dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
+ /* Do we need this? */
- for (i = 1; i < 16; i++){
- v3_dev_hook_io(dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
- }
+ return 0;
+}
- v3_dev_hook_io(dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
- v3_dev_hook_io(dev, NIC_RESET_PORT, &ne2k_reset_read, &ne2k_reset_write);
- } else {
+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;
- int i;
- PrintDebug("NE2k: PCI Enabled\n");
+ PrintDebug("NE2000: PCI Enabled\n");
for (i = 0; i < 6; i++) {
bars[i].type = PCI_BAR_NONE;
bars[0].io_read = ne2k_pci_read;
bars[0].io_write = ne2k_pci_write;
+ bars[0].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, dev);
+ pci_config_update, NULL, NULL, nic_state);
- if (pci_dev == NULL) {
- PrintError("Failed to register NE2K with PCI\n");
- return -1;
- }
+ if (pci_dev == NULL) {
+ PrintError("NE2000: 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.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);
+ }
+
+ 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);
}
-
-#ifdef CONFIG_DEBUG_NE2K
- dump_state(dev);
-#endif
return 0;
}
+static int connect_fn(struct v3_vm_info * info,
+ void * frontend_data,
+ struct v3_dev_net_ops * ops,
+ v3_cfg_tree_t * cfg,
+ void * private_data) {
+ struct ne2k_state * nic_state = (struct ne2k_state *)frontend_data;
+
+ ne2k_init_state(nic_state);
+ register_dev(nic_state);
+
+ nic_state->net_ops = ops;
+ nic_state->backend_data = private_data;
+ ops->recv = ne2k_rx;
+ ops->poll = NULL;
+ ops->start_tx = NULL;
+ ops->stop_tx = NULL;
+ ops->frontend_data = nic_state;
+ memcpy(ops->fnt_mac, nic_state->mac, ETH_ALEN);
-static int ne2k_deinit_device(struct vm_device *dev) {
+ return 0;
+}
+
+
+static int ne2k_free(struct ne2k_state * nic_state) {
int i;
-
- for (i = 0; i < 16; i++){
- v3_dev_unhook_io(dev, NIC_REG_BASE_PORT + i);
- }
+
+ /* 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(dev, NIC_DATA_PORT);
- v3_dev_unhook_io(dev, NIC_RESET_PORT);
+ 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;
+
+ V3_Free(nic_state);
+
+ return 0;
}
-static struct v3_device_ops dev_ops = {
- .init = ne2k_init_device,
- .deinit = ne2k_deinit_device,
- .reset = ne2k_reset_device,
- .start = ne2k_start_device,
- .stop = ne2k_stop_device,
+static struct v3_device_ops dev_ops = {
+ .free = (int (*)(void *))ne2k_free,
};
-struct vm_device * v3_create_ne2k(struct vm_device * pci) {
- struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
+static int ne2k_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
+ struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
+ struct ne2k_state * nic_state = NULL;
+ char * dev_id = v3_cfg_val(cfg, "ID");
+ char * macstr = v3_cfg_val(cfg, "mac");
- memset(nic_state, 0, sizeof(struct ne2k_context));
+ nic_state = (struct ne2k_state *)V3_Malloc(sizeof(struct ne2k_state));
+ memset(nic_state, 0, sizeof(struct ne2k_state));
- nic_state->pci_bus = pci;
+ nic_state->pci_bus = pci_bus;
+ nic_state->vm = vm;
- struct vm_device * device = v3_create_device("NE2K", &dev_ops, nic_state);
-
- return device;
+ if (macstr != NULL && !str2mac(macstr, nic_state->mac)) {
+ PrintDebug("NE2000: Mac specified %s\n", macstr);
+ }else {
+ PrintDebug("NE2000: MAC not specified\n");
+ random_ethaddr(nic_state->mac);
+ }
+
+ struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, nic_state);
+
+ if (dev == NULL) {
+ PrintError("NE2000: Could not attach device %s\n", dev_id);
+ V3_Free(nic_state);
+ return -1;
+ }
+
+ nic_state->dev = dev;
+
+ if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)nic_state) == -1) {
+ PrintError("NE2000: Could not register %s as net frontend\n", dev_id);
+ v3_remove_device(dev);
+ V3_Free(nic_state);
+ return -1;
+ }
+
+ return 0;
}
+device_register("NE2000", ne2k_init)