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...)
37 //#define TEST_PERFORMANCE 0
39 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
42 struct guest_info *vm;
43 nic_state_t dev_state;
45 struct ne2k_regs regs;
47 uchar_t mem[NE2K_MEM_SIZE];
48 struct pci_device *pci_dev;
49 struct vm_device *pci;
54 struct vm_device *ne2ks[NUM_NE2K]; //the array of virtual network cards
56 static int nic_no = 0;
59 static uint32_t exit_num = 0;
60 static uint32_t int_num = 0;
63 #define compare_mac(src, dst) ({ \
64 ((src[0] == dst[0]) && \
65 (src[1] == dst[1]) && \
66 (src[2] == dst[2]) && \
67 (src[3] == dst[3]) && \
68 (src[4] == dst[4]) && \
69 (src[5] == dst[5]))? 1:0; \
72 extern int V3_Send_pkt(uchar_t *buf, int length);
73 extern int V3_Register_pkt_event(int (*netif_input)(uchar_t * pkt, uint_t size));
76 static void dump_state(struct vm_device *dev)
80 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
82 PrintDebug("====NE2000: Dumping state Begin ==========\n");
83 PrintDebug("Registers:\n");
85 p = (uchar_t *)&nic_state->regs;
86 for(i = 0; i < sizeof(struct ne2k_regs); i++)
87 PrintDebug("Regs[%d] = 0x%2x\n", i, (int)p[i]);
89 PrintDebug("Memory:\n");
90 for(i = 0; i < 32; i++)
91 PrintDebug("0x%02x ", nic_state->mem[i]);
93 PrintDebug("====NE2000: Dumping state End==========\n");
99 static void ne2k_update_irq(struct vm_device *dev)
102 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
103 struct guest_info *guest = dev->vm;
105 isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0x7f);
107 if ((isr & 0x7f) != 0x0) {
108 v3_raise_irq(guest, NIC_DEF_IRQ);
109 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->regs.isr, nic_state->regs.imr);
117 static void ne2k_update_irq(struct vm_device *dev)
120 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
121 struct pci_device *pdev = nic_state->pci_dev;
125 PrintDebug("Ne2k: Device %p is not attached to any PCI Bus\n", nic_state);
126 irqline = NE2K_DEF_IRQ;
128 irqline = pdev->config_header.intr_line;
131 isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0x7f);
134 PrintError("Ne2k: IRQ_LINE: %d\n", irqline);
138 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->regs.isr, nic_state->regs.imr);
139 PrintDebug("ne2k_update_irq: irq_line: %d\n", irqline);
141 if ((isr & 0x7f) != 0x0) {
142 v3_raise_irq(nic_state->vm, irqline);
143 PrintDebug("Ne2k: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->regs.isr, nic_state->regs.imr);
146 if ((++int_num) % 50 == 0)
147 PrintError("Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
154 static void init_ne2k_context(struct vm_device *dev)
156 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
158 uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, (0x60 + nic_no)};
160 nic_state->vm = dev->vm;
162 nic_state->regs.isr = ENISR_RESET;
163 nic_state->regs.imr = 0x00;
164 nic_state->regs.cmd = 0x22;
166 for (i = 0; i < 5; i++)
167 nic_state->regs.macaddr[i] = nic_state->mac[i] = mac[i];
169 nic_state->regs.macaddr[5] = nic_state->mac[5] = mac[5] + nic_no;
171 for (i = 0; i < 8; i++)
172 nic_state->regs.mult[i] = 0xff;
174 for(i = 0; i < 32; i++) {
175 nic_state->mem[i] = 0xff;
178 memcpy(nic_state->mem, nic_state->mac, 6);
179 nic_state->mem[14] = 0x57;
180 nic_state->mem[15] = 0x57;
188 static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length)
192 PrintDebug("\nNe2k: Sending Packet\n");
194 for (i = 0; i<length; i++)
195 PrintDebug("%x ",pkt[i]);
198 return V3_Send_pkt(pkt, length);
201 static int ne2k_rxbuf_full(struct vm_device *dev)
203 int empty, index, boundary;
204 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
206 index = nic_state->regs.curpag << 8;
207 boundary = nic_state->regs.boundary << 8;
208 if (index < boundary)
209 empty = boundary - index;
211 empty = ((nic_state->regs.pgstop - nic_state->regs.pgstart) << 8) - (index - boundary);
213 if (empty < (MAX_ETH_FRAME_SIZE + 4))
219 #define MIN_BUF_SIZE 60
221 static void ne2k_receive(struct vm_device *dev, const uchar_t *pkt, int length)
223 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
224 struct ne2k_regs *nregs = &(nic_state->regs);
226 uint32_t total_len, next, len, index, empty;
228 uint32_t start, stop;
230 start = nregs->pgstart << 8;
231 stop = nregs->pgstop << 8;
233 if (nregs->cmd & NE2K_STOP)
236 if (ne2k_rxbuf_full(dev)){
237 PrintError("Ne2k: received buffer overflow\n");
241 //packet too small, expand it
242 if (length < MIN_BUF_SIZE) {
243 memcpy(buf, pkt, length);
244 memset(buf + length, 0, MIN_BUF_SIZE - length);
246 length = MIN_BUF_SIZE;
249 index = nregs->curpag << 8;
251 total_len = length + 4;
252 //address for next packet (4 bytes for CRC)
253 next = index + ((total_len + 4 + 255) & ~0xff);
255 next -= stop - start;
257 p = nic_state->mem + index;
258 nregs->rsr = ENRSR_RXOK;
261 nregs->rsr |= ENRSR_PHY;
266 p[3] = total_len >> 8;
271 empty = stop - index;
277 memcpy(nic_state->mem + index, pkt, len);
284 nregs->curpag = next >> 8;
286 nregs->isr |= ENISR_RX;
287 ne2k_update_irq(dev);
290 static int ne2k_hook_iospace(struct vm_device *vmdev, addr_t base_addr, int size, int type, void *data);
292 static struct pci_device * pci_ne2k_init(struct vm_device *vmdev,
293 struct vm_device *pci,
297 int (*io_read)(ushort_t port, void * dst, uint_t length, struct vm_device * dev),
298 int (*io_write)(ushort_t port, void * src, uint_t length, struct vm_device * dev))
301 struct pci_device *pdev;
302 struct v3_pci_bar ne2k_bar;
304 ne2k_bar.type = PCI_BAR_IO;
305 ne2k_bar.num_ports = 0x100;
306 ne2k_bar.default_base_port = 0xc100;
307 ne2k_bar.io_read = io_read;
308 ne2k_bar.io_write = io_write;
310 pdev = v3_pci_register_device(vmdev,
317 NULL, NULL, NULL, vmdev);
320 PrintError("NIC: Register to PCI bus failed\n");
324 pci_conf = pdev->config_space;
326 pci_conf[0x00] = 0xec; // Realtek 8029
327 pci_conf[0x01] = 0x10;
328 pci_conf[0x02] = 0x29;
329 pci_conf[0x03] = 0x80;
330 pci_conf[0x0a] = 0x00; // ethernet network controller
331 pci_conf[0x0b] = 0x02;
332 pci_conf[0x0e] = 0x00; // header_type
333 pci_conf[0x3d] = 1; // interrupt pin 0
334 pci_conf[0x3c] = 11; //default IRQ Line
336 pdev->vm_dev = vmdev;
341 static int netif_input(uchar_t *pkt, uint_t size)
343 struct ne2k_context *nic_state;
344 struct ne2k_regs *nregs;
345 static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
348 PrintDebug("\nNe2k: Packet Received:\nSource:");
349 for (i = 6; i < 12; i++) {
350 PrintDebug("%x ", pkt[i]);
353 for(i= 0; i<size; i++)
354 PrintDebug("%x ", pkt[i]);
357 for (i = 0; i < NUM_NE2K; i++){
358 if (ne2ks[i] != NULL) {
359 nic_state = (struct ne2k_context *)ne2ks[i]->private_data;
360 nregs = &(nic_state->regs);
362 if (nregs->rcr & 0x10) {//promiscuous mode
363 ne2k_receive(ne2ks[i], pkt, size);
365 if (compare_mac(pkt, brocast_mac) && (nregs->rcr & 0x04)){ //broadcast packet
366 ne2k_receive(ne2ks[i], pkt, size);
367 } else if (pkt[0] & 0x01) {
368 //TODO: multicast packet
369 if (nregs->rcr & 0x08)
370 ne2k_receive(ne2ks[i], pkt, size);
371 } else if (compare_mac(pkt, nic_state->mac)){
372 ne2k_receive(ne2ks[i], pkt, size);
383 static inline uint16_t cpu2le16(uint16_t val)
386 uchar_t *p1 = (uchar_t *)&p;
395 static inline uint32_t cpu2le32(uint32_t val)
398 uchar_t *p1 = (uchar_t *)&p;
408 static inline uint16_t le16_to_cpu(const uint16_t *p)
410 const uchar_t *p1 = (const uchar_t *)p;
411 return p1[0] | (p1[1] << 8);
414 static inline uint32_t le32_to_cpu(const uint32_t *p)
416 const uchar_t *p1 = (const uchar_t *)p;
417 return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
421 ne2k_mem_writeb(struct ne2k_context *nic_state,
427 tmp = (uchar_t) (val & 0x000000ff);
428 if (addr < 32 || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
429 nic_state->mem[addr] = tmp;
432 PrintDebug("wmem addr: %x val: %x\n", addr, val);
436 ne2k_mem_writew(struct ne2k_context *nic_state,
440 addr &= ~1; //XXX: check exact behaviour if not even
442 (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
443 *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
446 PrintDebug("wmem addr: %x val: %x\n", addr, val);
450 ne2k_mem_writel(struct ne2k_context *nic_state,
454 addr &= ~1; // XXX: check exact behaviour if not even
456 (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
457 *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
460 PrintDebug("wmem addr: %x val: %x\n", addr, val);
464 ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr)
466 PrintDebug("rmem addr: %x\n", addr);
469 (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
470 return nic_state->mem[addr];
477 ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr)
479 PrintDebug("rmem addr: %x\n", addr);
481 addr &= ~1; //XXX: check exact behaviour if not even
483 (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
484 return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
491 ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr)
493 PrintDebug("rmem addr: %x\n", addr);
495 addr &= ~1; //XXX: check exact behaviour if not even
497 (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
498 return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
505 ne2k_dma_update(struct vm_device *dev, int len)
507 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
509 nic_state->regs.rsar += len;
511 if (nic_state->regs.rsar == nic_state->regs.pgstop)
512 nic_state->regs.rsar = nic_state->regs.pgstart;
514 if (nic_state->regs.rbcr <= len) {
515 nic_state->regs.rbcr = 0;
516 nic_state->regs.isr |= ENISR_RDC;
517 ne2k_update_irq(dev);
519 nic_state->regs.rbcr -= len;
524 //for data port read/write
525 static int ne2k_data_read(ushort_t port,
528 struct vm_device *dev)
531 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
533 // current dma address
534 uint32_t addr = nic_state->regs.rsar;
538 val = ne2k_mem_readb(nic_state, addr);
541 val = ne2k_mem_readw(nic_state, addr);
544 val = ne2k_mem_readl(nic_state, addr);
547 PrintError("ne2k_data_read error: invalid length %d\n", length);
551 ne2k_dma_update(dev, length);
553 memcpy(dst, &val, length);
555 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f,length, val);
558 if ((++exit_num) % 50 == 0)
559 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
565 static int ne2k_data_write(ushort_t port,
568 struct vm_device *dev)
571 struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
573 if (nic_state->regs.rbcr == 0)
576 memcpy(&val, src, length);
578 uint32_t addr = nic_state->regs.rsar;
582 ne2k_mem_writeb(nic_state, addr, val);
585 ne2k_mem_writew(nic_state, addr, val);
588 ne2k_mem_writel(nic_state, addr, val);
591 PrintError("nic_data_write error: invalid length %d\n", length);
594 ne2k_dma_update(dev, length);
596 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f,length, val);
599 if ((++exit_num) % 50 == 0)
600 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
606 static int ne2k_reset_device(struct vm_device * dev)
609 PrintDebug("vnic: reset device\n");
611 init_ne2k_context(dev);
618 static int ne2k_reset_port_read(ushort_t port,
621 struct vm_device *dev)
625 memcpy(dst, &val, length);
627 PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x\n", port,length, val);
629 ne2k_reset_device(dev);
632 if ((++exit_num) % 50 == 0)
633 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
639 static int ne2k_reset_port_write(ushort_t port,
642 struct vm_device *dev)
646 memcpy(&val, src, length);
648 PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port,length, val);
651 if ((++exit_num) % 50 == 0)
652 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
658 static int ne2k_ioport_write(ushort_t port,
661 struct vm_device *dev)
664 struct ne2k_context *nic_state = (struct ne2k_context* )dev->private_data;
669 memcpy(&val, src, 1);
671 PrintError("ne2k_write error: length %d\n", length);
675 PrintDebug("ne2k_write: port:0x%x val: 0x%x\n", port, (int)val);
680 return ne2k_data_write(port, src, length, dev);
683 return ne2k_reset_port_write(port, src, length, dev);
685 if (port == EN0_COMMAND) {
686 nic_state->regs.cmd = val;
687 if (!(val & NE2K_STOP)) {
688 nic_state->regs.isr &= ~ENISR_RESET;
689 if ((val & (NE2K_DMAREAD | NE2K_DMAWRITE)) &&
690 nic_state->regs.rbcr == 0) {
691 nic_state->regs.isr |= ENISR_RDC;
692 ne2k_update_irq(dev);
694 if (val & NE2K_TRANSMIT) {
695 index = (nic_state->regs.tpsr << 8);
696 if (index >= NE2K_PMEM_END)
697 index -= NE2K_PMEM_SIZE;
698 if (index + nic_state->regs.tbcr <= NE2K_PMEM_END) {
699 ne2k_send_packet(dev, nic_state->mem + index, nic_state->regs.tbcr);
701 nic_state->regs.tsr = ENTSR_PTX;
702 nic_state->regs.isr |= ENISR_TX;
703 nic_state->regs.cmd &= ~NE2K_TRANSMIT;
704 ne2k_update_irq(dev);
708 page = nic_state->regs.cmd >> 6;
712 nic_state->regs.pgstart = val;
715 nic_state->regs.pgstop = val;
718 nic_state->regs.boundary = val;
721 nic_state->regs.tpsr = val;
724 nic_state->regs.tbcr = (nic_state->regs.tbcr & 0xff00) | val;
727 nic_state->regs.tbcr = (nic_state->regs.tbcr & 0x00ff) | (val << 8);
730 nic_state->regs.isr &= ~(val & 0x7f);
731 ne2k_update_irq(dev);
734 nic_state->regs.rsar = (nic_state->regs.rsar & 0xff00) | val;
737 nic_state->regs.rsar = (nic_state->regs.rsar & 0x00ff) | (val << 8);
740 nic_state->regs.rbcr = (nic_state->regs.rbcr & 0xff00) | val;
743 nic_state->regs.rbcr = (nic_state->regs.rbcr & 0x00ff) | (val << 8);
746 nic_state->regs.rcr = val;
749 nic_state->regs.tcr = val;
751 nic_state->regs.dcr = val;
754 nic_state->regs.imr = val;
755 //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
756 ne2k_update_irq(dev);
759 PrintError("ne2k_write error: invalid port:0x%x\n", port);
765 case EN1_PHYS ... EN1_PHYS + 5:
766 nic_state->regs.phys[port - EN1_PHYS] = val;
769 nic_state->regs.curpag = val;
771 case EN1_MULT ... EN1_MULT + 7:
772 // PrintError("ne2k_write error: write EN_MULT:0x%x\n", (int)val);
773 nic_state->regs.mult[port - EN1_MULT] = val;
776 PrintError("ne2k_write error: invalid port:0x%x\n", port);
783 nic_state->regs.clda = (nic_state->regs.clda & 0xff00) | val;
786 nic_state->regs.clda = (nic_state->regs.clda & 0x00ff) | (val << 8);
789 nic_state->regs.rnpp = val;
792 nic_state->regs.lnpp = val;
795 nic_state->regs.addcnt = (nic_state->regs.addcnt & 0xff00) | val;
798 nic_state->regs.addcnt = (nic_state->regs.addcnt & 0x00ff) | (val << 8);
801 PrintError("ne2k_write error: invalid port:0x%x\n", port);
808 if ((++exit_num) % 50 == 0)
809 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
816 static int ne2k_ioport_read(ushort_t port,
819 struct vm_device *dev)
821 uchar_t page, ret, offset;
823 struct ne2k_context *nic_state = (struct ne2k_context* )dev->private_data;
826 PrintError("ne2k_read error: length %d\n", length);
834 return ne2k_data_read(port, dst, length, dev);
837 return ne2k_reset_port_read(port, dst, length, dev);
839 if (port == EN0_COMMAND) {
840 ret = nic_state->regs.cmd;
842 page = nic_state->regs.cmd >> 6;
846 ret = nic_state->regs.clda & 0x00ff;
849 ret = (nic_state->regs.clda & 0xff00) >> 8;
852 ret = nic_state->regs.boundary;
855 ret = nic_state->regs.tsr;
858 ret = nic_state->regs.ncr;
861 ret = nic_state->regs.fifo;
864 ret = nic_state->regs.isr;
865 ne2k_update_irq(dev);
868 ret = nic_state->regs.crda & 0x00ff;
871 ret = (nic_state->regs.crda & 0xff00) >> 8;
874 ret = nic_state->regs.rsr;
877 ret = nic_state->regs.cntr & 0x000000ff;
880 ret = (nic_state->regs.cntr & 0x0000ff00) >> 8;
883 ret = (nic_state->regs.cntr & 0x00ff0000) >> 16;
886 PrintError("ne2k_read error: invalid port:0x%x\n", port);
893 case EN1_PHYS ... EN1_PHYS + 5:
894 ret = nic_state->regs.phys[port - EN1_PHYS];
897 ret = nic_state->regs.curpag;
899 case EN1_MULT ... EN1_MULT + 7:
900 ret = nic_state->regs.mult[port - EN1_MULT];
903 PrintError("ne2k_read error: invalid port:0x%x\n", port);
911 ret = nic_state->regs.pgstart;
914 ret = nic_state->regs.pgstop;
917 ret = nic_state->regs.rnpp;
920 ret = nic_state->regs.lnpp;
923 ret = nic_state->regs.tpsr;
926 ret = nic_state->regs.addcnt & 0x00ff;
929 ret = (nic_state->regs.addcnt & 0xff00) >> 8;
932 ret = nic_state->regs.rcr;
935 ret = nic_state->regs.tcr;
938 ret = nic_state->regs.dcr;
941 ret = nic_state->regs.imr;
944 PrintError("ne2k_read error: invalid port:0x%x\n", port);
951 memcpy(dst, &ret, 1);
953 PrintDebug("ne2k_read: port:0x%x val: 0x%x\n", offset, (int)ret);
956 if ((++exit_num) % 50 == 0)
957 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
965 static int ne2k_start_device(struct vm_device *dev)
967 PrintDebug("vnic: start device\n");
973 static int ne2k_stop_device(struct vm_device *dev)
975 PrintDebug("vnic: stop device\n");
980 static void init_global_setting()
984 V3_Register_pkt_event(&netif_input);
986 for (i = 0; i < NUM_NE2K; i++)
991 static int ne2k_hook_iospace(struct vm_device *vmdev, addr_t base_addr, int size, int type, void *data)
998 PrintDebug("In NIC%d: Hook IO space starting from %x\n", nic_no, (int) base_addr);
1000 for (i = 0; i < 16; i++){
1001 v3_dev_hook_io(vmdev, base_addr + i, &ne2k_ioport_read, &ne2k_ioport_write);
1003 v3_dev_hook_io(vmdev, base_addr + NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
1004 v3_dev_hook_io(vmdev, base_addr + NIC_RESET_PORT, &ne2k_reset_port_read, &ne2k_reset_port_write);
1010 static int ne2k_init_device(struct vm_device * vmdev)
1012 struct vm_device *pci = NULL;
1013 struct pci_device *pdev = NULL;
1014 struct ne2k_context *nic_state = (struct ne2k_context *)vmdev->private_data;
1016 PrintDebug("ne2k%d: init_device\n", nic_no);
1018 if (nic_no == 0) // only initiate once
1019 init_global_setting();
1021 init_ne2k_context(vmdev);
1023 pci = nic_state->pci;
1026 PrintDebug("Ne2k: attach ne2k to the pci %p\n", pci);
1027 pdev = pci_ne2k_init(vmdev, pci, 0, -1, 0, &ne2k_ioport_read, &ne2k_ioport_write);
1029 PrintError("Ne2k: initiate failure, failure to attach ne2k to the bus %p\n", pci);
1031 PrintDebug("Ne2k: Not attached to any pci\n");
1032 ne2k_hook_iospace(vmdev, NE2K_DEF_BASE_ADDR, 100, 0, NULL);
1035 nic_state->pci_dev = pdev;
1036 ne2ks[nic_no ++] = vmdev;
1047 static int ne2k_deinit_device(struct vm_device *vmdev)
1051 for (i = 0; i<16; i++){
1052 v3_dev_unhook_io(vmdev, NE2K_DEF_BASE_ADDR + i);
1055 v3_dev_unhook_io(vmdev, NE2K_DEF_BASE_ADDR + NIC_DATA_PORT);
1056 v3_dev_unhook_io(vmdev, NE2K_DEF_BASE_ADDR + NIC_RESET_PORT);
1062 static struct vm_device_ops dev_ops = {
1063 .init = ne2k_init_device,
1064 .deinit = ne2k_deinit_device,
1065 .reset = ne2k_reset_device,
1066 .start = ne2k_start_device,
1067 .stop = ne2k_stop_device,
1071 struct vm_device *v3_create_ne2k(struct vm_device *pci)
1073 struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
1075 memset(nic_state, 0, sizeof(struct ne2k_context));
1077 PrintDebug("NE2K internal at %p\n", (void *)nic_state);
1079 nic_state->pci = pci;
1081 struct vm_device *device = v3_create_device("NE2K", &dev_ops, nic_state);