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>
32 #ifndef CONFIG_DEBUG_NE2K
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));
325 uint8_t mcast_addr[8]; // multicast mask array
326 uint8_t mac_addr[6]; // MAC Addr
328 uint8_t mem[NE2K_MEM_SIZE];
330 struct pci_device * pci_dev;
331 struct vm_device * pci_bus;
334 #define compare_mac(src, dst) !memcmp(src, dst, 6)
336 #ifdef CONFIG_DEBUG_NE2K
337 static void dump_state(struct vm_device * dev) {
338 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
342 PrintDebug("====NE2000: Dumping state Begin ==========\n");
343 PrintDebug("Registers:\n");
345 // JRL: Dump Registers
347 PrintDebug("Memory:\n");
349 for(i = 0; i < 32; i++) {
350 PrintDebug("0x%02x ", nic_state->mem[i]);
354 PrintDebug("====NE2000: Dumping state End==========\n");
360 static int ne2k_update_irq(struct vm_device *dev) {
361 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
362 struct pci_device * pci_dev = nic_state->pci_dev;
365 if (pci_dev == NULL){
366 PrintDebug("Ne2k: Device %p is not attached to any PCI Bus\n", nic_state);
367 irq_line = NE2K_DEFAULT_IRQ;
369 irq_line = pdev->config_header.intr_line;
373 PrintError("Ne2k: IRQ_LINE: %d\n", irq_line);
377 PrintDebug("ne2k_update_irq: irq_line: %d\n", irq_line);
380 // The top bit of the ISR/IMR is reserved and does not indicate and irq event
381 // We mask the bit out of the irq pending check
382 if ((nic_state->isr.val & nic_state->imr.val) & 0x7f) {
383 v3_raise_irq(nic_state->vm, irq_line);
384 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->isr.val, nic_state->imr.val);
392 static void ne2k_init_state(struct vm_device * dev) {
393 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
395 uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, 0x60};
397 nic_state->vm = dev->vm;
399 nic_state->isr.reset = 1;
400 nic_state->imr.val = 0x00;
401 nic_state->cmd.val = 0x22;
403 for (i = 0; i < 5; i++) {
404 nic_state->mac_addr[i] = mac[i];
407 memset(nic_state->mcast_addr, 0xff, sizeof(nic_state->mcast_addr));
409 // Not sure what this is about....
410 memset(nic_state->mem, 0xff, 32);
412 memcpy(nic_state->mem, nic_state->mac_addr, 6);
413 nic_state->mem[14] = 0x57;
414 nic_state->mem[15] = 0x57;
416 #ifdef CONFIG_DEBUG_NE2K
422 static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length) {
425 PrintDebug("\nNe2k: Sending Packet\n");
427 for (i = 0; i < length; i++) {
428 PrintDebug("%x ",pkt[i]);
433 PrintError("Implement Send Packet interface\n");
438 static int ne2k_rxbuf_full(struct vm_device *dev) {
442 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
444 index = nic_state->curpag << 8;
445 boundary = nic_state->boundary << 8;
447 if (index < boundary) {
448 empty = boundary - index;
450 empty = ((nic_state->pgstop - nic_state->pgstart) << 8) - (index - boundary);
453 if (empty < (MAX_ETH_FRAME_SIZE + 4)) {
460 #define MIN_BUF_SIZE 60
463 // This needs to be completely redone...
464 static void ne2k_receive(struct vm_device * dev, const uchar_t * pkt, int length) {
465 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
476 start = nic_state->pgstart << 8;
477 stop = nic_state->pgstop << 8;
479 if (nic_state->cmd.stop) {
483 if (ne2k_rxbuf_full(dev)) {
484 PrintError("Ne2k: received buffer overflow\n");
489 //packet too small, expand it
490 if (length < MIN_BUF_SIZE) {
491 memcpy(buf, pkt, length);
492 memset(buf + length, 0, MIN_BUF_SIZE - length);
494 length = MIN_BUF_SIZE;
497 index = nic_state->curpag << 8;
500 total_len = length + 4;
502 //address for next packet (4 bytes for CRC)
503 next = index + ((total_len + 4 + 255) & ~0xff);
506 next -= (stop - start);
509 p = nic_state->mem + index;
510 nic_state->rsr.val = 0;
511 nic_state->rsr.rx_pkt_ok = 1;
514 nic_state->rsr.phy = 1;
517 p[0] = nic_state->rsr.val;
520 p[3] = total_len >> 8;
525 empty = stop - index;
536 memcpy(nic_state->mem + index, pkt, len);
547 nic_state->curpag = next >> 8;
549 nic_state->isr.pkt_rx = 1;
550 ne2k_update_irq(dev);
556 static int netif_input(uchar_t *pkt, uint_t size) {
557 struct ne2k_context * nic_state;
558 static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
561 #ifdef CONFIG_DEBUG_NE2K
562 PrintDebug("\nNe2k: Packet Received:\nSource:");
563 for (i = 6; i < 12; i++) {
564 PrintDebug("%x ", pkt[i]);
569 for(i = 0; i < size; i++) {
570 PrintDebug("%x ", pkt[i]);
576 if (nic_state->rcr.prom_phys_enable == 1) {
578 ne2k_receive(ne2ks[i], pkt, size);
579 } else if (compare_mac(pkt, brocast_mac) && (nic_state->rcr.bcast_ok)) {
581 ne2k_receive(ne2ks[i], pkt, size);
582 } else if ((pkt[0] & 0x01) && (nic_state->rcr.mcast_ok)) {
583 //TODO: multicast packet
584 ne2k_receive(ne2ks[i], pkt, size);
585 } else if (compare_mac(pkt, nic_state->mac_addr)) {
586 ne2k_receive(ne2ks[i], pkt, size);
593 static void ne2k_mem_writeb(struct ne2k_context * nic_state, uint32_t addr, uint32_t val) {
596 tmp = (uchar_t) (val & 0x000000ff);
598 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
599 nic_state->mem[addr] = tmp;
602 PrintDebug("wmem addr: %x val: %x\n", addr, val);
605 static void ne2k_mem_writew(struct ne2k_context * nic_state,
608 addr &= ~1; //XXX: check exact behaviour if not even
610 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
611 *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
614 PrintDebug("wmem addr: %x val: %x\n", addr, val);
617 static void ne2k_mem_writel(struct ne2k_context *nic_state,
620 addr &= ~1; // XXX: check exact behaviour if not even
622 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
623 *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
626 PrintDebug("wmem addr: %x val: %x\n", addr, val);
629 static uchar_t ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr) {
630 PrintDebug("rmem addr: %x\n", addr);
632 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
633 return nic_state->mem[addr];
639 static ushort_t ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr) {
640 PrintDebug("rmem addr: %x\n", addr);
642 addr &= ~1; //XXX: check exact behaviour if not even
644 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
645 return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
651 static uint32_t ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr) {
652 PrintDebug("rmem addr: %x\n", addr);
654 addr &= ~1; //XXX: check exact behaviour if not even
656 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
657 return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
664 static void ne2k_dma_update(struct vm_device *dev, int len) {
665 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
667 nic_state->rsar += len;
670 if (nic_state->rsar == nic_state->pgstop) {
671 nic_state->rsar = nic_state->pgstart;
674 if (nic_state->rbcr <= len) {
676 nic_state->isr.rem_dma_done = 1;
677 ne2k_update_irq(dev);
679 nic_state->rbcr -= len;
684 //for data port read/write
685 static int ne2k_data_read(ushort_t port, void * dst, uint_t length, struct vm_device *dev) {
687 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
689 // current dma address
690 uint32_t addr = nic_state->rsar;
694 val = ne2k_mem_readb(nic_state, addr);
697 val = ne2k_mem_readw(nic_state, addr);
700 val = ne2k_mem_readl(nic_state, addr);
703 PrintError("ne2k_data_read error: invalid length %d\n", length);
707 ne2k_dma_update(dev, length);
709 memcpy(dst, &val, length);
711 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
716 static int ne2k_data_write(ushort_t port, void * src, uint_t length, struct vm_device *dev) {
718 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
719 uint32_t addr = nic_state->rsar;
721 if (nic_state->rbcr == 0) {
725 memcpy(&val, src, length);
729 ne2k_mem_writeb(nic_state, addr, val);
732 ne2k_mem_writew(nic_state, addr, val);
735 ne2k_mem_writel(nic_state, addr, val);
738 PrintError("nic_data_write error: invalid length %d\n", length);
741 ne2k_dma_update(dev, length);
743 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
748 static int ne2k_reset_device(struct vm_device * dev) {
749 PrintDebug("vnic: reset device\n");
751 init_ne2k_context(dev);
758 static int ne2k_reset_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
759 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x\n", port, length, val);
761 memset(dst, 0, length);
762 ne2k_reset_device(dev);
767 static int ne2k_reset_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
768 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port, length, val);
774 static int ne2k_cmd_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
775 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
778 PrintError("Invalid write length to ne2k Command register\n");
782 nic_state->cmd.val = *(uint8_t *)src;
784 if (!(nic_state->cmd.stop)) {
785 nic_state->isr.reset = 0;
788 // if ((send pkt) && (dma byte count == 0))
789 if ((nic_state.rem_dma_cmd & 0x3) && (nic_state->rbcr == 0)) {
790 nic_state->isr.rem_dma_done = 1;
791 ne2k_update_irq(dev);
794 if (nic_state->cmd.tx_pkt) {
795 int offset = (nic_state->tpsr << 8);
797 if (offset >= NE2K_PMEM_END) {
798 offset -= NE2K_PMEM_SIZE;
801 if (offset + nic_state->tbcr <= NE2K_PMEM_END) {
802 ne2k_send_packet(dev, nic_state->mem + offset, nic_state->tbcr);
806 nic_state->tsr.val = 0; // clear the tx status reg
807 nic_state->tsr.pkt_tx_ok = 1; // indicate successful tx
809 nic_state->isr.pkt_tx = 1; // irq due to pkt tx
810 nic_state->cmd.tx_pkt = 0; // reset cmd bit
811 ne2k_update_irq(dev);
814 // stop the controller
820 static int ne2k_cmd_read(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
821 *(uint8_t *)dst = nic_state->cmd.val;
823 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
827 static int ne2k_std_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
828 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
829 int index = port & 0x1f;
830 uint8_t page = nic_state->cmd.pg_sel;
833 PrintError("ne2k_write error: length %d\n", length);
837 PrintDebug("ne2k_write: port:0x%x val: 0x%x\n", port, (int)val);
843 nic_state->pgstart = val;
846 nic_state->pgstop = val;
849 nic_state->boundary = val;
852 nic_state->tpsr = val;
855 nic_state->tbcr0 = val;
858 nic_state->tbcr1 = val;
861 nic_state->isr.val &= ~(val & 0x7f);
862 ne2k_update_irq(dev);
865 nic_state->rsar0 = val;
868 nic_state->rsar1 = val;
871 nic_state->rbcr0 = val;
874 nic_state->rbcr1 = val;
877 nic_state->rcr.val = val;
880 nic_state->tcr.val = val;
883 nic_state->dcr.val = val;
886 nic_state->imr.val = val;
887 //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
888 ne2k_update_irq(dev);
891 PrintError("ne2k_write error: invalid port:0x%x\n", port);
894 } else if (page == 1) {
896 case EN1_PHYS ... EN1_PHYS + 5:
897 nic_state->mac_addr[port - EN1_PHYS] = val;
900 nic_state->curpag = val;
902 case EN1_MULT ... EN1_MULT + 7:
903 // PrintError("ne2k_write error: write EN_MULT:0x%x\n", (int)val);
904 nic_state->mcast_addr[port - EN1_MULT] = val;
907 PrintError("ne2k_write error: invalid port:0x%x\n", port);
910 } else if (page == 2) {
913 nic_state->clda0 = val;
916 nic_state->clda1 = val;
919 nic_state->rnpp = val;
922 nic_state->lnpp = val;
925 nic_state->addcnt0 = val;
928 nic_state->addcnt1 = val;
931 PrintError("ne2k_write error: invalid port:0x%x\n", port);
935 PrintError("Invalid Register Page Value\n");
944 static int ne2k_std_read(uint16_t port, void * dst, uint_t length, struct vm_device *dev) {
945 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
946 uint16_t index = port & 0x1f;
947 uint8_t page = nic_state->cmd.pg_sel;
950 PrintError("ne2k_read error: length %d\n", length);
958 *(uint8_t *)dst = nic_state->clda0;
961 *(uint8_t *)dst = nic_state->clda1;
964 *(uint8_t *)dst = nic_state->boundary;
967 *(uint8_t *)dst = nic_state->tsr.val;
970 *(uint8_t *)dst = nic_state->ncr;
973 *(uint8_t *)dst = nic_state->fifo;
976 *(uint8_t *)dst = nic_state->isr.val;
977 ne2k_update_irq(dev);
980 *(uint8_t *)dst = nic_state->crda0;
983 *(uint8_t *)dst = nic_state->crda1;
986 *(uint8_t *)dst = nic_state->rsr.val;
989 *(uint8_t *)dst = nic_state->cntr0;
992 *(uint8_t *)dst = nic_state->cntr1;
995 *(uint8_t *)dst = nic_state->cntr2;
998 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1002 } else if (page == 1) {
1005 case EN1_PHYS ... EN1_PHYS + 5:
1006 *(uint8_t *)dst = nic_state->mac_addr[index - EN1_PHYS];
1009 *(uint8_t *)dst = nic_state->curpag;
1011 case EN1_MULT ... EN1_MULT + 7:
1012 *(uint8_t *)dst = nic_state->mcast_addr[index - EN1_MULT];
1015 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1019 } else if (page == 2) {
1023 *(uint8_t *)dst = nic_state->pgstart;
1026 *(uint8_t *)dst = nic_state->pgstop;
1029 *(uint8_t *)dst = nic_state->rnpp;
1032 *(uint8_t *)dst = nic_state->lnpp;
1035 *(uint8_t *)dst = nic_state->tpsr;
1038 *(uint8_t *)dst = nic_state->addcnt0;
1041 *(uint8_t *)dst = nic_state->addcnt1;
1044 *(uint8_t *)dst = nic_state->rcr.val;
1047 *(uint8_t *)dst = nic_state->tcr.val;
1050 *(uint8_t *)dst = nic_state->dcr.val;
1053 *(uint8_t *)dst = nic_state->imr.val;
1056 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1060 PrintError("Invalid Register Page Value\n");
1065 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
1071 static int ne2k_start_device(struct vm_device * dev) {
1072 PrintDebug("vnic: start device\n");
1078 static int ne2k_stop_device(struct vm_device * dev) {
1079 PrintDebug("vnic: stop device\n");
1087 static int ne2k_init_device(struct vm_device * dev) {
1088 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
1090 PrintDebug("Initializing NE2K\n");
1092 init_ne2k_context(dev);
1094 if (nic_state->pci_bus == NULL) {
1095 PrintDebug("NE2k: Not attached to pci\n");
1097 v3_dev_hook_io(dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
1099 for (i = 1; i < 16; i++){
1100 v3_dev_hook_io(dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
1103 v3_dev_hook_io(dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
1104 v3_dev_hook_io(dev, NIC_RESET_PORT, &ne2k_reset_read, &ne2k_reset_write);
1108 struct v3_pci_bar bars[6];
1109 struct pci_device * pci_dev = NULL;
1112 PrintDebug("NE2k: 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 = NIC_REG_BASE_PORT;
1120 bars[0].num_ports = 256;
1122 bars[0].io_read = ne2k_pci_read;
1123 bars[0].io_write = ne2k_pci_write;
1125 pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
1127 pci_config_update, NULL, NULL, dev);
1129 if (pci_dev == NULL) {
1130 PrintError("Failed to register NE2K with PCI\n");
1134 pci_dev->config_header.vendor_id = 0x10ec;
1135 pci_dev->config_header.device_id = 0x8029;
1136 pci_dev->config_header.revision = 0x00;
1138 pci_dev->config_header.subclass = 0x00;
1139 pci_dev->config_header.class = 0x02;
1140 pci_dev->config_header.header_type = 0x00;
1142 pci_dev->config_header.intr_line = 11;
1143 pci_dev->config_header.intr_pin = 1;
1145 nic_state->pci_dev = pci_dev;
1149 #ifdef CONFIG_DEBUG_NE2K
1158 static int ne2k_deinit_device(struct vm_device *dev) {
1161 for (i = 0; i < 16; i++){
1162 v3_dev_unhook_io(dev, NIC_REG_BASE_PORT + i);
1165 v3_dev_unhook_io(dev, NIC_DATA_PORT);
1166 v3_dev_unhook_io(dev, NIC_RESET_PORT);
1172 static struct v3_device_ops dev_ops = {
1173 .init = ne2k_init_device,
1174 .deinit = ne2k_deinit_device,
1175 .reset = ne2k_reset_device,
1176 .start = ne2k_start_device,
1177 .stop = ne2k_stop_device,
1181 struct vm_device * v3_create_ne2k(struct vm_device * pci) {
1182 struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
1184 memset(nic_state, 0, sizeof(struct ne2k_context));
1186 nic_state->pci_bus = pci;
1188 struct vm_device * device = v3_create_device("NE2K", &dev_ops, nic_state);