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 <config/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>
31 #include <palacios/vmm_dev_mgr.h>
32 #include <palacios/vmm_intr.h>
34 #ifndef CONFIG_DEBUG_NE2K
36 #define PrintDebug(fmts, args...)
42 #define NE2K_DEFAULT_IRQ 11
44 #define MAX_ETH_FRAME_SIZE 1514
47 // What the hell is this crap?
48 #define NE2K_PMEM_SIZE (32 * 1024)
49 #define NE2K_PMEM_START (16 * 1024)
50 #define NE2K_PMEM_END (NE2K_PMEM_SIZE + NE2K_PMEM_START)
51 #define NE2K_MEM_SIZE NE2K_PMEM_END
53 #define NIC_REG_BASE_PORT 0xc100 //Command register (for all pages)
54 #define NIC_DATA_PORT 0xc110 //Data read/write port
55 #define NIC_RESET_PORT 0xc11f //Data read/write port
58 #define EN0_CLDALO 0x01 //Low byte of current local dma addr RD
59 #define EN0_STARTPG 0x01 //Starting page of ring bfr WR
60 #define EN0_CLDAHI 0x02 //High byte of current local dma addr RD
61 #define EN0_STOPPG 0x02 //Ending page +1 of ring bfr WR
62 #define EN0_BOUNDARY 0x03 //Boundary page of ring bfr RD WR
63 #define EN0_TSR 0x04 //Transmit status reg RD
64 #define EN0_TPSR 0x04 //Transmit starting page WR
65 #define EN0_NCR 0x05 //Number of collision reg RD
66 #define EN0_TCNTLO 0x05 //Low byte of tx byte count WR
67 #define EN0_FIFO 0x06 //FIFO RD
68 #define EN0_TCNTHI 0x06 //High byte of tx byte count WR
69 #define EN0_ISR 0x07 //Interrupt status reg RD WR
70 #define EN0_CRDALO 0x08 //low byte of current remote dma address RD
71 #define EN0_RSARLO 0x08 //Remote start address reg 0
72 #define EN0_CRDAHI 0x09 //high byte, current remote dma address RD
73 #define EN0_RSARHI 0x09 //Remote start address reg 1
74 #define EN0_RCNTLO 0x0a //Remote byte count reg WR
75 #define EN0_RTL8029ID0 0x0a //Realtek ID byte #1 RD
76 #define EN0_RCNTHI 0x0b //Remote byte count reg WR
77 #define EN0_RTL8029ID1 0x0b //Realtek ID byte #2 RD
78 #define EN0_RSR 0x0c //rx status reg RD
79 #define EN0_RXCR 0x0c //RX configuration reg WR
80 #define EN0_TXCR 0x0d //TX configuration reg WR
81 #define EN0_COUNTER0 0x0d //Rcv alignment error counter RD
82 #define EN0_DCFG 0x0e //Data configuration reg WR
83 #define EN0_COUNTER1 0x0e //Rcv CRC error counter RD
84 #define EN0_IMR 0x0f //Interrupt mask reg WR
85 #define EN0_COUNTER2 0x0f //Rcv missed frame error counter RD
89 #define EN1_CURPAG 0x07
93 #define EN2_STARTPG 0x01 //Starting page of ring bfr RD
94 #define EN2_STOPPG 0x02 //Ending page +1 of ring bfr RD
95 #define EN2_LDMA0 0x01 //Current Local DMA Address 0 WR
96 #define EN2_LDMA1 0x02 //Current Local DMA Address 1 WR
97 #define EN2_RNPR 0x03 //Remote Next Packet Pointer RD WR
98 #define EN2_TPSR 0x04 //Transmit Page Start Address RD
99 #define EN2_LNRP 0x05 //Local Next Packet Pointer RD WR
100 #define EN2_ACNT0 0x06 //Address Counter Upper WR
101 #define EN2_ACNT1 0x07 //Address Counter Lower WR
102 #define EN2_RCR 0x0c //Receive Configuration Register RD
103 #define EN2_TCR 0x0d //Transmit Configuration Register RD
104 #define EN2_DCR 0x0e //Data Configuration Register RD
105 #define EN2_IMR 0x0f //Interrupt Mask Register RD
108 #define EN3_CONFIG0 0x03
109 #define EN3_CONFIG1 0x04
110 #define EN3_CONFIG2 0x05
111 #define EN3_CONFIG3 0x06
115 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
124 uint8_t rem_dma_cmd : 3; // 0=Not allowed, 1=Read, 2=Write, 3=Send Pkt, 4=Abort/Complete DMA
126 } __attribute__((packed));
127 } __attribute__((packed));
128 } __attribute__((packed));
131 struct intr_status_reg {
139 uint8_t overwrite_warn : 1;
140 uint8_t cnt_overflow : 1;
141 uint8_t rem_dma_done : 1;
142 uint8_t reset_status : 1;
143 } __attribute__((packed));
144 } __attribute__((packed));
145 } __attribute__((packed));
148 struct intr_mask_reg {
156 uint8_t overwrite_warn : 1;
157 uint8_t cnt_overflow : 1;
158 uint8_t rem_dma_done : 1;
160 } __attribute__((packed));
161 } __attribute__((packed));
162 } __attribute__((packed));
165 struct data_cfg_reg {
169 uint8_t word_trans_sel : 1;
170 uint8_t byte_order_sel : 1;
171 uint8_t long_addr_sel : 1;
172 uint8_t loopback_sel : 1;
173 uint8_t auto_init_rem : 1;
174 uint8_t fifo_thresh_sel : 2;
176 } __attribute__((packed));
177 } __attribute__((packed));
178 } __attribute__((packed));
185 uint8_t inhibit_crc : 1;
186 uint8_t enc_loop_ctrl : 2;
187 uint8_t auto_tx_disable : 1;
188 uint8_t coll_offset_en : 1;
190 } __attribute__((packed));
191 } __attribute__((packed));
192 } __attribute__((packed));
194 struct tx_status_reg {
198 uint8_t pkt_tx_ok : 1;
200 uint8_t tx_collision : 1;
201 uint8_t tx_aborted : 1;
202 uint8_t carrier_lost : 1;
203 uint8_t fifo_underrun : 1;
204 uint8_t cd_heartbeat : 1;
205 uint8_t oow_collision : 1;
206 } __attribute__((packed));
207 } __attribute__((packed));
208 } __attribute__((packed));
214 uint8_t save_pkt_errs : 1;
215 uint8_t runt_pkt_ok : 1;
216 uint8_t bcast_ok : 1;
217 uint8_t mcast_ok : 1;
218 uint8_t prom_phys_enable : 1;
219 uint8_t mon_mode : 1;
221 } __attribute__((packed));
222 } __attribute__((packed));
223 } __attribute__((packed));
226 struct rx_status_reg {
230 uint8_t pkt_rx_ok : 1;
232 uint8_t frame_align_err : 1;
233 uint8_t fifo_overrun : 1;
234 uint8_t missed_pkt : 1;
235 uint8_t phy_match : 1; // 0=Physical Addr Match, 1=MCAST/BCAST Addr Match
236 uint8_t rx_disabled : 1;
237 uint8_t deferring : 1;
238 } __attribute__((packed));
239 } __attribute__((packed));
240 } __attribute__((packed));
243 struct ne2k_context {
244 struct guest_info * vm;
246 nic_state_t dev_state;
250 struct intr_status_reg isr;
251 struct intr_mask_reg imr;
252 struct data_cfg_reg dcr;
253 struct tx_cfg_reg tcr;
254 struct tx_status_reg tsr;
255 struct rx_cfg_reg rcr;
256 struct rx_status_reg rsr;
258 uint8_t pgstart; // page start reg
259 uint8_t pgstop; // page stop reg
260 uint8_t boundary; // boundary ptr
261 uint8_t tpsr; // tx page start addr
262 uint8_t ncr; // number of collisions
263 uint8_t fifo; // FIFO...
265 uint8_t curpag; // current page
266 uint8_t rnpp; // rem next pkt ptr
267 uint8_t lnpp; // local next pkt ptr
269 uint8_t cntr0; // counter 0 (frame alignment errors)
270 uint8_t cntr1; // counter 1 (CRC Errors)
271 uint8_t cntr2; // counter 2 (missed pkt errors)
273 union { // current local DMA Addr
278 } __attribute__((packed));
279 } __attribute__((packed));
282 union { // current remote DMA addr
287 } __attribute__((packed));
288 } __attribute__((packed));
291 union { // Remote Start Addr Reg
296 } __attribute__((packed));
297 } __attribute__((packed));
300 union { // TX Byte count Reg
305 } __attribute__((packed));
306 } __attribute__((packed));
308 union { // Remote Byte count Reg
313 } __attribute__((packed));
314 } __attribute__((packed));
318 union { // Address counter?
323 } __attribute__((packed));
324 } __attribute__((packed));
327 uint8_t mcast_addr[8]; // multicast mask array
328 uint8_t mac_addr[6]; // MAC Addr
330 uint8_t mem[NE2K_MEM_SIZE];
332 struct pci_device * pci_dev;
333 struct vm_device * pci_bus;
336 #define compare_mac(src, dst) !memcmp(src, dst, 6)
338 #ifdef CONFIG_DEBUG_NE2K
339 static void dump_state(struct vm_device * dev) {
340 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
344 PrintDebug("====NE2000: Dumping state Begin ==========\n");
345 PrintDebug("Registers:\n");
347 // JRL: Dump Registers
349 PrintDebug("Memory:\n");
351 for(i = 0; i < 32; i++) {
352 PrintDebug("0x%02x ", nic_state->mem[i]);
356 PrintDebug("====NE2000: Dumping state End==========\n");
362 static int ne2k_update_irq(struct vm_device *dev) {
363 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
364 struct pci_device * pci_dev = nic_state->pci_dev;
367 if (pci_dev == NULL){
368 PrintDebug("Ne2k: Device %p is not attached to any PCI Bus\n", nic_state);
369 irq_line = NE2K_DEFAULT_IRQ;
371 irq_line = pci_dev->config_header.intr_line;
375 PrintError("Ne2k: IRQ_LINE: %d\n", irq_line);
379 PrintDebug("ne2k_update_irq: irq_line: %d\n", irq_line);
382 // The top bit of the ISR/IMR is reserved and does not indicate and irq event
383 // We mask the bit out of the irq pending check
384 if ((nic_state->isr.val & nic_state->imr.val) & 0x7f) {
385 v3_raise_virq(nic_state->vm, irq_line);
386 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->isr.val, nic_state->imr.val);
394 static void ne2k_init_state(struct vm_device * dev) {
395 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
397 uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, 0x60};
399 nic_state->vm = dev->vm;
401 nic_state->isr.reset_status = 1;
402 nic_state->imr.val = 0x00;
403 nic_state->cmd.val = 0x22;
405 for (i = 0; i < 5; i++) {
406 nic_state->mac_addr[i] = mac[i];
409 memset(nic_state->mcast_addr, 0xff, sizeof(nic_state->mcast_addr));
411 // Not sure what this is about....
412 memset(nic_state->mem, 0xff, 32);
414 memcpy(nic_state->mem, nic_state->mac_addr, 6);
415 nic_state->mem[14] = 0x57;
416 nic_state->mem[15] = 0x57;
418 #ifdef CONFIG_DEBUG_NE2K
424 static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length) {
427 PrintDebug("\nNe2k: Sending Packet\n");
429 for (i = 0; i < length; i++) {
430 PrintDebug("%x ",pkt[i]);
435 PrintError("Implement Send Packet interface\n");
440 static int ne2k_rxbuf_full(struct vm_device *dev) {
444 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
446 index = nic_state->curpag << 8;
447 boundary = nic_state->boundary << 8;
449 if (index < boundary) {
450 empty = boundary - index;
452 empty = ((nic_state->pgstop - nic_state->pgstart) << 8) - (index - boundary);
455 if (empty < (MAX_ETH_FRAME_SIZE + 4)) {
462 #define MIN_BUF_SIZE 60
465 // This needs to be completely redone...
466 static void ne2k_receive(struct vm_device * dev, const uchar_t * pkt, int length) {
467 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
478 start = nic_state->pgstart << 8;
479 stop = nic_state->pgstop << 8;
481 if (nic_state->cmd.stop) {
485 if (ne2k_rxbuf_full(dev)) {
486 PrintError("Ne2k: received buffer overflow\n");
491 //packet too small, expand it
492 if (length < MIN_BUF_SIZE) {
493 memcpy(buf, pkt, length);
494 memset(buf + length, 0, MIN_BUF_SIZE - length);
496 length = MIN_BUF_SIZE;
499 index = nic_state->curpag << 8;
502 total_len = length + 4;
504 //address for next packet (4 bytes for CRC)
505 next = index + ((total_len + 4 + 255) & ~0xff);
508 next -= (stop - start);
511 p = nic_state->mem + index;
512 nic_state->rsr.val = 0;
513 nic_state->rsr.pkt_rx_ok = 1;
516 nic_state->rsr.phy = 1;
519 p[0] = nic_state->rsr.val;
522 p[3] = total_len >> 8;
527 empty = stop - index;
538 memcpy(nic_state->mem + index, pkt, len);
549 nic_state->curpag = next >> 8;
551 nic_state->isr.pkt_rx = 1;
552 ne2k_update_irq(dev);
558 static int netif_input(uchar_t *pkt, uint_t size) {
559 struct ne2k_context * nic_state;
560 static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
563 #ifdef CONFIG_DEBUG_NE2K
564 PrintDebug("\nNe2k: Packet Received:\nSource:");
565 for (i = 6; i < 12; i++) {
566 PrintDebug("%x ", pkt[i]);
571 for(i = 0; i < size; i++) {
572 PrintDebug("%x ", pkt[i]);
578 if (nic_state->rcr.prom_phys_enable == 1) {
580 ne2k_receive(ne2ks[i], pkt, size);
581 } else if (compare_mac(pkt, brocast_mac) && (nic_state->rcr.bcast_ok)) {
583 ne2k_receive(ne2ks[i], pkt, size);
584 } else if ((pkt[0] & 0x01) && (nic_state->rcr.mcast_ok)) {
585 //TODO: multicast packet
586 ne2k_receive(ne2ks[i], pkt, size);
587 } else if (compare_mac(pkt, nic_state->mac_addr)) {
588 ne2k_receive(ne2ks[i], pkt, size);
595 static void ne2k_mem_writeb(struct ne2k_context * nic_state, uint32_t addr, uint32_t val) {
598 tmp = (uchar_t) (val & 0x000000ff);
600 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
601 nic_state->mem[addr] = tmp;
604 PrintDebug("wmem addr: %x val: %x\n", addr, val);
607 static void ne2k_mem_writew(struct ne2k_context * nic_state,
610 addr &= ~1; //XXX: check exact behaviour if not even
612 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
613 *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
616 PrintDebug("wmem addr: %x val: %x\n", addr, val);
619 static void ne2k_mem_writel(struct ne2k_context *nic_state,
622 addr &= ~1; // XXX: check exact behaviour if not even
624 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
625 *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
628 PrintDebug("wmem addr: %x val: %x\n", addr, val);
631 static uchar_t ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr) {
632 PrintDebug("rmem addr: %x\n", addr);
634 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
635 return nic_state->mem[addr];
641 static ushort_t ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr) {
642 PrintDebug("rmem addr: %x\n", addr);
644 addr &= ~1; //XXX: check exact behaviour if not even
646 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
647 return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
653 static uint32_t ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr) {
654 PrintDebug("rmem addr: %x\n", addr);
656 addr &= ~1; //XXX: check exact behaviour if not even
658 if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
659 return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
666 static void ne2k_dma_update(struct vm_device *dev, int len) {
667 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
669 nic_state->rsar += len;
672 if (nic_state->rsar == nic_state->pgstop) {
673 nic_state->rsar = nic_state->pgstart;
676 if (nic_state->rbcr <= len) {
678 nic_state->isr.rem_dma_done = 1;
679 ne2k_update_irq(dev);
681 nic_state->rbcr -= len;
686 //for data port read/write
687 static int ne2k_data_read(ushort_t port, void * dst, uint_t length, struct vm_device *dev) {
689 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
691 // current dma address
692 uint32_t addr = nic_state->rsar;
696 val = ne2k_mem_readb(nic_state, addr);
699 val = ne2k_mem_readw(nic_state, addr);
702 val = ne2k_mem_readl(nic_state, addr);
705 PrintError("ne2k_data_read error: invalid length %d\n", length);
709 ne2k_dma_update(dev, length);
711 memcpy(dst, &val, length);
713 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
718 static int ne2k_data_write(ushort_t port, void * src, uint_t length, struct vm_device *dev) {
720 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
721 uint32_t addr = nic_state->rsar;
723 if (nic_state->rbcr == 0) {
727 memcpy(&val, src, length);
731 ne2k_mem_writeb(nic_state, addr, val);
734 ne2k_mem_writew(nic_state, addr, val);
737 ne2k_mem_writel(nic_state, addr, val);
740 PrintError("nic_data_write error: invalid length %d\n", length);
743 ne2k_dma_update(dev, length);
745 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
750 static int ne2k_reset_device(struct vm_device * dev) {
751 PrintDebug("vnic: reset device\n");
753 init_ne2k_context(dev);
760 static int ne2k_reset_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
761 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x\n", port, length, val);
763 memset(dst, 0, length);
764 ne2k_reset_device(dev);
769 static int ne2k_reset_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
770 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port, length, val);
776 static int ne2k_cmd_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
777 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
780 PrintError("Invalid write length to ne2k Command register\n");
784 nic_state->cmd.val = *(uint8_t *)src;
786 if (!(nic_state->cmd.stop)) {
787 nic_state->isr.reset_status = 0;
790 // if ((send pkt) && (dma byte count == 0))
791 if ((nic_state.rem_dma_cmd & 0x3) && (nic_state->rbcr == 0)) {
792 nic_state->isr.rem_dma_done = 1;
793 ne2k_update_irq(dev);
796 if (nic_state->cmd.tx_pkt) {
797 int offset = (nic_state->tpsr << 8);
799 if (offset >= NE2K_PMEM_END) {
800 offset -= NE2K_PMEM_SIZE;
803 if (offset + nic_state->tbcr <= NE2K_PMEM_END) {
804 ne2k_send_packet(dev, nic_state->mem + offset, nic_state->tbcr);
808 nic_state->tsr.val = 0; // clear the tx status reg
809 nic_state->tsr.pkt_tx_ok = 1; // indicate successful tx
811 nic_state->isr.pkt_tx = 1; // irq due to pkt tx
812 nic_state->cmd.tx_pkt = 0; // reset cmd bit
813 ne2k_update_irq(dev);
816 // stop the controller
822 static int ne2k_cmd_read(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
823 *(uint8_t *)dst = nic_state->cmd.val;
825 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
829 static int ne2k_std_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
830 struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
831 int index = port & 0x1f;
832 uint8_t page = nic_state->cmd.pg_sel;
835 PrintError("ne2k_write error: length %d\n", length);
839 PrintDebug("ne2k_write: port:0x%x val: 0x%x\n", port, (int)val);
845 nic_state->pgstart = val;
848 nic_state->pgstop = val;
851 nic_state->boundary = val;
854 nic_state->tpsr = val;
857 nic_state->tbcr0 = val;
860 nic_state->tbcr1 = val;
863 nic_state->isr.val &= ~(val & 0x7f);
864 ne2k_update_irq(dev);
867 nic_state->rsar0 = val;
870 nic_state->rsar1 = val;
873 nic_state->rbcr0 = val;
876 nic_state->rbcr1 = val;
879 nic_state->rcr.val = val;
882 nic_state->tcr.val = val;
885 nic_state->dcr.val = val;
888 nic_state->imr.val = val;
889 //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
890 ne2k_update_irq(dev);
893 PrintError("ne2k_write error: invalid port:0x%x\n", port);
896 } else if (page == 1) {
898 case EN1_PHYS ... EN1_PHYS + 5:
899 nic_state->mac_addr[port - EN1_PHYS] = val;
902 nic_state->curpag = val;
904 case EN1_MULT ... EN1_MULT + 7:
905 // PrintError("ne2k_write error: write EN_MULT:0x%x\n", (int)val);
906 nic_state->mcast_addr[port - EN1_MULT] = val;
909 PrintError("ne2k_write error: invalid port:0x%x\n", port);
912 } else if (page == 2) {
915 nic_state->clda0 = val;
918 nic_state->clda1 = val;
921 nic_state->rnpp = val;
924 nic_state->lnpp = val;
927 nic_state->addcnt0 = val;
930 nic_state->addcnt1 = val;
933 PrintError("ne2k_write error: invalid port:0x%x\n", port);
937 PrintError("Invalid Register Page Value\n");
946 static int ne2k_std_read(uint16_t port, void * dst, uint_t length, struct vm_device *dev) {
947 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
948 uint16_t index = port & 0x1f;
949 uint8_t page = nic_state->cmd.pg_sel;
952 PrintError("ne2k_read error: length %d\n", length);
960 *(uint8_t *)dst = nic_state->clda0;
963 *(uint8_t *)dst = nic_state->clda1;
966 *(uint8_t *)dst = nic_state->boundary;
969 *(uint8_t *)dst = nic_state->tsr.val;
972 *(uint8_t *)dst = nic_state->ncr;
975 *(uint8_t *)dst = nic_state->fifo;
978 *(uint8_t *)dst = nic_state->isr.val;
979 ne2k_update_irq(dev);
982 *(uint8_t *)dst = nic_state->crda0;
985 *(uint8_t *)dst = nic_state->crda1;
988 *(uint8_t *)dst = nic_state->rsr.val;
991 *(uint8_t *)dst = nic_state->cntr0;
994 *(uint8_t *)dst = nic_state->cntr1;
997 *(uint8_t *)dst = nic_state->cntr2;
1000 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1004 } else if (page == 1) {
1007 case EN1_PHYS ... EN1_PHYS + 5:
1008 *(uint8_t *)dst = nic_state->mac_addr[index - EN1_PHYS];
1011 *(uint8_t *)dst = nic_state->curpag;
1013 case EN1_MULT ... EN1_MULT + 7:
1014 *(uint8_t *)dst = nic_state->mcast_addr[index - EN1_MULT];
1017 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1021 } else if (page == 2) {
1025 *(uint8_t *)dst = nic_state->pgstart;
1028 *(uint8_t *)dst = nic_state->pgstop;
1031 *(uint8_t *)dst = nic_state->rnpp;
1034 *(uint8_t *)dst = nic_state->lnpp;
1037 *(uint8_t *)dst = nic_state->tpsr;
1040 *(uint8_t *)dst = nic_state->addcnt0;
1043 *(uint8_t *)dst = nic_state->addcnt1;
1046 *(uint8_t *)dst = nic_state->rcr.val;
1049 *(uint8_t *)dst = nic_state->tcr.val;
1052 *(uint8_t *)dst = nic_state->dcr.val;
1055 *(uint8_t *)dst = nic_state->imr.val;
1058 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1062 PrintError("Invalid Register Page Value\n");
1067 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", port, *(uint8_t *)dst);
1073 static int ne2k_start_device(struct vm_device * dev) {
1074 PrintDebug("vnic: start device\n");
1080 static int ne2k_stop_device(struct vm_device * dev) {
1081 PrintDebug("vnic: stop device\n");
1089 static int ne2k_init_device(struct vm_device * dev) {
1090 struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
1092 PrintDebug("Initializing NE2K\n");
1094 init_ne2k_context(dev);
1096 if (nic_state->pci_bus == NULL) {
1097 PrintDebug("NE2k: Not attached to pci\n");
1099 v3_dev_hook_io(dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
1101 for (i = 1; i < 16; i++){
1102 v3_dev_hook_io(dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
1105 v3_dev_hook_io(dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
1106 v3_dev_hook_io(dev, NIC_RESET_PORT, &ne2k_reset_read, &ne2k_reset_write);
1110 struct v3_pci_bar bars[6];
1111 struct pci_device * pci_dev = NULL;
1114 PrintDebug("NE2k: PCI Enabled\n");
1116 for (i = 0; i < 6; i++) {
1117 bars[i].type = PCI_BAR_NONE;
1120 bars[0].type = PCI_BAR_IO;
1121 bars[0].default_base_port = NIC_REG_BASE_PORT;
1122 bars[0].num_ports = 256;
1124 bars[0].io_read = ne2k_pci_read;
1125 bars[0].io_write = ne2k_pci_write;
1127 pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0,
1129 pci_config_update, NULL, NULL, dev);
1131 if (pci_dev == NULL) {
1132 PrintError("Failed to register NE2K with PCI\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;
1151 #ifdef CONFIG_DEBUG_NE2K
1160 static int ne2k_deinit_device(struct vm_device *dev) {
1163 for (i = 0; i < 16; i++){
1164 v3_dev_unhook_io(dev, NIC_REG_BASE_PORT + i);
1167 v3_dev_unhook_io(dev, NIC_DATA_PORT);
1168 v3_dev_unhook_io(dev, NIC_RESET_PORT);
1174 static struct v3_device_ops dev_ops = {
1175 .init = ne2k_init_device,
1176 .deinit = ne2k_deinit_device,
1177 .reset = ne2k_reset_device,
1178 .start = ne2k_start_device,
1179 .stop = ne2k_stop_device,
1183 struct vm_device * v3_create_ne2k(struct vm_device * pci) {
1184 struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
1186 memset(nic_state, 0, sizeof(struct ne2k_context));
1188 nic_state->pci_bus = pci;
1190 struct vm_device * device = v3_create_device("NE2K", &dev_ops, nic_state);