Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Update virtual NE2000
[palacios.git] / palacios / src / devices / ne2k.c
1 /*
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu> 
11  * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Lei Xia <lxia@northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19  
20 /*
21 * Virtual NE2K Network Card 
22 */
23
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>
31
32 #ifndef DEBUG_NE2K
33 #undef PrintDebug
34 #define PrintDebug(fmts, args...)
35 #endif
36
37 //#define TEST_PERFORMANCE 0
38
39 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
40
41 struct ne2k_context{
42     struct guest_info *vm;
43     nic_state_t dev_state;
44
45     struct ne2k_regs regs;
46     uchar_t mac[6];
47     uchar_t mem[NE2K_MEM_SIZE];
48     struct pci_device *pci_dev;
49     struct vm_device *pci;
50 };
51
52 #define NUM_NE2K 10
53
54 struct vm_device *ne2ks[NUM_NE2K];      //the array of virtual network cards
55
56 static int nic_no = 0;
57
58 #if TEST_PERFORMANCE
59 static uint32_t exit_num = 0;
60 static uint32_t int_num = 0; 
61 #endif
62
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; \
70         })
71
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));
74
75 #ifdef DEBUG_NE2K
76 static void dump_state(struct vm_device *dev)
77 {
78   int i;
79   uchar_t *p;
80   struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
81
82   PrintDebug("====NE2000: Dumping state Begin ==========\n");
83   PrintDebug("Registers:\n");
84
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]);    
88   
89   PrintDebug("Memory:\n");      
90   for(i = 0; i < 32; i++)
91         PrintDebug("0x%02x ", nic_state->mem[i]);
92   PrintDebug("\n");
93   PrintDebug("====NE2000: Dumping state End==========\n");
94 }
95 #endif
96
97 #if 0
98 //no-pci version
99 static void ne2k_update_irq(struct vm_device *dev)
100 {
101     int isr;
102     struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
103     struct guest_info *guest = dev->vm;
104         
105     isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0x7f);
106
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);
110     }   
111 }
112
113 #endif
114
115 #if 1
116 //pci version
117 static void ne2k_update_irq(struct vm_device *dev)
118 {
119     int isr;
120     struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
121     struct pci_device *pdev = nic_state->pci_dev;
122     int irqline = 0;
123
124     if (pdev == NULL){
125                 PrintDebug("Ne2k: Device %p is not attached to any PCI Bus\n", nic_state);
126                 irqline = NE2K_DEF_IRQ;
127     } else {
128                 irqline = pdev->config_header.intr_line;
129     }
130         
131     isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0x7f);
132     
133     if (irqline == 0){
134                 PrintError("Ne2k: IRQ_LINE: %d\n", irqline);
135                 return;
136     }
137
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);
140
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);
144
145         #if TEST_PERFORMANCE
146         if ((++int_num) % 50 == 0)
147              PrintError("Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
148         #endif
149     }   
150 }
151
152 #endif
153
154 static void init_ne2k_context(struct vm_device *dev)
155 {
156     struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
157     int i;
158     uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, (0x60 + nic_no)};
159
160     nic_state->vm = dev->vm;
161
162     nic_state->regs.isr = ENISR_RESET;
163     nic_state->regs.imr = 0x00;
164     nic_state->regs.cmd = 0x22;
165
166     for (i = 0; i < 5; i++)
167         nic_state->regs.macaddr[i] = nic_state->mac[i] = mac[i];
168
169     nic_state->regs.macaddr[5] = nic_state->mac[5] = mac[5] + nic_no;
170
171     for (i = 0; i < 8; i++)
172          nic_state->regs.mult[i] = 0xff;
173
174     for(i = 0; i < 32; i++) {
175         nic_state->mem[i] = 0xff;
176     }
177
178     memcpy(nic_state->mem, nic_state->mac, 6);
179     nic_state->mem[14] = 0x57;
180     nic_state->mem[15] = 0x57;
181
182 #ifdef DEBUG_NE2K
183     dump_state(dev);
184 #endif
185
186 }
187
188 static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length)
189 {
190     int i;
191   
192     PrintDebug("\nNe2k: Sending Packet\n");
193
194     for (i = 0; i<length; i++)
195             PrintDebug("%x ",pkt[i]);
196     PrintDebug("\n");
197         
198     return V3_Send_pkt(pkt, length);
199 }
200
201 //TODO: Support Broadcast and Multicast 
202 static struct vm_device * get_rx_dev(uchar_t *dst_mac)
203 {
204     struct ne2k_context *nic_state;
205     struct ne2k_regs *nregs;
206     int i;
207
208     static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
209
210     for (i = 0; i < NUM_NE2K; i++){
211                 if (ne2ks[i] != NULL) {
212                         nic_state = (struct ne2k_context *)ne2ks[i]->private_data;
213                         nregs = &(nic_state->regs);
214                         
215                         if (nregs->rcr & 0x10) {//broadcast packets, not correct here
216                                  return ne2ks[i];   
217                         } else {
218                          if (compare_mac(dst_mac,  brocast_mac) && (nregs->rcr & 0x04)) //broadcast address
219                                                 return ne2ks[i];
220                                  if (dst_mac[0] & 0x01) {
221                                     // multicast packet, not done here
222                                     // ==========
223                                     if (nregs->rcr & 0x08)
224                                                 return ne2ks[i];
225                                  } 
226                                 if (compare_mac(dst_mac, nic_state->mac))
227                                                 return ne2ks[i];   
228                       }
229                }
230     }
231
232     return NULL;
233 }
234
235 static int ne2k_rxbuf_full(struct vm_device *dev)
236 {
237     int empty, index, boundary;
238     struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
239
240     index = nic_state->regs.curpag << 8;
241     boundary = nic_state->regs.boundary << 8;
242     if (index < boundary)
243         empty = boundary - index;
244     else
245         empty = ((nic_state->regs.pgstop - nic_state->regs.pgstart) << 8) - (index - boundary);
246         
247     if (empty < (MAX_ETH_FRAME_SIZE + 4))
248         return 1;
249         
250     return 0;
251 }
252
253 #define MIN_BUF_SIZE 60
254
255 static void ne2k_receive(struct vm_device *dev, const uchar_t *pkt, int length)
256 {
257     struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
258     struct ne2k_regs *nregs = &(nic_state->regs);
259     uchar_t *p;
260     uint32_t total_len, next, len, index, empty;
261     uchar_t buf[60];
262     uint32_t start, stop;
263
264     start = nregs->pgstart << 8;
265     stop = nregs->pgstop << 8;
266    
267     if (nregs->cmd & NE2K_STOP)
268          return;
269
270     if (ne2k_rxbuf_full(dev)){
271          PrintError("Ne2k: received buffer overflow\n");
272         return;
273     }
274
275     //packet too small, expand it
276     if (length < MIN_BUF_SIZE) {
277         memcpy(buf, pkt, length);
278         memset(buf + length, 0, MIN_BUF_SIZE - length);
279         pkt = buf;
280         length = MIN_BUF_SIZE;
281     }
282
283     index = nregs->curpag << 8;
284     //header, 4 bytes
285     total_len = length + 4;
286     //address for next packet (4 bytes for CRC)
287     next = index + ((total_len + 4 + 255) & ~0xff);
288     if (next >= stop)
289         next -= stop - start;
290
291     p = nic_state->mem + index;
292     nregs->rsr = ENRSR_RXOK;
293
294     if (pkt[0] & 0x01)
295         nregs->rsr |= ENRSR_PHY;
296         
297     p[0] = nregs->rsr;
298     p[1] = next >> 8;
299     p[2] = total_len;
300     p[3] = total_len >> 8;
301     index += 4;
302
303     while (length > 0) {
304         if (index <= stop)
305             empty = stop - index;
306         else
307             empty = 0;
308         len = length;
309         if (len > empty)
310             len = empty;
311         memcpy(nic_state->mem + index, pkt, len);
312         pkt += len;
313         index += len;
314         if (index == stop)
315             index = start;
316         length -= len;
317     }
318     nregs->curpag = next >> 8;
319
320     nregs->isr |= ENISR_RX;
321     ne2k_update_irq(dev);
322 }
323
324 static int ne2k_hook_iospace(struct vm_device *vmdev, addr_t base_addr, int size, int type, void *data);
325
326 static struct pci_device * pci_ne2k_init(struct vm_device *vmdev, 
327                                 struct vm_device *pci,  
328                                 int bus_no, 
329                                 int dev_num,
330                                 int fn_num,
331                                 int (*io_read)(ushort_t port, void * dst, uint_t length, struct vm_device * dev),
332                                 int (*io_write)(ushort_t port, void * src, uint_t length, struct vm_device * dev))
333 {
334     uchar_t *pci_conf;
335     struct pci_device *pdev;
336     struct v3_pci_bar ne2k_bar;
337
338     ne2k_bar.type = PCI_BAR_IO;
339     ne2k_bar.num_ports = 0x100;
340     ne2k_bar.default_base_port = 0xc100;
341     ne2k_bar.io_read = io_read;
342     ne2k_bar.io_write = io_write;
343   
344     pdev = v3_pci_register_device(vmdev, 
345                                                                 PCI_STD_DEVICE, 
346                                                                 bus_no, 
347                                                                 dev_num, 
348                                                                 fn_num,
349                                                                 "NE2000", 
350                                                                 &ne2k_bar, 
351                                                                 NULL, NULL, NULL, vmdev);
352
353     if (pdev == NULL){
354        PrintError("NIC: Register to PCI bus failed\n");
355         return NULL;
356     }
357
358     pci_conf = pdev->config_space;
359         
360     pci_conf[0x00] = 0xec; // Realtek 8029
361     pci_conf[0x01] = 0x10;
362     pci_conf[0x02] = 0x29;
363     pci_conf[0x03] = 0x80;
364     pci_conf[0x0a] = 0x00; // ethernet network controller
365     pci_conf[0x0b] = 0x02;
366     pci_conf[0x0e] = 0x00; // header_type
367     pci_conf[0x3d] = 1; // interrupt pin 0
368     pci_conf[0x3c] = 11;
369
370     pdev->vm_dev = vmdev;
371     
372     return pdev;
373 }
374
375 static int netif_input(uchar_t * pkt, uint_t size)
376 {
377   uint_t i;
378   struct vm_device *dev;
379   
380   PrintDebug("\nNe2k: Packet Received:\nSource:");
381   for (i = 6; i < 12; i++) {
382         PrintDebug("%x ", pkt[i]);
383   }
384
385   dev = get_rx_dev(pkt); //TODO: handle multiple destination packets
386
387   if (dev == NULL) 
388         return 0;
389
390   PrintDebug("\n");
391   for(i= 0; i<size; i++)
392         PrintDebug("%x ", pkt[i]);
393   
394   ne2k_receive(dev, pkt, size);
395
396   return 0;
397 }
398
399
400 static inline uint16_t cpu2le16(uint16_t val)
401 {
402     uint16_t p;
403     uchar_t *p1 = (uchar_t *)&p;
404
405     p1[0] = val;
406     p1[1] = val >> 8;
407
408     return p;
409 }
410
411
412 static inline uint32_t cpu2le32(uint32_t val)
413 {
414     uint32_t p;
415     uchar_t *p1 = (uchar_t *)&p;
416
417     p1[0] = val;
418     p1[1] = val >> 8;
419     p1[2] = val >> 16;
420     p1[3] = val >> 24;
421
422     return p;
423 }
424
425 static inline uint16_t le16_to_cpu(const uint16_t *p)
426 {
427     const uchar_t *p1 = (const uchar_t *)p;
428     return p1[0] | (p1[1] << 8);
429 }
430
431 static inline uint32_t le32_to_cpu(const uint32_t *p)
432 {
433     const uchar_t *p1 = (const uchar_t *)p;
434     return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
435 }
436
437 static void 
438 ne2k_mem_writeb(struct ne2k_context *nic_state, 
439                         uint32_t addr,
440                         uint32_t val)
441 {
442     uchar_t tmp;
443
444     tmp = (uchar_t) (val & 0x000000ff);
445     if (addr < 32 || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
446         nic_state->mem[addr] = tmp;
447     }
448
449     PrintDebug("wmem addr: %x val: %x\n", addr, val);
450 }
451
452 static void 
453 ne2k_mem_writew(struct ne2k_context *nic_state, 
454                         uint32_t addr,
455                         uint32_t val)
456 {
457     addr &= ~1; //XXX: check exact behaviour if not even
458     if (addr < 32 ||
459         (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
460         *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
461     }
462
463     PrintDebug("wmem addr: %x val: %x\n", addr, val);
464 }
465
466 static void 
467 ne2k_mem_writel(struct ne2k_context *nic_state,
468                         uint32_t addr,
469                         uint32_t val)
470 {
471     addr &= ~1; // XXX: check exact behaviour if not even
472     if (addr < 32 ||
473         (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
474         *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
475     }
476
477     PrintDebug("wmem addr: %x val: %x\n", addr, val);
478 }
479
480 static uchar_t 
481 ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr)
482 {
483     PrintDebug("rmem addr: %x\n", addr);
484         
485     if (addr < 32 ||
486         (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
487         return nic_state->mem[addr];
488     } else {
489         return 0xff;
490     }
491 }
492
493 static ushort_t
494 ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr)
495 {
496     PrintDebug("rmem addr: %x\n", addr);
497         
498     addr &= ~1; //XXX: check exact behaviour if not even 
499     if (addr < 32 ||
500         (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
501         return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
502     } else {
503         return 0xffff;
504     }
505 }
506
507 static uint32_t 
508 ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr)
509 {
510     PrintDebug("rmem addr: %x\n", addr);
511
512     addr &= ~1; //XXX: check exact behaviour if not even
513     if (addr < 32 ||
514         (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
515         return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
516     } else {
517         return 0xffffffff;
518     }
519 }
520
521 static void 
522 ne2k_dma_update(struct vm_device *dev, int len)
523 {               
524     struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
525         
526     nic_state->regs.rsar += len;
527     // wrap
528     if (nic_state->regs.rsar == nic_state->regs.pgstop)
529         nic_state->regs.rsar = nic_state->regs.pgstart;
530
531     if (nic_state->regs.rbcr <= len) {
532         nic_state->regs.rbcr = 0;
533         nic_state->regs.isr |= ENISR_RDC;
534         ne2k_update_irq(dev);
535     } else {
536         nic_state->regs.rbcr -= len;
537     }
538 }
539
540
541 //for data port read/write
542 static int ne2k_data_read(ushort_t port,
543                         void * dst,
544                         uint_t length,
545                         struct vm_device *dev)
546 {
547         uint32_t val;
548         struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
549
550        // current dma address
551         uint32_t addr = nic_state->regs.rsar;
552
553         switch(length){
554                 case 1:
555                         val = ne2k_mem_readb(nic_state, addr);
556                         break;
557                 case 2:
558                         val = ne2k_mem_readw(nic_state, addr);
559                         break;
560                 case 4:
561                         val = ne2k_mem_readl(nic_state, addr);
562                         break;
563                 default:
564                         PrintError("ne2k_data_read error: invalid length %d\n", length);
565                         val = 0x0;
566         }
567
568        ne2k_dma_update(dev, length);
569
570         memcpy(dst, &val, length);
571
572         PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f,length, val);
573
574         #if TEST_PERFORMANCE
575        if ((++exit_num) % 50 == 0)
576         PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
577        #endif
578
579         return length;
580 }
581
582 static int ne2k_data_write(ushort_t port,
583                                                         void * src,
584                                                         uint_t length,
585                                                         struct vm_device *dev)
586 {
587         uint32_t val;
588         struct ne2k_context *nic_state = (struct ne2k_context *)dev->private_data;
589
590         if (nic_state->regs.rbcr == 0)
591                 return length;
592
593         memcpy(&val, src, length);
594
595         uint32_t addr = nic_state->regs.rsar;
596         
597         switch (length){
598                 case 1:
599                         ne2k_mem_writeb(nic_state, addr, val);
600                         break;
601                 case 2:
602                         ne2k_mem_writew(nic_state, addr, val);
603                         break;
604                 case 4:
605                         ne2k_mem_writel(nic_state, addr, val);
606                         break;
607                 default:
608                         PrintError("nic_data_write error: invalid length %d\n", length);
609                 }
610         
611         ne2k_dma_update(dev, length);
612
613         PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f,length, val);
614
615         #if TEST_PERFORMANCE
616        if ((++exit_num) % 50 == 0)
617                 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
618        #endif
619                         
620         return length;
621 }
622
623 static int ne2k_reset_device(struct vm_device * dev)
624 {
625   
626   PrintDebug("vnic: reset device\n");
627
628   init_ne2k_context(dev);
629
630   return 0;
631 }
632
633
634 //for 0xc11f port
635 static int ne2k_reset_port_read(ushort_t port,
636                                                         void * dst,
637                                                         uint_t length,
638                                                        struct vm_device *dev)
639 {
640         uint32_t val = 0x0;
641
642         memcpy(dst, &val, length);
643
644         PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x\n", port,length, val);
645
646         ne2k_reset_device(dev);
647
648         #if TEST_PERFORMANCE
649        if ((++exit_num) % 50 == 0)
650                 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
651        #endif
652
653         return length;
654 }
655
656 static int ne2k_reset_port_write(ushort_t port,
657                                                         void * src,
658                                                         uint_t length,
659                                                         struct vm_device *dev)
660 {
661         uint32_t val;
662
663         memcpy(&val, src, length);
664
665         PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port,length, val);
666
667         #if TEST_PERFORMANCE
668        if ((++exit_num) % 50 == 0)
669                 PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
670        #endif
671                         
672         return length;
673 }
674
675 static int ne2k_ioport_write(ushort_t port,
676                         void * src,
677                         uint_t length,
678                         struct vm_device *dev)
679 {
680     uchar_t  page;
681     struct ne2k_context *nic_state = (struct ne2k_context* )dev->private_data;
682     uchar_t val;
683     int index;
684         
685     if (length == 1) {
686           memcpy(&val, src, 1);
687     } else {
688           PrintError("ne2k_write error: length %d\n", length);  
689           return length;
690     }
691
692     PrintDebug("ne2k_write: port:0x%x  val: 0x%x\n", port, (int)val);
693         
694     port &= 0x1f;
695
696     if (port == 0x10)
697                 return ne2k_data_write(port, src, length, dev);
698
699     if (port == 0x1f)
700                 return ne2k_reset_port_write(port, src, length, dev);
701                 
702     if (port == EN0_COMMAND) {
703         nic_state->regs.cmd = val;
704         if (!(val & NE2K_STOP)) {
705             nic_state->regs.isr &= ~ENISR_RESET; 
706             if ((val & (NE2K_DMAREAD | NE2K_DMAWRITE)) &&
707                         nic_state->regs.rbcr == 0) {
708                 nic_state->regs.isr |= ENISR_RDC;
709                 ne2k_update_irq(dev);
710             }
711             if (val & NE2K_TRANSMIT) {
712                 index = (nic_state->regs.tpsr << 8);
713                 if (index >= NE2K_PMEM_END)
714                     index -= NE2K_PMEM_SIZE;
715                 if (index + nic_state->regs.tbcr <= NE2K_PMEM_END) {
716                     ne2k_send_packet(dev, nic_state->mem + index, nic_state->regs.tbcr);
717                 }
718                 nic_state->regs.tsr = ENTSR_PTX;
719                 nic_state->regs.isr |= ENISR_TX;
720                 nic_state->regs.cmd &= ~NE2K_TRANSMIT;
721                 ne2k_update_irq(dev);
722             }
723         }
724     } else {
725         page = nic_state->regs.cmd >> 6;
726         if(page == 0){
727                 switch(port) {
728                         case EN0_STARTPG:
729                             nic_state->regs.pgstart = val;
730                             break;
731                         case EN0_STOPPG:
732                             nic_state->regs.pgstop = val;
733                             break;
734                         case EN0_BOUNDARY:
735                             nic_state->regs.boundary = val;
736                             break;
737                          case EN0_TPSR:
738                             nic_state->regs.tpsr = val;
739                             break;
740                          case EN0_TCNTLO:
741                             nic_state->regs.tbcr = (nic_state->regs.tbcr & 0xff00) | val;
742                             break;
743                         case EN0_TCNTHI:
744                             nic_state->regs.tbcr = (nic_state->regs.tbcr & 0x00ff) | (val << 8);
745                             break;
746                          case EN0_ISR:
747                             nic_state->regs.isr &= ~(val & 0x7f);
748                             ne2k_update_irq(dev);
749                             break;
750                          case EN0_RSARLO:
751                             nic_state->regs.rsar = (nic_state->regs.rsar & 0xff00) | val;
752                             break;
753                         case EN0_RSARHI:
754                             nic_state->regs.rsar = (nic_state->regs.rsar & 0x00ff) | (val << 8);
755                             break;
756                          case EN0_RCNTLO:
757                             nic_state->regs.rbcr = (nic_state->regs.rbcr & 0xff00) | val;
758                             break;
759                         case EN0_RCNTHI:
760                             nic_state->regs.rbcr = (nic_state->regs.rbcr & 0x00ff) | (val << 8);
761                             break;
762                         case EN0_RXCR:
763                             nic_state->regs.rcr = val;
764                             break;
765                          case EN0_TXCR:
766                              nic_state->regs.tcr = val;
767                         case EN0_DCFG:
768                             nic_state->regs.dcr = val;
769                             break;      
770                         case EN0_IMR:
771                             nic_state->regs.imr = val;
772                              //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
773                             ne2k_update_irq(dev);
774                             break;
775                          default:
776                              PrintError("ne2k_write error: invalid port:0x%x\n", port);
777                              break;
778                         }
779                 }
780          if(page == 1){
781                 switch(port) {
782                         case EN1_PHYS ... EN1_PHYS + 5:
783                             nic_state->regs.phys[port - EN1_PHYS] = val;
784                             break;
785                         case EN1_CURPAG:
786                             nic_state->regs.curpag = val;
787                             break;
788                         case EN1_MULT ... EN1_MULT + 7:
789                             // PrintError("ne2k_write error: write EN_MULT:0x%x\n", (int)val);
790                             nic_state->regs.mult[port - EN1_MULT] = val;
791                             break;
792                          default:
793                              PrintError("ne2k_write error: invalid port:0x%x\n", port);
794                              break;
795                         }
796                 }
797         if(page == 2){
798                 switch(port) {
799                          case EN2_LDMA0:
800                             nic_state->regs.clda = (nic_state->regs.clda & 0xff00) | val;
801                             break;
802                          case EN2_LDMA1:
803                             nic_state->regs.clda = (nic_state->regs.clda & 0x00ff) | (val << 8);
804                             break;
805                          case EN2_RNPR:
806                             nic_state->regs.rnpp = val;
807                             break;
808                          case EN2_LNRP:
809                             nic_state->regs.lnpp = val;
810                             break;
811                          case EN2_ACNT0:
812                             nic_state->regs.addcnt = (nic_state->regs.addcnt & 0xff00) | val;
813                             break;
814                          case EN2_ACNT1: 
815                             nic_state->regs.addcnt = (nic_state->regs.addcnt & 0x00ff) | (val << 8);
816                             break;
817                          default:
818                             PrintError("ne2k_write error: invalid port:0x%x\n", port);
819                             break;
820                         }
821                 }
822     }
823
824     #if TEST_PERFORMANCE
825     if ((++exit_num) % 50 == 0)
826         PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
827     #endif
828
829     return length;
830         
831 }
832
833 static int ne2k_ioport_read(ushort_t port,
834                         void * dst,
835                         uint_t length,
836                         struct vm_device *dev)
837 {
838     uchar_t page, ret, offset;
839
840     struct ne2k_context *nic_state = (struct ne2k_context* )dev->private_data;
841
842     if (length > 1) {
843            PrintError("ne2k_read error: length %d\n", length);
844            return length;
845     }
846
847     offset = port;
848     port &= 0x1f;
849
850     if (port == 0x10)
851                 return ne2k_data_read(port, dst, length, dev);
852
853     if (port == 0x1f)
854                 return ne2k_reset_port_read(port, dst, length, dev);
855
856     if (port == EN0_COMMAND) {
857         ret = nic_state->regs.cmd;
858     } else {
859         page = nic_state->regs.cmd >> 6;
860         if (page == 0){
861             switch(port) {              
862                  case EN0_CLDALO:
863                     ret = nic_state->regs.clda & 0x00ff;
864                     break;
865                 case EN0_CLDAHI:
866                     ret = (nic_state->regs.clda & 0xff00) >> 8;
867                     break;
868                 case EN0_BOUNDARY:
869                     ret = nic_state->regs.boundary;
870                     break;
871                  case EN0_TSR:
872                     ret = nic_state->regs.tsr;
873                     break;
874                  case EN0_NCR:
875                     ret = nic_state->regs.ncr;
876                     break;
877                 case EN0_FIFO:
878                     ret = nic_state->regs.fifo;
879                     break;
880                  case EN0_ISR:
881                     ret = nic_state->regs.isr;
882                     ne2k_update_irq(dev);
883                     break;
884                  case EN0_CRDALO:
885                     ret = nic_state->regs.crda & 0x00ff;
886                     break;
887                 case EN0_CRDAHI:
888                     ret = (nic_state->regs.crda & 0xff00) >> 8;
889                     break;
890                 case EN0_RSR:
891                     ret = nic_state->regs.rsr;
892                     break;
893                  case EN0_COUNTER0:
894                      ret = nic_state->regs.cntr & 0x000000ff;
895                      break;
896                 case EN0_COUNTER1:
897                     ret = (nic_state->regs.cntr & 0x0000ff00) >> 8;
898                      break;     
899                 case EN0_COUNTER2:
900                     ret = (nic_state->regs.cntr & 0x00ff0000) >> 16;
901                      break;
902                  default:
903                      PrintError("ne2k_read error: invalid port:0x%x\n", port);
904                      ret = 0x00;
905                      break;
906            }
907         }
908          if (page == 1){
909            switch(port) {
910                 case EN1_PHYS ... EN1_PHYS + 5:
911                     ret = nic_state->regs.phys[port - EN1_PHYS];
912                     break;
913                 case EN1_CURPAG:
914                     ret = nic_state->regs.curpag;
915                     break;
916                 case EN1_MULT ... EN1_MULT + 7:
917                     ret = nic_state->regs.mult[port - EN1_MULT];
918                     break;
919                  default:
920                      PrintError("ne2k_read error: invalid port:0x%x\n", port);
921                      ret = 0x00;
922                      break;
923            }
924          }
925          if (page == 2){
926            switch(port) {
927                  case EN2_STARTPG:
928                     ret = nic_state->regs.pgstart;
929                     break;
930                  case EN2_STOPPG:
931                     ret = nic_state->regs.pgstop;
932                     break;
933                  case EN2_RNPR:
934                     ret = nic_state->regs.rnpp;
935                     break;
936                  case EN2_LNRP:
937                     ret = nic_state->regs.lnpp;
938                     break;
939                  case EN2_TPSR:
940                     ret = nic_state->regs.tpsr;
941                     break;
942                  case EN2_ACNT0:
943                     ret = nic_state->regs.addcnt & 0x00ff;
944                     break;
945                  case EN2_ACNT1: 
946                     ret = (nic_state->regs.addcnt & 0xff00) >> 8;
947                     break;
948                  case EN2_RCR:
949                     ret = nic_state->regs.rcr;
950                     break;
951                  case EN2_TCR:
952                     ret = nic_state->regs.tcr;
953                     break;
954                  case EN2_DCR:
955                     ret = nic_state->regs.dcr;
956                     break;
957                  case EN2_IMR:
958                     ret = nic_state->regs.imr;
959                     break;
960                  default:
961                     PrintError("ne2k_read error: invalid port:0x%x\n", port);
962                     ret = 0x00;
963                     break;
964            }
965          }
966     }
967
968     memcpy(dst, &ret, 1);
969
970     PrintDebug("ne2k_read: port:0x%x  val: 0x%x\n", offset, (int)ret);
971
972     #if TEST_PERFORMANCE
973     if ((++exit_num) % 50 == 0)
974         PrintError("Ne2k-Ne2k: Total Exit: %d, INT: %d\n", (int)exit_num, int_num);
975     #endif
976
977     return length;
978
979 }
980
981
982 static int ne2k_start_device(struct vm_device *dev)
983 {
984   PrintDebug("vnic: start device\n");
985   
986   return 0;
987 }
988
989
990 static int ne2k_stop_device(struct vm_device *dev)
991 {
992   PrintDebug("vnic: stop device\n");
993   
994   return 0;
995 }
996
997 static void  init_global_setting()
998 {       
999   int i;
1000   
1001   V3_Register_pkt_event(&netif_input);
1002   
1003   for (i = 0; i < NUM_NE2K; i++)
1004         ne2ks[i] = NULL;
1005
1006 }
1007
1008 static int ne2k_hook_iospace(struct vm_device *vmdev, addr_t base_addr, int size, int type, void *data)
1009 {
1010   int i;
1011
1012   if (base_addr <= 0)
1013         return -1;
1014
1015   PrintDebug("In NIC%d: Hook IO space starting from %x\n", nic_no, (int) base_addr);
1016
1017   for (i = 0; i < 16; i++){     
1018         v3_dev_hook_io(vmdev, base_addr + i, &ne2k_ioport_read, &ne2k_ioport_write);
1019   }
1020   v3_dev_hook_io(vmdev, base_addr + NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
1021   v3_dev_hook_io(vmdev, base_addr + NIC_RESET_PORT, &ne2k_reset_port_read, &ne2k_reset_port_write);
1022
1023   return 0;
1024
1025 }
1026
1027 static int ne2k_init_device(struct vm_device * vmdev) 
1028 {
1029   struct vm_device *pci = NULL;
1030   struct pci_device *pdev = NULL;
1031   struct ne2k_context *nic_state = (struct ne2k_context *)vmdev->private_data;
1032
1033   PrintDebug("ne2k%d: init_device\n",  nic_no);
1034
1035   if (nic_no == 0) // only initiate once
1036         init_global_setting();
1037
1038   init_ne2k_context(vmdev);
1039
1040   pci = nic_state->pci;
1041
1042   if (pci != NULL) {
1043         PrintDebug("Ne2k: attach ne2k to the pci %p\n", pci);
1044        pdev = pci_ne2k_init(vmdev, pci, 0, -1, 0,  &ne2k_ioport_read, &ne2k_ioport_write);
1045         if (pdev == NULL)
1046                 PrintError("Ne2k: initiate failure, failure to attach ne2k to the bus %p\n", pci);
1047   } else {
1048         PrintError("Ne2k: Failure to initiate Ne2k , no pci\n");
1049         ne2k_hook_iospace(vmdev, NE2K_DEF_BASE_ADDR, 100, 0, NULL);
1050   }
1051
1052   nic_state->pci_dev = pdev;  
1053   ne2ks[nic_no ++] = vmdev;
1054
1055   #ifdef DEBUG_NE2K
1056   dump_state(vmdev);
1057   #endif
1058
1059   return 0;
1060 }
1061
1062
1063
1064 static int ne2k_deinit_device(struct vm_device *vmdev)
1065 {
1066   int i;
1067   
1068   for (i = 0; i<16; i++){               
1069         v3_dev_unhook_io(vmdev, NE2K_DEF_BASE_ADDR + i);
1070   }
1071
1072   v3_dev_unhook_io(vmdev, NE2K_DEF_BASE_ADDR + NIC_DATA_PORT);
1073   v3_dev_unhook_io(vmdev, NE2K_DEF_BASE_ADDR + NIC_RESET_PORT);
1074   
1075   return 0;
1076 }
1077
1078
1079 static struct vm_device_ops dev_ops = { 
1080   .init = ne2k_init_device, 
1081   .deinit = ne2k_deinit_device,
1082   .reset = ne2k_reset_device,
1083   .start = ne2k_start_device,
1084   .stop = ne2k_stop_device,
1085 };
1086
1087
1088 struct vm_device *v3_create_ne2k(struct vm_device *pci) 
1089 {
1090   struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
1091
1092   memset(nic_state, 0, sizeof(struct ne2k_context));
1093
1094   PrintDebug("NE2K internal at %p\n", (void *)nic_state);
1095
1096   nic_state->pci = pci;
1097
1098   struct vm_device *device = v3_create_device("NE2K", &dev_ops, nic_state);
1099
1100   return device;
1101 }
1102