From: Lei Xia Date: Mon, 7 Feb 2011 23:29:33 +0000 (-0600) Subject: Fix the NE2k card X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=22dbf90548cb2ea56a9057a706e3da411dc1b57b;p=palacios.git Fix the NE2k card Fix the config on NE2k Minor formt of NET code --- diff --git a/palacios/include/palacios/vmm_ethernet.h b/palacios/include/palacios/vmm_ethernet.h index f7405fc..ddd1435 100644 --- a/palacios/include/palacios/vmm_ethernet.h +++ b/palacios/include/palacios/vmm_ethernet.h @@ -66,6 +66,37 @@ static inline int compare_ether_hdr(const uint8_t * hdr1, const uint8_t * hdr2) (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); } +/* AA:BB:CC:DD:EE:FF */ +static inline int str2mac(char * macstr, uint8_t * mac){ + char hex[2], *s = macstr; + int i = 0; + + while(s){ + memcpy(hex, s, 2); + mac[i++] = (char)atox(hex); + if (i == ETH_ALEN) return 0; + s=strchr(s, ':'); + if(s) s++; + } + + return -1; +} + + +/* generate random ethernet address */ +static inline void random_ethaddr(uint8_t * addr) +{ + uint64_t val; + + /* using current rdtsc as random number */ + rdtscll(val); + *(uint64_t *)addr = val; + + addr [0] &= 0xfe; /* clear multicast bit */ + addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ +} + + #endif #endif diff --git a/palacios/include/palacios/vmm_vnet.h b/palacios/include/palacios/vmm_vnet.h index 86af1a2..03d2298 100644 --- a/palacios/include/palacios/vmm_vnet.h +++ b/palacios/include/palacios/vmm_vnet.h @@ -25,26 +25,21 @@ #include #include -#define MAC_ANY 0 -#define MAC_NOT 1 -#define MAC_NONE 2 -#define MAC_ADDR 3 +#define MAC_ANY 0 +#define MAC_NOT 1 +#define MAC_NONE 2 +#define MAC_ADDR 3 -#define LINK_INTERFACE 0 -#define LINK_EDGE 1 -#define LINK_ANY 2 +#define LINK_INTERFACE 0 +#define LINK_EDGE 1 +#define LINK_ANY 2 -#define VNET_HASH_SIZE 17 -#define VMM_DRIVERN 1 -#define GUEST_DRIVERN 0 - -#define HOST_LNX_BRIDGE 1 -#define CTL_VM_BRIDGE 2 +#define VNET_HASH_SIZE 17 //routing table entry struct v3_vnet_route { - uint8_t src_mac[6]; - uint8_t dst_mac[6]; + uint8_t src_mac[ETH_ALEN]; + uint8_t dst_mac[ETH_ALEN]; uint8_t src_mac_qual; uint8_t dst_mac_qual; @@ -78,6 +73,28 @@ struct v3_vnet_pkt { } __attribute__((packed)); } __attribute__((packed)); +struct v3_vnet_bridge_ops { + int (*input)(struct v3_vm_info * vm, + struct v3_vnet_pkt * pkt, + void * private_data); + void (*poll)(struct v3_vm_info * vm, + void * private_data); +}; + +#define HOST_LNX_BRIDGE 1 +#define CTL_VM_BRIDGE 2 + +int v3_vnet_add_bridge(struct v3_vm_info * vm, + struct v3_vnet_bridge_ops * ops, + uint8_t type, + void * priv_data); +int v3_vnet_add_route(struct v3_vnet_route route); +int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data); + +#ifdef __V3VEE__ + +#define VMM_DRIVERN 1 +#define GUEST_DRIVERN 0 struct v3_vnet_dev_ops { int (*input)(struct v3_vm_info * vm, @@ -89,33 +106,17 @@ struct v3_vnet_dev_ops { void (*stop_tx)(void * dev_data); }; -struct v3_vnet_bridge_ops { - int (*input)(struct v3_vm_info * vm, - struct v3_vnet_pkt * pkt, - void * private_data); - void (*poll)(struct v3_vm_info * vm, - void * private_data); -}; - int v3_init_vnet(void); void v3_deinit_vnet(void); -int v3_vnet_send_pkt(struct v3_vnet_pkt * pkt, void * private_data); - void v3_vnet_poll(struct v3_vm_info * vm); -int v3_vnet_add_route(struct v3_vnet_route route); -int v3_vnet_add_bridge(struct v3_vm_info * vm, - struct v3_vnet_bridge_ops * ops, - uint8_t type, - void * priv_data); - - -int v3_vnet_add_dev(struct v3_vm_info * info, uint8_t mac[6], +int v3_vnet_add_dev(struct v3_vm_info * info, uint8_t * mac, struct v3_vnet_dev_ops * ops, void * priv_data); int v3_vnet_del_dev(int dev_id); +#endif #endif diff --git a/palacios/src/devices/Kconfig b/palacios/src/devices/Kconfig index 3d157d6..671625f 100644 --- a/palacios/src/devices/Kconfig +++ b/palacios/src/devices/Kconfig @@ -174,9 +174,10 @@ config NE2K help Includes the Virtual NE2K network card -config DEBUG_NE2k +config DEBUG_NE2K bool "NE2K debugging" - depends on NE2k && DEBUG_ON + default n + depends on NE2K && DEBUG_ON help Enable debugging for the NE2K diff --git a/palacios/src/devices/lnx_virtio_nic.c b/palacios/src/devices/lnx_virtio_nic.c index 56bf74e..654698f 100644 --- a/palacios/src/devices/lnx_virtio_nic.c +++ b/palacios/src/devices/lnx_virtio_nic.c @@ -89,7 +89,7 @@ struct virtio_dev_state { struct list_head dev_list; struct v3_vm_info *vm; - char mac[ETH_ALEN]; + uint8_t mac[ETH_ALEN]; }; struct virtio_net_state { @@ -823,35 +823,6 @@ static int connect_fn(struct v3_vm_info * info, return 0; } - -static int str2mac(char * macstr, char * mac){ - char hex[2], *s = macstr; - int i = 0; - - while(s){ - memcpy(hex, s, 2); - mac[i++] = (char)atox(hex); - if (i == ETH_ALEN) return 0; - s=strchr(s, ':'); - if(s) s++; - } - - return -1; -} - -static inline void random_ethaddr(uchar_t * addr) -{ - uint64_t val; - - /* using current rdtsc as random number */ - rdtscll(val); - *(uint64_t *)addr = val; - - addr [0] &= 0xfe; /* clear multicast bit */ - addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ -} - - static int virtio_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 virtio_dev_state * virtio_state = NULL; diff --git a/palacios/src/devices/ne2k.c b/palacios/src/devices/ne2k.c index bbe80c0..46594c3 100644 --- a/palacios/src/devices/ne2k.c +++ b/palacios/src/devices/ne2k.c @@ -17,19 +17,16 @@ * redistribute, and modify it as specified in the file "V3VEE_LICENSE". */ -/* -* Virtual NE2K Network Card -*/ - #include -#include #include -#include #include #include #include #include #include +#include +#include +#include #ifndef CONFIG_DEBUG_NE2K #undef PrintDebug @@ -37,83 +34,75 @@ #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; @@ -121,7 +110,7 @@ struct cmd_reg { 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)); @@ -232,7 +221,7 @@ struct rx_status_reg { 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)); @@ -240,12 +229,7 @@ struct rx_status_reg { } __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; @@ -255,22 +239,22 @@ struct ne2k_context { 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; @@ -279,7 +263,7 @@ struct ne2k_context { } __attribute__((packed)); - union { // current remote DMA addr + union { /* current remote DMA addr */ uint16_t crda; struct { uint8_t crda0; @@ -288,7 +272,7 @@ struct ne2k_context { } __attribute__((packed)); - union { // Remote Start Addr Reg + union { /* Remote Start Addr Reg */ uint16_t rsar; struct { uint8_t rsar0; @@ -297,7 +281,7 @@ struct ne2k_context { } __attribute__((packed)); - union { // TX Byte count Reg + union { /* TX Byte count Reg */ uint16_t tbcr; struct { uint8_t tbcr0; @@ -305,7 +289,7 @@ struct ne2k_context { } __attribute__((packed)); } __attribute__((packed)); - union { // Remote Byte count Reg + union { /* Remote Byte count Reg */ uint16_t rbcr; struct { uint8_t rbcr0; @@ -313,146 +297,73 @@ struct ne2k_context { } __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; } @@ -463,40 +374,40 @@ static int ne2k_rxbuf_full(struct vm_device *dev) { // 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; @@ -509,127 +420,99 @@ static void ne2k_receive(struct vm_device * dev, const uchar_t * pkt, int length } 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]; @@ -638,89 +521,93 @@ static uchar_t ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t 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; } @@ -728,213 +615,260 @@ static int ne2k_data_write(ushort_t port, void * src, uint_t length, struct vm_d 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; } @@ -943,10 +877,15 @@ static int ne2k_std_write(uint16_t port, void * src, uint_t length, struct vm_de } -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); @@ -954,164 +893,202 @@ static int ne2k_std_read(uint16_t port, void * dst, uint_t length, struct vm_dev } 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; @@ -1123,16 +1100,18 @@ static int ne2k_init_device(struct vm_device * dev) { 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; @@ -1145,50 +1124,113 @@ static int ne2k_init_device(struct vm_device * dev) { 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) diff --git a/palacios/src/palacios/vmm_vnet_core.c b/palacios/src/palacios/vmm_vnet_core.c index 99b61c7..6baef5a 100644 --- a/palacios/src/palacios/vmm_vnet_core.c +++ b/palacios/src/palacios/vmm_vnet_core.c @@ -100,7 +100,7 @@ static struct { #ifdef CONFIG_DEBUG_VNET -static inline void mac_to_string(char * mac, char * buf) { +static inline void mac_to_string(uint8_t * mac, char * buf) { snprintf(buf, 100, "%d:%d:%d:%d:%d:%d", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); @@ -209,15 +209,6 @@ static struct vnet_dev * dev_by_mac(uint8_t * mac) { return NULL; } -int v3_vnet_id_by_mac(char * mac){ - struct vnet_dev *dev = dev_by_mac(mac); - - if (dev == NULL) - return -1; - - return dev->dev_id; -} - int v3_vnet_add_route(struct v3_vnet_route route) { struct vnet_route_info * new_route = NULL; @@ -582,7 +573,7 @@ static void free_routes(){ } } - +/* TODO: Round-bin or ?? */ void v3_vnet_poll(struct v3_vm_info * vm){ struct vnet_dev * dev = NULL; struct vnet_brg_dev *bridge = vnet_state.bridge;