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".
21 * Virtual NE2K Network Card
24 #include <devices/pci.h>
25 #include <devices/ne2k.h>
26 #include <palacios/vmm.h>
27 #include <palacios/vmm_types.h>
28 #include <palacios/vmm_io.h>
29 #include <palacios/vmm_debug.h>
30 #include <palacios/vmm_string.h>
34 #define PrintDebug(fmts, args...)
40 #define NE2K_DEFAULT_IRQ 11
42 #define MAX_ETH_FRAME_SIZE 1514
45 // What the hell is this crap?
46 #define NE2K_PMEM_SIZE (32 * 1024)
47 #define NE2K_PMEM_START (16 * 1024)
48 #define NE2K_PMEM_END (NE2K_PMEM_SIZE + NE2K_PMEM_START)
49 #define NE2K_MEM_SIZE NE2K_PMEM_END
51 #define NIC_REG_BASE_PORT 0xc100 //Command register (for all pages)
52 #define NIC_DATA_PORT 0xc110 //Data read/write port
53 #define NIC_RESET_PORT 0xc11f //Data read/write port
56 #define EN0_CLDALO 0x01 //Low byte of current local dma addr RD
57 #define EN0_STARTPG 0x01 //Starting page of ring bfr WR
58 #define EN0_CLDAHI 0x02 //High byte of current local dma addr RD
59 #define EN0_STOPPG 0x02 //Ending page +1 of ring bfr WR
60 #define EN0_BOUNDARY 0x03 //Boundary page of ring bfr RD WR
61 #define EN0_TSR 0x04 //Transmit status reg RD
62 #define EN0_TPSR 0x04 //Transmit starting page WR
63 #define EN0_NCR 0x05 //Number of collision reg RD
64 #define EN0_TCNTLO 0x05 //Low byte of tx byte count WR
65 #define EN0_FIFO 0x06 //FIFO RD
66 #define EN0_TCNTHI 0x06 //High byte of tx byte count WR
67 #define EN0_ISR 0x07 //Interrupt status reg RD WR
68 #define EN0_CRDALO 0x08 //low byte of current remote dma address RD
69 #define EN0_RSARLO 0x08 //Remote start address reg 0
70 #define EN0_CRDAHI 0x09 //high byte, current remote dma address RD
71 #define EN0_RSARHI 0x09 //Remote start address reg 1
72 #define EN0_RCNTLO 0x0a //Remote byte count reg WR
73 #define EN0_RTL8029ID0 0x0a //Realtek ID byte #1 RD
74 #define EN0_RCNTHI 0x0b //Remote byte count reg WR
75 #define EN0_RTL8029ID1 0x0b //Realtek ID byte #2 RD
76 #define EN0_RSR 0x0c //rx status reg RD
77 #define EN0_RXCR 0x0c //RX configuration reg WR
78 #define EN0_TXCR 0x0d //TX configuration reg WR
79 #define EN0_COUNTER0 0x0d //Rcv alignment error counter RD
80 #define EN0_DCFG 0x0e //Data configuration reg WR
81 #define EN0_COUNTER1 0x0e //Rcv CRC error counter RD
82 #define EN0_IMR 0x0f //Interrupt mask reg WR
83 #define EN0_COUNTER2 0x0f //Rcv missed frame error counter RD
87 #define EN1_CURPAG 0x07
91 #define EN2_STARTPG 0x01 //Starting page of ring bfr RD
92 #define EN2_STOPPG 0x02 //Ending page +1 of ring bfr RD
93 #define EN2_LDMA0 0x01 //Current Local DMA Address 0 WR
94 #define EN2_LDMA1 0x02 //Current Local DMA Address 1 WR
95 #define EN2_RNPR 0x03 //Remote Next Packet Pointer RD WR
96 #define EN2_TPSR 0x04 //Transmit Page Start Address RD
97 #define EN2_LNRP 0x05 //Local Next Packet Pointer RD WR
98 #define EN2_ACNT0 0x06 //Address Counter Upper WR
99 #define EN2_ACNT1 0x07 //Address Counter Lower WR
100 #define EN2_RCR 0x0c //Receive Configuration Register RD
101 #define EN2_TCR 0x0d //Transmit Configuration Register RD
102 #define EN2_DCR 0x0e //Data Configuration Register RD
103 #define EN2_IMR 0x0f //Interrupt Mask Register RD
106 #define EN3_CONFIG0 0x03
107 #define EN3_CONFIG1 0x04
108 #define EN3_CONFIG2 0x05
109 #define EN3_CONFIG3 0x06
113 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
122 uint8_t rem_dma_cmd : 3; // 0=Not allowed, 1=Read, 2=Write, 3=Send Pkt, 4=Abort/Complete DMA
124 } __attribute__((packed));
125 } __attribute__((packed));
126 } __attribute__((packed));
129 struct intr_status_reg {
137 uint8_t overwrite_warn : 1;
138 uint8_t cnt_overflow : 1;
139 uint8_t rem_dma_done : 1;
140 uint8_t reset_status : 1;
141 } __attribute__((packed));
142 } __attribute__((packed));
143 } __attribute__((packed));
146 struct intr_mask_reg {
154 uint8_t overwrite_warn : 1;
155 uint8_t cnt_overflow : 1;
156 uint8_t rem_dma_done : 1;
158 } __attribute__((packed));
159 } __attribute__((packed));
160 } __attribute__((packed));
163 struct data_cfg_reg {
167 uint8_t word_trans_sel : 1;
168 uint8_t byte_order_sel : 1;
169 uint8_t long_addr_sel : 1;
170 uint8_t loopback_sel : 1;
171 uint8_t auto_init_rem : 1;
172 uint8_t fifo_thresh_sel : 2;
174 } __attribute__((packed));
175 } __attribute__((packed));
176 } __attribute__((packed));
183 uint8_t inhibit_crc : 1;
184 uint8_t enc_loop_ctrl : 2;
185 uint8_t auto_tx_disable : 1;
186 uint8_t coll_offset_en : 1;
188 } __attribute__((packed));
189 } __attribute__((packed));
190 } __attribute__((packed));
192 struct tx_status_reg {
196 uint8_t pkt_tx_ok : 1;
198 uint8_t tx_collision : 1;
199 uint8_t tx_aborted : 1;
200 uint8_t carrier_lost : 1;
201 uint8_t fifo_underrun : 1;
202 uint8_t cd_heartbeat : 1;
203 uint8_t oow_collision : 1;
204 } __attribute__((packed));
205 } __attribute__((packed));
206 } __attribute__((packed));
212 uint8_t save_pkt_errs : 1;
213 uint8_t runt_pkt_ok : 1;
214 uint8_t bcast_ok : 1;
215 uint8_t mcast_ok : 1;
216 uint8_t prom_phys_enable : 1;
217 uint8_t mon_mode : 1;
219 } __attribute__((packed));
220 } __attribute__((packed));
221 } __attribute__((packed));
224 struct rx_status_reg {
228 uint8_t pkt_rx_ok : 1;
230 uint8_t frame_align_err : 1;
231 uint8_t fifo_overrun : 1;
232 uint8_t missed_pkt : 1;
233 uint8_t phy_match : 1; // 0=Physical Addr Match, 1=MCAST/BCAST Addr Match
234 uint8_t rx_disabled : 1;
235 uint8_t deferring : 1;
236 } __attribute__((packed));
237 } __attribute__((packed));
238 } __attribute__((packed));
241 struct ne2k_context {
242 struct guest_info * vm;
244 nic_state_t dev_state;
248 struct intr_status_reg isr;
249 struct intr_mask_reg imr;
250 struct data_cfg_reg dcr;
251 struct tx_cfg_reg tcr;
252 struct tx_status_reg tsr;
253 struct rx_cfg_reg rcr;
254 struct rx_status_reg rsr;
256 uint8_t pgstart; // page start reg
257 uint8_t pgstop; // page stop reg
258 uint8_t boundary; // boundary ptr
259 uint8_t tpsr; // tx page start addr
260 uint8_t ncr; // number of collisions
261 uint8_t fifo; // FIFO...
263 uint8_t curpag; // current page
264 uint8_t rnpp; // rem next pkt ptr
265 uint8_t lnpp; // local next pkt ptr
267 uint8_t cntr0; // counter 0 (frame alignment errors)
268 uint8_t cntr1; // counter 1 (CRC Errors)
269 uint8_t cntr2; // counter 2 (missed pkt errors)
271 union { // current local DMA Addr
276 } __attribute__((packed));
277 } __attribute__((packed));
280 union { // current remote DMA addr
285 } __attribute__((packed));
286 } __attribute__((packed));
289 union { // Remote Start Addr Reg
294 } __attribute__((packed));
295 } __attribute__((packed));
298 union { // TX Byte count Reg
303 } __attribute__((packed));
304 } __attribute__((packed));
306 union { // Remote Byte count Reg
311 } __attribute__((packed));
312 } __attribute__((packed));
316 union { // Address counter?
321 } __attribute__((packed));
322 } __attribute__((packed));
328 uint8_t mcast_addr[8]; // multicast mask array
329 uint8_t mac_addr[6]; // MAC Addr
334 uint8_t mem[NE2K_MEM_SIZE];
336 struct pci_device * pci_dev;
337 struct vm_device * pci_bus;
340 #define compare_mac(src, dst) !memcmp(src, dst, 6)
343 static void dump_state(struct vm_device * dev) {
344 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
348 PrintDebug("====NE2000: Dumping state Begin ==========\n");
349 PrintDebug("Registers:\n");
351 // JRL: Dump Registers
353 PrintDebug("Memory:\n");
355 for(i = 0; i < 32; i++) {
356 PrintDebug("0x%02x ", nic_state->mem[i]);
360 PrintDebug("====NE2000: Dumping state End==========\n");
366 static int ne2k_update_irq(struct vm_device *dev) {
367 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
368 struct pci_device * pci_dev = nic_state->pci_dev;
371 if (pci_dev == NULL){
372 PrintDebug("Ne2k: Device %p is not attached to any PCI Bus\n", nic_state);
373 irq_line = NE2K_DEFAULT_IRQ;
375 irq_line = pdev->config_header.intr_line;
379 PrintError("Ne2k: IRQ_LINE: %d\n", irq_line);
383 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->isr.val, nic_state->imr.val);
384 PrintDebug("ne2k_update_irq: irq_line: %d\n", irq_line);
387 // The top bit of the ISR/IMR is reserved and does not indicate and irq event
388 // We mask the bit out of the irq pending check
389 if ((nic_state->isr.val & nic_state->imr.val) & 0x7f) {
390 v3_raise_irq(nic_state->vm, irq_line);
391 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->isr.val, nic_state->imr.val);
399 static void ne2k_init_state(struct vm_device * dev) {
400 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
402 uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, 0x60};
404 nic_state->vm = dev->vm;
406 nic_state->isr.reset = 1;
407 nic_state->imr.val = 0x00;
408 nic_state->cmd.val = 0x22;
410 for (i = 0; i < 5; i++) {
411 nic_state->mac_addr[i] = mac[i];
414 memset(nic_state->mcast_addr, 0xff, sizeof(nic_state->mcast_addr));
416 // Not sure what this is about....
417 memset(nic_state->mem, 0xff, 32);
419 memcpy(nic_state->mem, nic_state->mac_addr, 6);
420 nic_state->mem[14] = 0x57;
421 nic_state->mem[15] = 0x57;
429 static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length) {
432 PrintDebug("\nNe2k: Sending Packet\n");
434 for (i = 0; i < length; i++) {
435 PrintDebug("%x ",pkt[i]);
440 PrintError("Implement Send Packet interface\n");
445 static int ne2k_rxbuf_full(struct vm_device *dev) {
449 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
451 index = nic_state->curpag << 8;
452 boundary = nic_state->boundary << 8;
454 if (index < boundary) {
455 empty = boundary - index;
457 empty = ((nic_state->pgstop - nic_state->pgstart) << 8) - (index - boundary);
460 if (empty < (MAX_ETH_FRAME_SIZE + 4)) {
467 #define MIN_BUF_SIZE 60
470 // This needs to be completely redone...
471 static void ne2k_receive(struct vm_device * dev, const uchar_t * pkt, int length) {
472 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
483 start = nic_state->pgstart << 8;
484 stop = nic_state->pgstop << 8;
486 if (nic_state->cmd.stop) {
490 if (ne2k_rxbuf_full(dev)) {
491 PrintError("Ne2k: received buffer overflow\n");
496 //packet too small, expand it
497 if (length < MIN_BUF_SIZE) {
498 memcpy(buf, pkt, length);
499 memset(buf + length, 0, MIN_BUF_SIZE - length);
501 length = MIN_BUF_SIZE;
504 index = nic_state->curpag << 8;
507 total_len = length + 4;
509 //address for next packet (4 bytes for CRC)
510 next = index + ((total_len + 4 + 255) & ~0xff);
513 next -= (stop - start);
516 p = nic_state->mem + index;
517 nic_state->rsr.val = 0;
518 nic_state->rsr.rx_pkt_ok = 1;
521 nic_state->rsr.phy = 1;
524 p[0] = nic_state->rsr.val;
527 p[3] = total_len >> 8;
532 empty = stop - index;
543 memcpy(nic_state->mem + index, pkt, len);
554 nic_state->curpag = next >> 8;
556 nic_state->isr.pkt_rx = 1;
557 ne2k_update_irq(dev);
563 static int netif_input(uchar_t *pkt, uint_t size) {
564 struct ne2k_context * nic_state;
565 static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
569 PrintDebug("\nNe2k: Packet Received:\nSource:");
570 for (i = 6; i < 12; i++) {
571 PrintDebug("%x ", pkt[i]);
576 for(i = 0; i < size; i++) {
577 PrintDebug("%x ", pkt[i]);
583 if (nic_state->rcr.prom_phys_enable == 1) {
585 ne2k_receive(ne2ks[i], pkt, size);
586 } else if (compare_mac(pkt, brocast_mac) && (nic_state->rcr.bcast_ok)) {
588 ne2k_receive(ne2ks[i], pkt, size);
589 } else if ((pkt[0] & 0x01) && (nic_state->rcr.mcast_ok)) {
590 //TODO: multicast packet
591 ne2k_receive(ne2ks[i], pkt, size);
592 } else if (compare_mac(pkt, nic_state->mac_addr)) {
593 ne2k_receive(ne2ks[i], pkt, size);
600 static void ne2k_mem_writeb(struct ne2k_context * nic_state, uint32_t addr, uint32_t val) {
603 tmp = (uchar_t) (val & 0x000000ff);
605 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
606 nic_state->mem[addr] = tmp;
609 PrintDebug("wmem addr: %x val: %x\n", addr, val);
612 static void ne2k_mem_writew(struct ne2k_context * nic_state,
615 addr &= ~1; //XXX: check exact behaviour if not even
617 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
618 *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
621 PrintDebug("wmem addr: %x val: %x\n", addr, val);
624 static void ne2k_mem_writel(struct ne2k_context *nic_state,
627 addr &= ~1; // XXX: check exact behaviour if not even
629 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
630 *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
633 PrintDebug("wmem addr: %x val: %x\n", addr, val);
636 static uchar_t ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr) {
637 PrintDebug("rmem addr: %x\n", addr);
639 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
640 return nic_state->mem[addr];
646 static ushort_t ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr) {
647 PrintDebug("rmem addr: %x\n", addr);
649 addr &= ~1; //XXX: check exact behaviour if not even
651 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
652 return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
658 static uint32_t ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr) {
659 PrintDebug("rmem addr: %x\n", addr);
661 addr &= ~1; //XXX: check exact behaviour if not even
663 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
664 return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
671 static void ne2k_dma_update(struct vm_device *dev, int len) {
672 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
674 nic_state->rsar += len;
677 if (nic_state->rsar == nic_state->pgstop) {
678 nic_state->rsar = nic_state->pgstart;
681 if (nic_state->rbcr <= len) {
683 nic_state->isr.rem_dma_done = 1;
684 ne2k_update_irq(dev);
686 nic_state->rbcr -= len;
691 //for data port read/write
692 static int ne2k_data_read(ushort_t port, void * dst, uint_t length, struct vm_device *dev) {
694 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
696 // current dma address
697 uint32_t addr = nic_state->rsar;
701 val = ne2k_mem_readb(nic_state, addr);
704 val = ne2k_mem_readw(nic_state, addr);
707 val = ne2k_mem_readl(nic_state, addr);
710 PrintError("ne2k_data_read error: invalid length %d\n", length);
714 ne2k_dma_update(dev, length);
716 memcpy(dst, &val, length);
718 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
723 static int ne2k_data_write(ushort_t port, void * src, uint_t length, struct vm_device *dev) {
725 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
726 uint32_t addr = nic_state->rsar;
728 if (nic_state->rbcr == 0) {
732 memcpy(&val, src, length);
736 ne2k_mem_writeb(nic_state, addr, val);
739 ne2k_mem_writew(nic_state, addr, val);
742 ne2k_mem_writel(nic_state, addr, val);
745 PrintError("nic_data_write error: invalid length %d\n", length);
748 ne2k_dma_update(dev, length);
750 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
755 static int ne2k_reset_device(struct vm_device * dev) {
756 PrintDebug("vnic: reset device\n");
758 init_ne2k_context(dev);
765 static int ne2k_reset_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
766 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x\n", port, length, val);
768 memset(dst, 0, length);
769 ne2k_reset_device(dev);
774 static int ne2k_reset_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
775 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port, length, val);
781 static int ne2k_cmd_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
782 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
785 PrintError("Invalid write length to ne2k Command register\n");
789 nic_state->cmd.val = *(uint8_t *)src;
791 if (!(nic_state->cmd.stop)) {
792 nic_state->isr.reset = 0;
795 // if ((send pkt) && (dma byte count == 0))
796 if ((nic_state.rem_dma_cmd & 0x3) && (nic_state->rbcr == 0)) {
797 nic_state->isr.rem_dma_done = 1;
798 ne2k_update_irq(dev);
801 if (nic_state->cmd.tx_pkt) {
802 int offset = (nic_state->tpsr << 8);
804 if (offset >= NE2K_PMEM_END) {
805 offset -= NE2K_PMEM_SIZE;
808 if (offset + nic_state->tbcr <= NE2K_PMEM_END) {
809 ne2k_send_packet(dev, nic_state->mem + offset, nic_state->tbcr);
813 nic_state->tsr.val = 0; // clear the tx status reg
814 nic_state->tsr.pkt_tx_ok = 1; // indicate successful tx
816 nic_state->isr.pkt_tx = 1; // irq due to pkt tx
817 nic_state->cmd.tx_pkt = 0; // reset cmd bit
818 ne2k_update_irq(dev);
821 // stop the controller
827 static int ne2k_cmd_read(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
828 *(uint8_t *)dst = nic_state->cmd.val;
830 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
834 static int ne2k_std_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
835 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
836 int index = port & 0x1f;
837 uint8_t page = nic_state->cmd.pg_sel;
840 PrintError("ne2k_write error: length %d\n", length);
844 PrintDebug("ne2k_write: port:0x%x val: 0x%x\n", port, (int)val);
850 nic_state->pgstart = val;
853 nic_state->pgstop = val;
856 nic_state->boundary = val;
859 nic_state->tpsr = val;
862 nic_state->tbcr0 = val;
865 nic_state->tbcr1 = val;
868 nic_state->isr.val &= ~(val & 0x7f);
869 ne2k_update_irq(dev);
872 nic_state->rsar0 = val;
875 nic_state->rsar1 = val;
878 nic_state->rbcr0 = val;
881 nic_state->rbcr1 = val;
884 nic_state->rcr.val = val;
887 nic_state->tcr.val = val;
890 nic_state->dcr.val = val;
893 nic_state->imr.val = val;
894 //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
895 ne2k_update_irq(dev);
898 PrintError("ne2k_write error: invalid port:0x%x\n", port);
901 } else if (page == 1) {
903 case EN1_PHYS ... EN1_PHYS + 5:
904 nic_state->mac_addr[port - EN1_PHYS] = val;
907 nic_state->curpag = val;
909 case EN1_MULT ... EN1_MULT + 7:
910 // PrintError("ne2k_write error: write EN_MULT:0x%x\n", (int)val);
911 nic_state->mcast_addr[port - EN1_MULT] = val;
914 PrintError("ne2k_write error: invalid port:0x%x\n", port);
917 } else if (page == 2) {
920 nic_state->clda0 = val;
923 nic_state->clda1 = val;
926 nic_state->rnpp = val;
929 nic_state->lnpp = val;
932 nic_state->addcnt0 = val;
935 nic_state->addcnt1 = val;
938 PrintError("ne2k_write error: invalid port:0x%x\n", port);
942 PrintError("Invalid Register Page Value\n");
951 static int ne2k_std_read(uint16_t port, void * dst, uint_t length, struct vm_device *dev) {
952 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
953 uint16_t index = port & 0x1f;
954 uint8_t page = nic_state->cmd.pg_sel;
957 PrintError("ne2k_read error: length %d\n", length);
965 *(uint8_t *)dst = nic_state->clda0;
968 *(uint8_t *)dst = nic_state->clda1;
971 *(uint8_t *)dst = nic_state->boundary;
974 *(uint8_t *)dst = nic_state->tsr.val;
977 *(uint8_t *)dst = nic_state->ncr;
980 *(uint8_t *)dst = nic_state->fifo;
983 *(uint8_t *)dst = nic_state->isr.val;
984 ne2k_update_irq(dev);
987 *(uint8_t *)dst = nic_state->crda0;
990 *(uint8_t *)dst = nic_state->crda1;
993 *(uint8_t *)dst = nic_state->rsr.val;
996 *(uint8_t *)dst = nic_state->cntr0;
999 *(uint8_t *)dst = nic_state->cntr1;
1002 *(uint8_t *)dst = nic_state->cntr2;
1005 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1009 } else if (page == 1) {
1012 case EN1_PHYS ... EN1_PHYS + 5:
1013 *(uint8_t *)dst = nic_state->mac_addr[index - EN1_PHYS];
1016 *(uint8_t *)dst = nic_state->curpag;
1018 case EN1_MULT ... EN1_MULT + 7:
1019 *(uint8_t *)dst = nic_state->mcast_addr[index - EN1_MULT];
1022 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1026 } else if (page == 2) {
1030 *(uint8_t *)dst = nic_state->pgstart;
1033 *(uint8_t *)dst = nic_state->pgstop;
1036 *(uint8_t *)dst = nic_state->rnpp;
1039 *(uint8_t *)dst = nic_state->lnpp;
1042 *(uint8_t *)dst = nic_state->tpsr;
1045 *(uint8_t *)dst = nic_state->addcnt0;
1048 *(uint8_t *)dst = nic_state->addcnt1;
1051 *(uint8_t *)dst = nic_state->rcr.val;
1054 *(uint8_t *)dst = nic_state->tcr.val;
1057 *(uint8_t *)dst = nic_state->dcr.val;
1060 *(uint8_t *)dst = nic_state->imr.val;
1063 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1067 PrintError("Invalid Register Page Value\n");
1072 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
1078 static int ne2k_start_device(struct vm_device * dev) {
1079 PrintDebug("vnic: start device\n");
1085 static int ne2k_stop_device(struct vm_device * dev) {
1086 PrintDebug("vnic: stop device\n");
1094 static int ne2k_init_device(struct vm_device * dev) {
1095 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
1097 PrintDebug("Initializing NE2K\n");
1099 init_ne2k_context(dev);
1101 if (nic_state->pci_bus == NULL) {
1102 PrintDebug("NE2k: Not attached to pci\n");
1104 v3_dev_hook_io(dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
1106 for (i = 1; i < 16; i++){
1107 v3_dev_hook_io(dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
1110 v3_dev_hook_io(dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
1111 v3_dev_hook_io(dev, NIC_RESET_PORT, &ne2k_reset_read, &ne2k_reset_write);
1115 struct v3_pci_bar bars[6];
1116 struct pci_device * pci_dev = NULL;
1119 PrintDebug("NE2k: PCI Enabled\n");
1121 for (i = 0; i < 6; i++) {
1122 bars[i].type = PCI_BAR_NONE;
1125 bars[0].type = PCI_BAR_IO;
1126 bars[0].default_base_port = NIC_REG_BASE_PORT;
1127 bars[0].num_ports = 256;
1129 bars[0].io_read = ne2k_pci_read;
1130 bars[0].io_write = ne2k_pci_write;
1132 pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
1134 pci_config_update, NULL, NULL, dev);
1136 if (pci_dev == NULL) {
1137 PrintError("Failed to register NE2K with PCI\n");
1141 pci_dev->config_header.vendor_id = 0x10ec;
1142 pci_dev->config_header.device_id = 0x8029;
1143 pci_dev->config_header.revision = 0x00;
1145 pci_dev->config_header.subclass = 0x00;
1146 pci_dev->config_header.class = 0x02;
1147 pci_dev->config_header.header_type = 0x00;
1149 pci_dev->config_header.intr_line = 11;
1150 pci_dev->config_header.intr_pin = 1;
1152 nic_state->pci_dev = pci_dev;
1165 static int ne2k_deinit_device(struct vm_device *dev) {
1168 for (i = 0; i < 16; i++){
1169 v3_dev_unhook_io(dev, NIC_REG_BASE_PORT + i);
1172 v3_dev_unhook_io(dev, NIC_DATA_PORT);
1173 v3_dev_unhook_io(dev, NIC_RESET_PORT);
1179 static struct vm_device_ops dev_ops = {
1180 .init = ne2k_init_device,
1181 .deinit = ne2k_deinit_device,
1182 .reset = ne2k_reset_device,
1183 .start = ne2k_start_device,
1184 .stop = ne2k_stop_device,
1188 struct vm_device * v3_create_ne2k(struct vm_device * pci) {
1189 struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
1191 memset(nic_state, 0, sizeof(struct ne2k_context));
1193 nic_state->pci_bus = pci;
1195 struct vm_device * device = v3_create_device("NE2K", &dev_ops, nic_state);