2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Lei Xia <lxia@northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <devices/pci.h>
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_io.h>
23 #include <palacios/vmm_debug.h>
24 #include <palacios/vmm_string.h>
25 #include <palacios/vmm_dev_mgr.h>
26 #include <palacios/vmm_intr.h>
27 #include <palacios/vmm_ethernet.h>
28 #include <palacios/vm_guest.h>
29 #include <palacios/vmm_sprintf.h>
31 #ifndef V3_CONFIG_DEBUG_NE2K
33 #define PrintDebug(fmts, args...)
37 #define NE2K_DEFAULT_IRQ 11
39 // What the hell is this crap?
40 #define NE2K_PMEM_SIZE (32 * 1024)
41 #define NE2K_PMEM_START (16 * 1024)
42 #define NE2K_PMEM_END (NE2K_PMEM_SIZE + NE2K_PMEM_START)
43 #define NE2K_MEM_SIZE NE2K_PMEM_END
45 #define NIC_REG_BASE_PORT 0xc100 /* Command register (for all pages) */
47 #define NE2K_CMD_OFFSET 0x00
48 #define NE2K_DATA_OFFSET 0x10
49 #define NE2K_RESET_OFFSET 0x1f
51 /* Page 0 registers */
52 #define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
53 #define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
54 #define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
55 #define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
56 #define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
57 #define EN0_TSR 0x04 /* Transmit status reg RD */
58 #define EN0_TPSR 0x04 /* Transmit starting page WR */
59 #define EN0_NCR 0x05 /* Number of collision reg RD */
60 #define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
61 #define EN0_FIFO 0x06 /* FIFO RD */
62 #define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
63 #define EN0_ISR 0x07 /* Interrupt status reg RD WR */
64 #define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
65 #define EN0_RSARLO 0x08 /* Remote start address reg 0 */
66 #define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
67 #define EN0_RSARHI 0x09 /* Remote start address reg 1 */
68 #define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
69 #define EN0_RTL8029ID0 0x0a /* Realtek ID byte #1 RD */
70 #define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
71 #define EN0_RTL8029ID1 0x0b /* Realtek ID byte #2 RD */
72 #define EN0_RSR 0x0c /* rx status reg RD */
73 #define EN0_RXCR 0x0c /* RX configuration reg WR */
74 #define EN0_TXCR 0x0d /* TX configuration reg WR */
75 #define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
76 #define EN0_DCFG 0x0e /* Data configuration reg WR */
77 #define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
78 #define EN0_IMR 0x0f /* Interrupt mask reg WR */
79 #define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
81 /* Page 1 registers */
83 #define EN1_CURPAG 0x07
86 /* Page 2 registers */
87 #define EN2_STARTPG 0x01 /* Starting page of ring bfr RD */
88 #define EN2_STOPPG 0x02 /* Ending page +1 of ring bfr RD */
89 #define EN2_LDMA0 0x01 /* Current Local DMA Address 0 WR */
90 #define EN2_LDMA1 0x02 /* Current Local DMA Address 1 WR */
91 #define EN2_RNPR 0x03 /* Remote Next Packet Pointer RD WR */
92 #define EN2_TPSR 0x04 /* Transmit Page Start Address RD */
93 #define EN2_LNRP 0x05 /* Local Next Packet Pointer RD WR */
94 #define EN2_ACNT0 0x06 /* Address Counter Upper WR */
95 #define EN2_ACNT1 0x07 /* Address Counter Lower WR */
96 #define EN2_RCR 0x0c /* Receive Configuration Register RD */
97 #define EN2_TCR 0x0d /* Transmit Configuration Register RD */
98 #define EN2_DCR 0x0e /* Data Configuration Register RD */
99 #define EN2_IMR 0x0f /* Interrupt Mask Register RD */
101 /* Page 3 registers */
102 #define EN3_CONFIG0 0x03
103 #define EN3_CONFIG1 0x04
104 #define EN3_CONFIG2 0x05
105 #define EN3_CONFIG3 0x06
115 uint8_t rem_dma_cmd : 3; /* 0=Not allowed, 1=Read, 2=Write, 3=Send Pkt, 4=Abort/Complete DMA */
117 } __attribute__((packed));
118 } __attribute__((packed));
119 } __attribute__((packed));
122 struct intr_status_reg {
130 uint8_t overwrite_warn : 1;
131 uint8_t cnt_overflow : 1;
132 uint8_t rem_dma_done : 1;
133 uint8_t reset_status : 1;
134 } __attribute__((packed));
135 } __attribute__((packed));
136 } __attribute__((packed));
139 struct intr_mask_reg {
147 uint8_t overwrite_warn : 1;
148 uint8_t cnt_overflow : 1;
149 uint8_t rem_dma_done : 1;
151 } __attribute__((packed));
152 } __attribute__((packed));
153 } __attribute__((packed));
156 struct data_cfg_reg {
160 uint8_t word_trans_sel : 1;
161 uint8_t byte_order_sel : 1;
162 uint8_t long_addr_sel : 1;
163 uint8_t loopback_sel : 1;
164 uint8_t auto_init_rem : 1;
165 uint8_t fifo_thresh_sel : 2;
167 } __attribute__((packed));
168 } __attribute__((packed));
169 } __attribute__((packed));
176 uint8_t inhibit_crc : 1;
177 uint8_t enc_loop_ctrl : 2;
178 uint8_t auto_tx_disable : 1;
179 uint8_t coll_offset_en : 1;
181 } __attribute__((packed));
182 } __attribute__((packed));
183 } __attribute__((packed));
185 struct tx_status_reg {
189 uint8_t pkt_tx_ok : 1;
191 uint8_t tx_collision : 1;
192 uint8_t tx_aborted : 1;
193 uint8_t carrier_lost : 1;
194 uint8_t fifo_underrun : 1;
195 uint8_t cd_heartbeat : 1;
196 uint8_t oow_collision : 1;
197 } __attribute__((packed));
198 } __attribute__((packed));
199 } __attribute__((packed));
205 uint8_t save_pkt_errs : 1;
206 uint8_t runt_pkt_ok : 1;
207 uint8_t bcast_ok : 1;
208 uint8_t mcast_ok : 1;
209 uint8_t prom_phys_enable : 1;
210 uint8_t mon_mode : 1;
212 } __attribute__((packed));
213 } __attribute__((packed));
214 } __attribute__((packed));
217 struct rx_status_reg {
221 uint8_t pkt_rx_ok : 1;
223 uint8_t frame_align_err : 1;
224 uint8_t fifo_overrun : 1;
225 uint8_t missed_pkt : 1;
226 uint8_t phy_match : 1; /* 0=Physical Addr Match, 1=MCAST/BCAST Addr Match */
227 uint8_t rx_disabled : 1;
228 uint8_t deferring : 1;
229 } __attribute__((packed));
230 } __attribute__((packed));
231 } __attribute__((packed));
234 struct ne2k_registers {
236 struct intr_status_reg isr;
237 struct intr_mask_reg imr;
238 struct data_cfg_reg dcr;
239 struct tx_cfg_reg tcr;
240 struct tx_status_reg tsr;
241 struct rx_cfg_reg rcr;
242 struct rx_status_reg rsr;
244 uint8_t pgstart; /* page start reg */
245 uint8_t pgstop; /* page stop reg */
246 uint8_t boundary; /* boundary ptr */
247 uint8_t tpsr; /* tx page start addr */
248 uint8_t ncr; /* number of collisions */
249 uint8_t fifo; /* FIFO... */
251 uint8_t curpag; /* current page */
252 uint8_t rnpp; /* rem next pkt ptr */
253 uint8_t lnpp; /* local next pkt ptr */
255 uint8_t cntr0; /* counter 0 (frame alignment errors) */
256 uint8_t cntr1; /* counter 1 (CRC Errors) */
257 uint8_t cntr2; /* counter 2 (missed pkt errors) */
259 union { /* current local DMA Addr */
264 } __attribute__((packed));
265 } __attribute__((packed));
268 union { /* current remote DMA addr */
273 } __attribute__((packed));
274 } __attribute__((packed));
277 union { /* Remote Start Addr Reg */
282 } __attribute__((packed));
283 } __attribute__((packed));
286 union { /* TX Byte count Reg */
291 } __attribute__((packed));
292 } __attribute__((packed));
294 union { /* Remote Byte count Reg */
299 } __attribute__((packed));
300 } __attribute__((packed));
302 union { /* Address counter? */
307 } __attribute__((packed));
308 } __attribute__((packed));
313 struct v3_vm_info * vm;
314 struct pci_device * pci_dev;
315 struct vm_device * pci_bus;
316 struct vm_device * dev;
318 struct ne2k_registers context;
319 uint8_t mem[NE2K_MEM_SIZE];
321 uint8_t mcast_addr[8];
322 uint8_t mac[ETH_ALEN];
324 struct nic_statistics statistics;
326 struct v3_dev_net_ops *net_ops;
330 static int ne2k_update_irq(struct ne2k_state * nic_state) {
331 struct pci_device * pci_dev = nic_state->pci_dev;
333 if ((nic_state->context.isr.val & nic_state->context.imr.val) & 0x7f) {
334 if (pci_dev == NULL){
335 v3_raise_virq(&(nic_state->vm->cores[0]), NE2K_DEFAULT_IRQ);
337 v3_pci_raise_irq(nic_state->pci_bus, nic_state->pci_dev, 0);
340 nic_state->statistics.rx_interrupts ++;
342 PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Raise IRQ\n");
348 static int tx_one_pkt(struct ne2k_state * nic_state, uchar_t *pkt, uint32_t length) {
350 #ifdef V3_CONFIG_DEBUG_NE2K
351 PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Send Packet:\n");
352 v3_hexdump(pkt, length, NULL, 0);
355 if(nic_state->net_ops->send(pkt, length, nic_state->backend_data) >= 0){
356 nic_state->statistics.tx_pkts ++;
357 nic_state->statistics.tx_bytes += length;
362 nic_state->statistics.tx_dropped ++;
367 static int ne2k_rxbuf_full(struct ne2k_registers * regs) {
372 index = regs->curpag << 8;
373 boundary = regs->boundary << 8;
375 if (index < boundary) {
376 empty = boundary - index;
378 empty = ((regs->pgstop - regs->pgstart) << 8) - (index - boundary);
381 if (empty < (ETHERNET_PACKET_LEN + 4)) {
388 #define MIN_BUF_SIZE 60
391 // This needs to be completely redone...
392 static int rx_one_pkt(struct ne2k_state * nic_state, const uchar_t * pkt, uint32_t length) {
393 struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
403 start = regs->pgstart << 8;
404 stop = regs->pgstop << 8;
406 if (regs->cmd.stop) {
410 if (ne2k_rxbuf_full(regs)) {
411 PrintError(VM_NONE, VCORE_NONE, "Ne2k: received buffer overflow\n");
415 //packet too small, expand it
416 if (length < MIN_BUF_SIZE) {
417 uchar_t buf[MIN_BUF_SIZE];
419 memcpy(buf, pkt, length);
420 memset(buf + length, 0, MIN_BUF_SIZE - length);
422 length = MIN_BUF_SIZE;
425 index = regs->curpag << 8;
428 total_len = length + 4;
430 //address for next packet (4 bytes for CRC)
431 next = index + ((total_len + 4 + 255) & ~0xff);
434 next -= (stop - start);
437 p = nic_state->mem + index;
439 regs->rsr.pkt_rx_ok = 1;
442 regs->rsr.phy_match = 1; /* TODO: Check this back */
445 p[0] = regs->rsr.val;
448 p[3] = total_len >> 8;
453 empty = stop - index;
464 memcpy(nic_state->mem + index, pkt, len);
475 regs->curpag = next >> 8;
477 regs->isr.pkt_rx = 1;
478 ne2k_update_irq(nic_state);
484 static int ne2k_rx(uint8_t * buf, uint32_t size, void * private_data){
485 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
487 #ifdef V3_CONFIG_DEBUG_NE2K
488 PrintDebug(VM_NONE, VCORE_NONE, "\nNe2k: Packet Received:\n");
489 v3_hexdump(buf, size, NULL, 0);
492 if(!rx_one_pkt(nic_state, buf, size)){
493 nic_state->statistics.rx_pkts ++;
494 nic_state->statistics.rx_bytes += size;
499 nic_state->statistics.rx_dropped ++;
505 static inline void mem_writeb(struct ne2k_state * nic_state,
508 uchar_t tmp = (uchar_t) (val & 0x000000ff);
510 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
511 nic_state->mem[addr] = tmp;
515 static inline void mem_writew(struct ne2k_state * nic_state,
520 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
521 *(uint16_t *)(nic_state->mem + addr) = val;
525 static inline void mem_writel(struct ne2k_state * nic_state,
530 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
531 *(uint32_t *)(nic_state->mem + addr) = val;
535 static inline uint8_t mem_readb(struct ne2k_state * nic_state, uint32_t addr) {
537 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
538 return nic_state->mem[addr];
544 static inline uint16_t mem_readw(struct ne2k_state * nic_state, uint32_t addr) {
547 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
548 return *(uint16_t *)(nic_state->mem + addr);
554 static uint32_t mem_readl(struct ne2k_state * nic_state, uint32_t addr) {
557 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
558 return *(uint32_t *)(nic_state->mem + addr);
565 static void dma_update( struct ne2k_state * nic_state, int len) {
566 struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
571 if (regs->rsar == regs->pgstop) {
572 regs->rsar = regs->pgstart;
575 if (regs->rbcr <= len) {
577 regs->isr.rem_dma_done = 1;
578 ne2k_update_irq(nic_state);
584 static int ne2k_data_read(struct guest_info * core,
588 void * private_data) {
589 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
591 struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
593 // current dma address
594 uint32_t addr = regs->rsar;
598 val = mem_readb(nic_state, addr);
601 val = mem_readw(nic_state, addr);
604 val = mem_readl(nic_state, addr);
607 PrintError(VM_NONE, VCORE_NONE, "ne2k_data_read error: invalid length %d\n", length);
611 dma_update(nic_state, length);
612 memcpy(dst, &val, length);
614 PrintDebug(VM_NONE, VCORE_NONE, "NE2000 read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
619 static int ne2k_data_write(struct guest_info * core,
623 void * private_data) {
624 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
626 struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
628 uint32_t addr = regs->rsar;
630 if (regs->rbcr == 0) {
634 memcpy(&val, src, length);
638 mem_writeb(nic_state, addr, val);
641 mem_writew(nic_state, addr, val);
644 mem_writel(nic_state, addr, val);
647 PrintError(VM_NONE, VCORE_NONE, "NE2000 port write error: invalid length %d\n", length);
650 dma_update(nic_state, length);
652 PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Write port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
658 static void ne2k_init_state(struct ne2k_state * nic_state) {
661 /* Not sure what this is about.... */
662 memset(nic_state->mem, 0xff, 32);
664 memcpy(nic_state->mem, nic_state->mac, ETH_ALEN);
665 memset(nic_state->mcast_addr, 0xff, sizeof(nic_state->mcast_addr));
666 nic_state->mem[14] = 0x57;
667 nic_state->mem[15] = 0x57;
669 /* initiate registers */
670 nic_state->context.isr.reset_status = 1;
671 nic_state->context.imr.val = 0x00;
672 nic_state->context.cmd.val = 0x22;
675 static int reset_device(struct ne2k_state * nic_state) {
676 ne2k_init_state(nic_state);
678 PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Reset device\n");
684 static int ne2k_reset_port_read(struct guest_info * core,
688 void * private_data) {
689 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
691 memset(dst, 0, length);
692 reset_device(nic_state);
697 static int ne2k_reset_port_write(struct guest_info * core,
701 void * private_data) {
708 static int ne2k_cmd_write(struct guest_info * core,
712 void * private_data) {
713 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
714 struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
717 PrintError(core->vm_info, core, "Invalid write length to NE2000 Command register\n");
721 regs->cmd.val = *(uint8_t *)src;
723 if (!(regs->cmd.stop)) {
724 regs->isr.reset_status = 0;
726 // if ((send pkt) && (dma byte count == 0))
727 if ((regs->cmd.rem_dma_cmd & 0x3) && (regs->rbcr == 0)) {
728 regs->isr.rem_dma_done = 1;
729 ne2k_update_irq(nic_state);
732 if (regs->cmd.tx_pkt) {
733 int offset = (regs->tpsr << 8);
735 if (offset >= NE2K_PMEM_END) {
736 offset -= NE2K_PMEM_SIZE;
739 if (offset + regs->tbcr <= NE2K_PMEM_END) {
740 tx_one_pkt(nic_state, nic_state->mem + offset, regs->tbcr);
743 regs->tsr.val = 0; /* clear the tx status reg */
744 regs->tsr.pkt_tx_ok = 1; /* indicate successful tx */
746 regs->isr.pkt_tx = 1; /* irq due to pkt tx */
747 regs->cmd.tx_pkt = 0; /* reset cmd bit */
749 ne2k_update_irq(nic_state);
752 /* stop the controller */
758 static int ne2k_cmd_read(struct guest_info * core,
762 void * private_data) {
763 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
766 PrintError(core->vm_info, core, "Invalid read length to NE2000 Command register\n");
770 *(uint8_t *)dst = nic_state->context.cmd.val;
772 PrintDebug(core->vm_info, core, "ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
776 static int ne2k_std_write(struct guest_info * core,
780 void * private_data) {
781 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
782 struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
783 int idx = port & 0x1f;
784 uint8_t page = regs->cmd.pg_sel;
787 PrintError(core->vm_info, core, "NE2000 port write error: length %d port 0x%xnot equal to 1\n", length, port);
791 uint8_t val = *(uint8_t *)src;
793 PrintDebug(core->vm_info, core, "NE2000: write port:0x%x val: 0x%x\n", port, (uint8_t)val);
804 regs->boundary = val;
816 regs->isr.val &= ~(val & 0x7f);
817 ne2k_update_irq(nic_state);
842 ne2k_update_irq(nic_state);
846 PrintError(core->vm_info, core, "NE2000 port write error: invalid port:0x%x\n", port);
849 } else if (page == 1) {
851 case EN1_PHYS ... EN1_PHYS + ETH_ALEN -1:
852 nic_state->mac[port - EN1_PHYS] = val;
857 case EN1_MULT ... EN1_MULT + 7:
858 nic_state->mcast_addr[port - EN1_MULT] = val;
862 PrintError(core->vm_info, core, "NE2000 write port error: invalid port:0x%x\n", port);
865 } else if (page == 2) {
887 PrintError(core->vm_info, core, "NE2000 write port error: invalid port:0x%x\n", port);
891 PrintError(core->vm_info, core, "NE2000: Invalid Register Page Value\n");
900 static int ne2k_std_read(struct guest_info * core,
904 void * private_data) {
905 struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
906 struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
907 uint16_t index = port & 0x1f;
908 uint8_t page = regs->cmd.pg_sel;
911 PrintError(core->vm_info, core, "ne2k_read error: length %d\n", length);
918 *(uint8_t *)dst = regs->clda0;
921 *(uint8_t *)dst = regs->clda1;
924 *(uint8_t *)dst = regs->boundary;
927 *(uint8_t *)dst = regs->tsr.val;
930 *(uint8_t *)dst = regs->ncr;
933 *(uint8_t *)dst = regs->fifo;
936 *(uint8_t *)dst = regs->isr.val;
937 ne2k_update_irq(nic_state);
940 *(uint8_t *)dst = regs->crda0;
943 *(uint8_t *)dst = regs->crda1;
946 *(uint8_t *)dst = regs->rsr.val;
949 *(uint8_t *)dst = regs->cntr0;
952 *(uint8_t *)dst = regs->cntr1;
955 *(uint8_t *)dst = regs->cntr2;
959 PrintError(core->vm_info, core, "NE2000 port read error: invalid port:0x%x\n", port);
962 } else if (page == 1) {
964 case EN1_PHYS ... EN1_PHYS + ETH_ALEN -1:
965 *(uint8_t *)dst = nic_state->mac[index - EN1_PHYS];
968 *(uint8_t *)dst = regs->curpag;
970 case EN1_MULT ... EN1_MULT + 7:
971 *(uint8_t *)dst = nic_state->mcast_addr[index - EN1_MULT];
975 PrintError(core->vm_info, core, "ne2k_read error: invalid port:0x%x\n", port);
978 } else if (page == 2) {
981 *(uint8_t *)dst = regs->pgstart;
984 *(uint8_t *)dst = regs->pgstop;
987 *(uint8_t *)dst = regs->rnpp;
990 *(uint8_t *)dst = regs->lnpp;
993 *(uint8_t *)dst = regs->tpsr;
996 *(uint8_t *)dst = regs->addcnt0;
999 *(uint8_t *)dst = regs->addcnt1;
1002 *(uint8_t *)dst = regs->rcr.val;
1005 *(uint8_t *)dst = regs->tcr.val;
1008 *(uint8_t *)dst = regs->dcr.val;
1011 *(uint8_t *)dst = regs->imr.val;
1014 PrintError(core->vm_info, core, "NE2000 port read error: invalid port:0x%x\n", port);
1018 PrintError(core->vm_info, core, "NE2000 port read: Invalid Register Page Value\n");
1022 PrintDebug(core->vm_info, core, "NE2000 port read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
1029 static int ne2k_pci_write(struct guest_info * core,
1033 void * private_data) {
1034 uint16_t idx = port & 0x1f;
1038 case NE2K_CMD_OFFSET:
1039 ret = ne2k_cmd_write(core, port, src, length, private_data);
1041 case NE2K_CMD_OFFSET+1 ... NE2K_CMD_OFFSET+15:
1042 ret = ne2k_std_write(core, port, src, length, private_data);
1044 case NE2K_DATA_OFFSET:
1045 ret = ne2k_data_write(core, port, src, length, private_data);
1047 case NE2K_RESET_OFFSET:
1048 ret = ne2k_reset_port_write(core, port, src, length, private_data);
1052 PrintError(core->vm_info, core, "NE2000 port write error: invalid port:0x%x\n", port);
1059 static int ne2k_pci_read(struct guest_info * core,
1063 void * private_data) {
1064 uint16_t idx = port & 0x1f;
1068 case NE2K_CMD_OFFSET:
1069 ret = ne2k_cmd_read(core, port, dst, length, private_data);
1071 case NE2K_CMD_OFFSET+1 ... NE2K_CMD_OFFSET+15:
1072 ret = ne2k_std_read(core, port, dst, length, private_data);
1074 case NE2K_DATA_OFFSET:
1075 ret = ne2k_data_read(core, port, dst, length, private_data);
1077 case NE2K_RESET_OFFSET:
1078 ret = ne2k_reset_port_read(core, port, dst, length, private_data);
1082 PrintError(core->vm_info, core, "NE2000 port read error: invalid port:0x%x\n", port);
1091 static int pci_config_update(struct pci_device * pci_dev,
1095 void * private_data) {
1096 PrintDebug(VM_NONE, VCORE_NONE, "PCI Config Update\n");
1098 /* Do we need this? */
1104 static int register_dev(struct ne2k_state * nic_state)
1108 if (nic_state->pci_bus != NULL) {
1109 struct v3_pci_bar bars[6];
1110 struct pci_device * pci_dev = NULL;
1112 PrintDebug(VM_NONE, VCORE_NONE, "NE2000: PCI Enabled\n");
1114 for (i = 0; i < 6; i++) {
1115 bars[i].type = PCI_BAR_NONE;
1118 bars[0].type = PCI_BAR_IO;
1119 bars[0].default_base_port = -1;
1120 bars[0].num_ports = 256;
1122 bars[0].io_read = ne2k_pci_read;
1123 bars[0].io_write = ne2k_pci_write;
1124 bars[0].private_data = nic_state;
1126 pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
1128 pci_config_update, NULL, NULL, NULL, nic_state);
1131 if (pci_dev == NULL) {
1132 PrintError(VM_NONE, VCORE_NONE, "NE2000: Could not register PCI Device\n");
1136 pci_dev->config_header.vendor_id = 0x10ec;
1137 pci_dev->config_header.device_id = 0x8029;
1138 pci_dev->config_header.revision = 0x00;
1140 pci_dev->config_header.subclass = 0x00;
1141 pci_dev->config_header.class = 0x02;
1142 pci_dev->config_header.header_type = 0x00;
1144 pci_dev->config_header.intr_line = 11;
1145 pci_dev->config_header.intr_pin = 1;
1147 nic_state->pci_dev = pci_dev;
1149 PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Not attached to PCI\n");
1151 v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
1153 for (i = 1; i < 16; i++){
1154 v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
1157 v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_DATA_OFFSET, &ne2k_data_read, &ne2k_data_write);
1158 v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_RESET_OFFSET, &ne2k_reset_port_read, &ne2k_reset_port_write);
1165 static int connect_fn(struct v3_vm_info * info,
1166 void * frontend_data,
1167 struct v3_dev_net_ops * ops,
1168 v3_cfg_tree_t * cfg,
1169 void * private_data) {
1170 struct ne2k_state * nic_state = (struct ne2k_state *)frontend_data;
1172 ne2k_init_state(nic_state);
1173 register_dev(nic_state);
1175 nic_state->net_ops = ops;
1176 nic_state->backend_data = private_data;
1178 ops->recv = ne2k_rx;
1180 ops->config.frontend_data = nic_state;
1181 ops->config.fnt_mac = nic_state->mac;
1187 static int ne2k_free(struct ne2k_state * nic_state) {
1190 /* dettached from backend */
1192 if(nic_state->pci_bus == NULL){
1193 for (i = 0; i < 16; i++){
1194 v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + i);
1197 v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_DATA_OFFSET);
1198 v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_RESET_OFFSET);
1200 /* unregistered from PCI? */
1209 static struct v3_device_ops dev_ops = {
1210 .free = (int (*)(void *))ne2k_free,
1214 static int ne2k_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1215 struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
1216 struct ne2k_state * nic_state = NULL;
1217 char * dev_id = v3_cfg_val(cfg, "ID");
1218 char * macstr = v3_cfg_val(cfg, "mac");
1220 nic_state = (struct ne2k_state *)V3_Malloc(sizeof(struct ne2k_state));
1223 PrintError(vm, VCORE_NONE, "Cannot allocate in init\n");
1227 memset(nic_state, 0, sizeof(struct ne2k_state));
1229 nic_state->pci_bus = pci_bus;
1232 if (macstr != NULL && !str2mac(macstr, nic_state->mac)) {
1233 PrintDebug(vm, VCORE_NONE, "NE2000: Mac specified %s\n", macstr);
1235 PrintDebug(vm, VCORE_NONE, "NE2000: MAC not specified\n");
1236 random_ethaddr(nic_state->mac);
1239 struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, nic_state);
1242 PrintError(vm, VCORE_NONE, "NE2000: Could not attach device %s\n", dev_id);
1247 nic_state->dev = dev;
1249 if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)nic_state) == -1) {
1250 PrintError(vm, VCORE_NONE, "NE2000: Could not register %s as net frontend\n", dev_id);
1251 v3_remove_device(dev);
1259 device_register("NE2000", ne2k_init)