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
44 #define NE2K_PMEM_SIZE (32 * 1024)
45 #define NE2K_PMEM_START (16 * 1024)
46 #define NE2K_PMEM_END (NE2K_PMEM_SIZE + NE2K_PMEM_START)
47 #define NE2K_MEM_SIZE NE2K_PMEM_END
49 #define NIC_REG_BASE_PORT 0xc100 //Command register (for all pages)
50 #define NIC_DATA_PORT 0xc110 //Data read/write port
51 #define NIC_RESET_PORT 0xc11f //Data read/write port
54 #define EN0_CLDALO 0x01 //Low byte of current local dma addr RD
55 #define EN0_STARTPG 0x01 //Starting page of ring bfr WR
56 #define EN0_CLDAHI 0x02 //High byte of current local dma addr RD
57 #define EN0_STOPPG 0x02 //Ending page +1 of ring bfr WR
58 #define EN0_BOUNDARY 0x03 //Boundary page of ring bfr RD WR
59 #define EN0_TSR 0x04 //Transmit status reg RD
60 #define EN0_TPSR 0x04 //Transmit starting page WR
61 #define EN0_NCR 0x05 //Number of collision reg RD
62 #define EN0_TCNTLO 0x05 //Low byte of tx byte count WR
63 #define EN0_FIFO 0x06 //FIFO RD
64 #define EN0_TCNTHI 0x06 //High byte of tx byte count WR
65 #define EN0_ISR 0x07 //Interrupt status reg RD WR
66 #define EN0_CRDALO 0x08 //low byte of current remote dma address RD
67 #define EN0_RSARLO 0x08 //Remote start address reg 0
68 #define EN0_CRDAHI 0x09 //high byte, current remote dma address RD
69 #define EN0_RSARHI 0x09 //Remote start address reg 1
70 #define EN0_RCNTLO 0x0a //Remote byte count reg WR
71 #define EN0_RTL8029ID0 0x0a //Realtek ID byte #1 RD
72 #define EN0_RCNTHI 0x0b //Remote byte count reg WR
73 #define EN0_RTL8029ID1 0x0b //Realtek ID byte #2 RD
74 #define EN0_RSR 0x0c //rx status reg RD
75 #define EN0_RXCR 0x0c //RX configuration reg WR
76 #define EN0_TXCR 0x0d //TX configuration reg WR
77 #define EN0_COUNTER0 0x0d //Rcv alignment error counter RD
78 #define EN0_DCFG 0x0e //Data configuration reg WR
79 #define EN0_COUNTER1 0x0e //Rcv CRC error counter RD
80 #define EN0_IMR 0x0f //Interrupt mask reg WR
81 #define EN0_COUNTER2 0x0f //Rcv missed frame error counter RD
85 #define EN1_CURPAG 0x07
89 #define EN2_STARTPG 0x01 //Starting page of ring bfr RD
90 #define EN2_STOPPG 0x02 //Ending page +1 of ring bfr RD
91 #define EN2_LDMA0 0x01 //Current Local DMA Address 0 WR
92 #define EN2_LDMA1 0x02 //Current Local DMA Address 1 WR
93 #define EN2_RNPR 0x03 //Remote Next Packet Pointer RD WR
94 #define EN2_TPSR 0x04 //Transmit Page Start Address RD
95 #define EN2_LNRP 0x05 //Local Next Packet Pointer RD WR
96 #define EN2_ACNT0 0x06 //Address Counter Upper WR
97 #define EN2_ACNT1 0x07 //Address Counter Lower WR
98 #define EN2_RCR 0x0c //Receive Configuration Register RD
99 #define EN2_TCR 0x0d //Transmit Configuration Register RD
100 #define EN2_DCR 0x0e //Data Configuration Register RD
101 #define EN2_IMR 0x0f //Interrupt Mask Register RD
104 #define EN3_CONFIG0 0x03
105 #define EN3_CONFIG1 0x04
106 #define EN3_CONFIG2 0x05
107 #define EN3_CONFIG3 0x06
111 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
120 uint8_t rem_dma_cmd : 3;
122 } __attribute__((packed));
123 } __attribute__((packed));
124 } __attribute__((packed));
127 struct intr_status_reg {
135 uint8_t overwrite_warn : 1;
136 uint8_t cnt_overflow : 1;
137 uint8_t rem_dma_done : 1;
138 uint8_t reset_status : 1;
139 } __attribute__((packed));
140 } __attribute__((packed));
141 } __attribute__((packed));
144 struct intr_mask_reg {
152 uint8_t overwrite_warn : 1;
153 uint8_t cnt_overflow : 1;
154 uint8_t rem_dma_done : 1;
156 } __attribute__((packed));
157 } __attribute__((packed));
158 } __attribute__((packed));
161 struct data_cfg_reg {
165 uint8_t word_trans_sel : 1;
166 uint8_t byte_order_sel : 1;
167 uint8_t long_addr_sel : 1;
168 uint8_t loopback_sel : 1;
169 uint8_t auto_init_rem : 1;
170 uint8_t fifo_thresh_sel : 2;
172 } __attribute__((packed));
173 } __attribute__((packed));
174 } __attribute__((packed));
181 uint8_t inhibit_crc : 1;
182 uint8_t enc_loop_ctrl : 2;
183 uint8_t auto_tx_disable : 1;
184 uint8_t coll_offset_en : 1;
186 } __attribute__((packed));
187 } __attribute__((packed));
188 } __attribute__((packed));
190 struct tx_status_reg {
194 uint8_t pkt_tx_ok : 1;
196 uint8_t tx_collision : 1;
197 uint8_t tx_aborted : 1;
198 uint8_t carrier_lost : 1;
199 uint8_t fifo_underrun : 1;
200 uint8_t cd_heartbeat : 1;
201 uint8_t oow_collision : 1;
202 } __attribute__((packed));
203 } __attribute__((packed));
204 } __attribute__((packed));
210 uint8_t save_pkt_errs : 1;
211 uint8_t runt_pkt_ok : 1;
212 uint8_t bcast_ok : 1;
213 uint8_t mcast_ok : 1;
214 uint8_t prom_phys_enable : 1;
215 uint8_t mon_mode : 1;
217 } __attribute__((packed));
218 } __attribute__((packed));
219 } __attribute__((packed));
222 struct rx_status_reg {
226 uint8_t pkt_rx_ok : 1;
228 uint8_t frame_align_err : 1;
229 uint8_t fifo_overrun : 1;
230 uint8_t missed_pkt : 1;
231 uint8_t mac_addr_match : 1;
232 uint8_t rx_disabled : 1;
233 uint8_t deferring : 1;
234 } __attribute__((packed));
235 } __attribute__((packed));
236 } __attribute__((packed));
239 struct ne2k_context {
240 struct guest_info * vm;
242 nic_state_t dev_state;
246 struct intr_status_reg isr;
247 struct intr_mask_reg imr;
248 struct data_cfg_reg dcr;
249 struct tx_cfg_reg tcr;
250 struct tx_status_reg tsr;
251 struct rx_cfg_reg rcr;
252 struct rx_status_reg rsr;
270 } __attribute__((packed));
271 } __attribute__((packed));
278 } __attribute__((packed));
279 } __attribute__((packed));
292 } __attribute__((packed));
293 } __attribute__((packed));
295 uint8_t mcast_addr[8]; //multicast mask array
299 uchar_t mem[NE2K_MEM_SIZE];
301 struct pci_device * pci_dev;
302 struct vm_device * pci_bus;
305 #define compare_mac(src, dst) ({ \
306 ((src[0] == dst[0]) && \
307 (src[1] == dst[1]) && \
308 (src[2] == dst[2]) && \
309 (src[3] == dst[3]) && \
310 (src[4] == dst[4]) && \
311 (src[5] == dst[5]))? 1 : 0; \
316 static void dump_state(struct vm_device * dev) {
317 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
321 PrintDebug("====NE2000: Dumping state Begin ==========\n");
322 PrintDebug("Registers:\n");
324 // JRL: Dump Registers
326 PrintDebug("Memory:\n");
328 for(i = 0; i < 32; i++) {
329 PrintDebug("0x%02x ", nic_state->mem[i]);
333 PrintDebug("====NE2000: Dumping state End==========\n");
339 static int ne2k_update_irq(struct vm_device *dev) {
341 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
342 struct pci_device * pdev = nic_state->pci_dev;
346 PrintDebug("Ne2k: Device %p is not attached to any PCI Bus\n", nic_state);
347 irqline = NE2K_DEFAULT_IRQ;
349 irqline = pdev->config_header.intr_line;
352 // What the hell is this?
353 isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0x7f);
356 PrintError("Ne2k: IRQ_LINE: %d\n", irqline);
360 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->regs.isr, nic_state->regs.imr);
361 PrintDebug("ne2k_update_irq: irq_line: %d\n", irqline);
363 if ((isr & 0x7f) != 0x0) {
364 v3_raise_irq(nic_state->vm, irqline);
365 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->regs.isr, nic_state->regs.imr);
373 static void ne2k_init_state(struct vm_device * dev) {
374 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
376 uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, 0x60};
378 nic_state->vm = dev->vm;
380 nic_state->regs.isr = ENISR_RESET;
381 nic_state->regs.imr = 0x00;
382 nic_state->regs.cmd = 0x22;
384 for (i = 0; i < 5; i++) {
385 nic_state->mac_addr[i] = mac[i];
388 nic_state->mac_addr[5] = mac[5] + nic_no;
390 for (i = 0; i < 8; i++) {
391 nic_state->regs.mcast_addr[i] = 0xff;
394 for(i = 0; i < 32; i++) {
395 nic_state->mem[i] = 0xff;
398 memcpy(nic_state->mem, nic_state->mac_addr, 6);
399 nic_state->mem[14] = 0x57;
400 nic_state->mem[15] = 0x57;
408 static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length) {
411 PrintDebug("\nNe2k: Sending Packet\n");
413 for (i = 0; i < length; i++) {
414 PrintDebug("%x ",pkt[i]);
419 return V3_Send_pkt(pkt, length);
422 static int ne2k_rxbuf_full(struct vm_device *dev) {
423 int empty, index, boundary;
424 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
426 index = nic_state->regs.curpag << 8;
427 boundary = nic_state->regs.boundary << 8;
429 if (index < boundary) {
430 empty = boundary - index;
432 empty = ((nic_state->regs.pgstop - nic_state->regs.pgstart) << 8) - (index - boundary);
435 if (empty < (MAX_ETH_FRAME_SIZE + 4)) {
442 #define MIN_BUF_SIZE 60
444 static void ne2k_receive(struct vm_device *dev, const uchar_t * pkt, int length) {
445 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
446 struct ne2k_regs *nregs = &(nic_state->regs);
448 uint32_t total_len, next, len, index, empty;
450 uint32_t start, stop;
452 start = nregs->pgstart << 8;
453 stop = nregs->pgstop << 8;
455 if (nregs->cmd & NE2K_STOP) {
459 if (ne2k_rxbuf_full(dev)) {
460 PrintError("Ne2k: received buffer overflow\n");
464 //packet too small, expand it
465 if (length < MIN_BUF_SIZE) {
466 memcpy(buf, pkt, length);
467 memset(buf + length, 0, MIN_BUF_SIZE - length);
469 length = MIN_BUF_SIZE;
472 index = nregs->curpag << 8;
475 total_len = length + 4;
477 //address for next packet (4 bytes for CRC)
478 next = index + ((total_len + 4 + 255) & ~0xff);
481 next -= stop - start;
484 p = nic_state->mem + index;
485 nregs->rsr = ENRSR_RXOK;
488 nregs->rsr |= ENRSR_PHY;
494 p[3] = total_len >> 8;
499 empty = stop - index;
510 memcpy(nic_state->mem + index, pkt, len);
521 nregs->curpag = next >> 8;
523 nregs->isr |= ENISR_RX;
524 ne2k_update_irq(dev);
530 static int netif_input(uchar_t *pkt, uint_t size) {
531 struct ne2k_context *nic_state;
532 struct ne2k_regs *nregs;
533 static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
537 PrintDebug("\nNe2k: Packet Received:\nSource:");
538 for (i = 6; i < 12; i++) {
539 PrintDebug("%x ", pkt[i]);
544 for(i= 0; i<size; i++) {
545 PrintDebug("%x ", pkt[i]);
549 for (i = 0; i < NUM_NE2K; i++){
550 if (ne2ks[i] != NULL) {
551 nic_state = (struct ne2k_context *)ne2ks[i]->private_data;
552 nregs = &(nic_state->regs);
554 if (nregs->rcr & 0x10) {
556 ne2k_receive(ne2ks[i], pkt, size);
558 if (compare_mac(pkt, brocast_mac) && (nregs->rcr & 0x04)) {
560 ne2k_receive(ne2ks[i], pkt, size);
561 } else if (pkt[0] & 0x01) {
562 //TODO: multicast packet
563 if (nregs->rcr & 0x08)
564 ne2k_receive(ne2ks[i], pkt, size);
565 } else if (compare_mac(pkt, nic_state->mac_addr)) {
566 ne2k_receive(ne2ks[i], pkt, size);
578 static void ne2k_mem_writeb(struct ne2k_context * nic_state, uint32_t addr, uint32_t val) {
581 tmp = (uchar_t) (val & 0x000000ff);
583 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
584 nic_state->mem[addr] = tmp;
587 PrintDebug("wmem addr: %x val: %x\n", addr, val);
590 static void ne2k_mem_writew(struct ne2k_context * nic_state,
593 addr &= ~1; //XXX: check exact behaviour if not even
595 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
596 *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
599 PrintDebug("wmem addr: %x val: %x\n", addr, val);
602 static void ne2k_mem_writel(struct ne2k_context *nic_state,
605 addr &= ~1; // XXX: check exact behaviour if not even
607 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
608 *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
611 PrintDebug("wmem addr: %x val: %x\n", addr, val);
614 static uchar_t ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr) {
615 PrintDebug("rmem addr: %x\n", addr);
617 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
618 return nic_state->mem[addr];
624 static ushort_t ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr) {
625 PrintDebug("rmem addr: %x\n", addr);
627 addr &= ~1; //XXX: check exact behaviour if not even
629 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
630 return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
636 static uint32_t ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr) {
637 PrintDebug("rmem addr: %x\n", addr);
639 addr &= ~1; //XXX: check exact behaviour if not even
641 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
642 return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
649 static void ne2k_dma_update(struct vm_device *dev, int len) {
650 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
652 nic_state->regs.rsar += len;
655 if (nic_state->regs.rsar == nic_state->regs.pgstop) {
656 nic_state->regs.rsar = nic_state->regs.pgstart;
659 if (nic_state->regs.rbcr <= len) {
660 nic_state->regs.rbcr = 0;
661 nic_state->regs.isr |= ENISR_RDC;
662 ne2k_update_irq(dev);
664 nic_state->regs.rbcr -= len;
669 //for data port read/write
670 static int ne2k_data_read(ushort_t port, void * dst, uint_t length, struct vm_device *dev) {
672 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
674 // current dma address
675 uint32_t addr = nic_state->regs.rsar;
679 val = ne2k_mem_readb(nic_state, addr);
682 val = ne2k_mem_readw(nic_state, addr);
685 val = ne2k_mem_readl(nic_state, addr);
688 PrintError("ne2k_data_read error: invalid length %d\n", length);
692 ne2k_dma_update(dev, length);
694 memcpy(dst, &val, length);
696 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
701 static int ne2k_data_write(ushort_t port, void * src, uint_t length, struct vm_device *dev) {
703 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
704 uint32_t addr = nic_state->regs.rsar;
706 if (nic_state->regs.rbcr == 0) {
710 memcpy(&val, src, length);
714 ne2k_mem_writeb(nic_state, addr, val);
717 ne2k_mem_writew(nic_state, addr, val);
720 ne2k_mem_writel(nic_state, addr, val);
723 PrintError("nic_data_write error: invalid length %d\n", length);
726 ne2k_dma_update(dev, length);
728 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
733 static int ne2k_reset_device(struct vm_device * dev) {
734 PrintDebug("vnic: reset device\n");
736 init_ne2k_context(dev);
743 static int ne2k_reset_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
744 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x\n", port, length, val);
746 memset(dst, 0, length);
747 ne2k_reset_device(dev);
752 static int ne2k_reset_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
753 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port, length, val);
759 static int ne2k_cmd_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
760 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
763 PrintError("Invalid write length to ne2k Command register\n");
767 nic_state->cmd.val = *(uint8_t *)src;
769 if (!(nic_state->cmd.stop)) {
770 nic_state->isr.reset = 0;
772 if ((val & (NE2K_DMAREAD | NE2K_DMAWRITE)) && (nic_state->rbcr == 0)) {
773 nic_state->isr.rem_dma_done = 1;
774 ne2k_update_irq(dev);
777 if (nic_state->cmd.tx_pkt) {
778 int offset = (nic_state->tpsr << 8);
780 if (offset >= NE2K_PMEM_END) {
781 offset -= NE2K_PMEM_SIZE;
784 if (offset + nic_state->tbcr <= NE2K_PMEM_END) {
785 ne2k_send_packet(dev, nic_state->mem + offset, nic_state->tbcr);
789 nic_state->tsr.val = 0; // clear the tx status reg
790 nic_state->tsr.pkt_tx_ok = 1; // indicate successful tx
792 nic_state->isr.pkt_tx = 1; // irq due to pkt tx
793 nic_state->cmd.tx_pkt = 0; // reset cmd bit
794 ne2k_update_irq(dev);
797 // stop the controller
803 static int ne2k_cmd_read(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
804 *(uint8_t *)dst = nic_state->cmd.val;
806 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
810 static int ne2k_std_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
811 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
812 int index = port & 0x1f;
813 uint8_t page = nic_state->cmd.pg_sel;
816 PrintError("ne2k_write error: length %d\n", length);
820 PrintDebug("ne2k_write: port:0x%x val: 0x%x\n", port, (int)val);
826 nic_state->regs.pgstart = val;
829 nic_state->regs.pgstop = val;
832 nic_state->regs.boundary = val;
835 nic_state->regs.tpsr = val;
838 nic_state->regs.tbcr = (nic_state->regs.tbcr & 0xff00) | val;
841 nic_state->regs.tbcr = (nic_state->regs.tbcr & 0x00ff) | (val << 8);
844 nic_state->regs.isr &= ~(val & 0x7f);
845 ne2k_update_irq(dev);
848 nic_state->regs.rsar = (nic_state->regs.rsar & 0xff00) | val;
851 nic_state->regs.rsar = (nic_state->regs.rsar & 0x00ff) | (val << 8);
854 nic_state->regs.rbcr = (nic_state->regs.rbcr & 0xff00) | val;
857 nic_state->regs.rbcr = (nic_state->regs.rbcr & 0x00ff) | (val << 8);
860 nic_state->regs.rcr = val;
863 nic_state->regs.tcr = val;
865 nic_state->regs.dcr = val;
868 nic_state->regs.imr = val;
869 //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
870 ne2k_update_irq(dev);
873 PrintError("ne2k_write error: invalid port:0x%x\n", port);
876 } else if (page == 1) {
878 case EN1_PHYS ... EN1_PHYS + 5:
879 nic_state->regs.mac_addr[port - EN1_PHYS] = val;
882 nic_state->regs.curpag = val;
884 case EN1_MULT ... EN1_MULT + 7:
885 // PrintError("ne2k_write error: write EN_MULT:0x%x\n", (int)val);
886 nic_state->regs.mcast_addr[port - EN1_MULT] = val;
889 PrintError("ne2k_write error: invalid port:0x%x\n", port);
892 } else if (page == 2) {
895 nic_state->regs.clda = (nic_state->regs.clda & 0xff00) | val;
898 nic_state->regs.clda = (nic_state->regs.clda & 0x00ff) | (val << 8);
901 nic_state->regs.rnpp = val;
904 nic_state->regs.lnpp = val;
907 nic_state->regs.addcnt = (nic_state->regs.addcnt & 0xff00) | val;
910 nic_state->regs.addcnt = (nic_state->regs.addcnt & 0x00ff) | (val << 8);
913 PrintError("ne2k_write error: invalid port:0x%x\n", port);
917 PrintError("Invalid Register Page Value\n");
926 static int ne2k_std_read(uint16_t port, void * dst, uint_t length, struct vm_device *dev) {
927 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
928 uint16_t index = port & 0x1f;
929 uint8_t page = nic_state->cmd.pg_sel;
932 PrintError("ne2k_read error: length %d\n", length);
943 *(uint8_t *)dst = nic_state->clda & 0x00ff;
946 *(uint8_t *)dst = (nic_state->clda & 0xff00) >> 8;
949 *(uint8_t *)dst = nic_state->boundary;
952 *(uint8_t *)dst = nic_state->tsr;
955 *(uint8_t *)dst = nic_state->ncr;
958 *(uint8_t *)dst = nic_state->fifo;
961 *(uint8_t *)dst = nic_state->isr;
962 ne2k_update_irq(dev);
965 *(uint8_t *)dst = nic_state->crda & 0x00ff;
968 *(uint8_t *)dst = (nic_state->crda & 0xff00) >> 8;
971 *(uint8_t *)dst = nic_state->rsr;
974 *(uint8_t *)dst = nic_state->cntr & 0x000000ff;
977 *(uint8_t *)dst = (nic_state->cntr & 0x0000ff00) >> 8;
980 *(uint8_t *)dst = (nic_state->cntr & 0x00ff0000) >> 16;
983 PrintError("ne2k_read error: invalid port:0x%x\n", port);
987 } else if (page == 1) {
990 case EN1_PHYS ... EN1_PHYS + 5:
991 *(uint8_t *)dst = nic_state->mac_addr[index - EN1_PHYS];
994 *(uint8_t *)dst = nic_state->curpag;
996 case EN1_MULT ... EN1_MULT + 7:
997 *(uint8_t *)dst = nic_state->mcast_addr[index - EN1_MULT];
1000 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1004 } else if (page == 2) {
1008 *(uint8_t *)dst = nic_state->pgstart;
1011 *(uint8_t *)dst = nic_state->pgstop;
1014 *(uint8_t *)dst = nic_state->rnpp;
1017 *(uint8_t *)dst = nic_state->lnpp;
1020 *(uint8_t *)dst = nic_state->tpsr;
1023 *(uint8_t *)dst = nic_state->addcnt & 0x00ff;
1026 *(uint8_t *)dst = (nic_state->addcnt & 0xff00) >> 8;
1029 *(uint8_t *)dst = nic_state->rcr;
1032 *(uint8_t *)dst = nic_state->tcr;
1035 *(uint8_t *)dst = nic_state->dcr;
1038 *(uint8_t *)dst = nic_state->imr;
1041 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1045 PrintError("Invalid Register Page Value\n");
1050 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
1056 static int ne2k_start_device(struct vm_device * dev) {
1057 PrintDebug("vnic: start device\n");
1063 static int ne2k_stop_device(struct vm_device * dev) {
1064 PrintDebug("vnic: stop device\n");
1072 static int ne2k_init_device(struct vm_device * dev) {
1073 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
1075 PrintDebug("Initializing NE2K\n");
1077 init_ne2k_context(dev);
1079 if (nic_state->pci_bus == NULL) {
1080 PrintDebug("NE2k: Not attached to pci\n");
1082 v3_dev_hook_io(dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
1084 for (i = 1; i < 16; i++){
1085 v3_dev_hook_io(dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
1088 v3_dev_hook_io(dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
1089 v3_dev_hook_io(dev, NIC_RESET_PORT, &ne2k_reset_read, &ne2k_reset_write);
1093 struct v3_pci_bar bars[6];
1094 struct pci_device * pci_dev = NULL;
1097 PrintDebug("NE2k: PCI Enabled\n");
1099 for (i = 0; i < 6; i++) {
1100 bars[i].type = PCI_BAR_NONE;
1103 bars[0].type = PCI_BAR_IO;
1104 bars[0].default_base_port = NIC_REG_BASE_PORT;
1105 bars[0].num_ports = 256;
1107 bars[0].io_read = ne2k_pci_read;
1108 bars[0].io_write = ne2k_pci_write;
1110 pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
1112 pci_config_update, NULL, NULL, dev);
1114 if (pci_dev == NULL) {
1115 PrintError("Failed to register NE2K with PCI\n");
1119 pci_dev->config_header.vendor_id = 0x10ec;
1120 pci_dev->config_header.device_id = 0x8029;
1121 pci_dev->config_header.revision = 0x00;
1123 pci_dev->config_header.subclass = 0x00;
1124 pci_dev->config_header.class = 0x02;
1125 pci_dev->config_header.header_type = 0x00;
1127 pci_dev->config_header.intr_line = 11;
1128 pci_dev->config_header.intr_pin = 1;
1130 nic_state->pci_dev = pci_dev;
1143 static int ne2k_deinit_device(struct vm_device *dev) {
1146 for (i = 0; i < 16; i++){
1147 v3_dev_unhook_io(dev, NIC_REG_BASE_PORT + i);
1150 v3_dev_unhook_io(dev, NIC_DATA_PORT);
1151 v3_dev_unhook_io(dev, NIC_RESET_PORT);
1157 static struct vm_device_ops dev_ops = {
1158 .init = ne2k_init_device,
1159 .deinit = ne2k_deinit_device,
1160 .reset = ne2k_reset_device,
1161 .start = ne2k_start_device,
1162 .stop = ne2k_stop_device,
1166 struct vm_device * v3_create_ne2k(struct vm_device * pci) {
1167 struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
1169 memset(nic_state, 0, sizeof(struct ne2k_context));
1171 nic_state->pci_bus = pci;
1173 struct vm_device * device = v3_create_device("NE2K", &dev_ops, nic_state);