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.


9df08716f92acec460746f4b00f81d89533dd0cd
[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 CONFIG_DEBUG_NE2K
33 #undef PrintDebug
34 #define PrintDebug(fmts, args...)
35 #endif
36
37
38
39
40 #define NE2K_DEFAULT_IRQ        11
41
42 #define MAX_ETH_FRAME_SIZE      1514
43
44
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
50
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
54
55 // Page 0 registers
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 
84
85 //Page 1 registers
86 #define EN1_PHYS                0x01
87 #define EN1_CURPAG              0x07
88 #define EN1_MULT                0x08
89
90 //Page 2 registers
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 
104
105 //Page 3 registers
106 #define EN3_CONFIG0             0x03
107 #define EN3_CONFIG1             0x04
108 #define EN3_CONFIG2             0x05
109 #define EN3_CONFIG3             0x06
110
111
112
113 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
114
115 struct cmd_reg {
116     union {
117         uint8_t val;
118         struct {
119             uint8_t stop        : 1;
120             uint8_t start       : 1;
121             uint8_t tx_pkt      : 1;
122             uint8_t rem_dma_cmd : 3; // 0=Not allowed, 1=Read, 2=Write, 3=Send Pkt, 4=Abort/Complete DMA
123             uint8_t pg_sel      : 2;
124         } __attribute__((packed));
125     } __attribute__((packed));
126 } __attribute__((packed));
127
128
129 struct intr_status_reg {
130     union {
131         uint8_t val;
132         struct {
133             uint8_t pkt_rx          : 1;
134             uint8_t pkt_tx          : 1;
135             uint8_t rx_err          : 1;
136             uint8_t tx_err          : 1;
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));
144
145
146 struct intr_mask_reg {
147     union {
148         uint8_t val;
149         struct {
150             uint8_t pkt_rx          : 1;
151             uint8_t pkt_tx          : 1;
152             uint8_t rx_err          : 1;
153             uint8_t tx_err          : 1;
154             uint8_t overwrite_warn  : 1;
155             uint8_t cnt_overflow    : 1;
156             uint8_t rem_dma_done    : 1;
157             uint8_t rsvd            : 1;
158         } __attribute__((packed));
159     } __attribute__((packed));
160 } __attribute__((packed));
161
162
163 struct data_cfg_reg {
164     union {
165         uint8_t val;
166         struct {
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;
173             uint8_t rsvd             : 1;
174         } __attribute__((packed));
175     } __attribute__((packed));
176 } __attribute__((packed));
177
178
179 struct tx_cfg_reg { 
180     union {
181         uint8_t val;
182         struct {
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;
187             uint8_t rsvd            : 3;
188         } __attribute__((packed));
189     } __attribute__((packed));
190 } __attribute__((packed));
191
192 struct tx_status_reg { 
193     union {
194         uint8_t val;
195         struct {
196             uint8_t pkt_tx_ok       : 1;
197             uint8_t rsvd            : 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));
207
208 struct rx_cfg_reg { 
209     union {
210         uint8_t val;
211         struct {
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;
218             uint8_t rsvd             : 2;
219         } __attribute__((packed));
220     } __attribute__((packed));
221 } __attribute__((packed));
222
223
224 struct rx_status_reg { 
225     union {
226         uint8_t val;
227         struct {
228             uint8_t pkt_rx_ok        : 1;
229             uint8_t crc_err          : 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));
239
240
241 struct ne2k_context {
242     struct guest_info * vm;
243
244     nic_state_t dev_state;
245
246     // Registers
247     struct cmd_reg cmd;
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;  
255
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...
262
263     uint8_t      curpag;       // current page
264     uint8_t      rnpp;         // rem next pkt ptr
265     uint8_t      lnpp;         // local next pkt ptr
266
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)
270
271     union {                    // current local DMA Addr
272         uint16_t     clda;
273         struct {
274             uint8_t clda0;
275             uint8_t clda1;
276         } __attribute__((packed));
277     } __attribute__((packed));
278
279
280     union {                   // current remote DMA addr
281         uint16_t     crda;
282         struct {
283             uint8_t crda0;
284             uint8_t crda1;
285         } __attribute__((packed));
286     } __attribute__((packed));
287
288
289     union {                   // Remote Start Addr Reg
290         uint16_t     rsar;
291         struct {
292             uint8_t rsar0;
293             uint8_t rsar1;
294         } __attribute__((packed));
295     } __attribute__((packed));
296
297
298     union {                    // TX Byte count Reg
299         uint16_t     tbcr;
300         struct {
301             uint8_t tbcr0;
302             uint8_t tbcr1;
303         } __attribute__((packed));
304     } __attribute__((packed));
305
306     union {                    // Remote Byte count Reg
307         uint16_t     rbcr;
308         struct {
309             uint8_t rbcr0;
310             uint8_t rbcr1;
311         } __attribute__((packed));
312     } __attribute__((packed));
313
314
315
316     union {                    // Address counter?
317         uint16_t     addcnt;
318         struct {
319             uint8_t addcnt0;
320             uint8_t addcnt1;
321         } __attribute__((packed));
322     } __attribute__((packed));
323
324
325     uint8_t      mcast_addr[8];  // multicast mask array 
326     uint8_t      mac_addr[6];    // MAC Addr
327
328     uint8_t mem[NE2K_MEM_SIZE];
329
330     struct pci_device * pci_dev;
331     struct vm_device * pci_bus;
332 };
333
334 #define compare_mac(src, dst) !memcmp(src, dst, 6)
335
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;
339     int i;
340
341
342     PrintDebug("====NE2000: Dumping state Begin ==========\n");
343     PrintDebug("Registers:\n");
344
345     // JRL: Dump Registers
346
347     PrintDebug("Memory:\n");    
348
349     for(i = 0; i < 32; i++) {
350         PrintDebug("0x%02x ", nic_state->mem[i]);
351     } 
352
353     PrintDebug("\n");
354     PrintDebug("====NE2000: Dumping state End==========\n");
355 }
356 #endif
357
358
359
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;
363     int irq_line = 0;
364
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;
368     } else {
369         irq_line = pdev->config_header.intr_line;
370     }
371             
372     if (irq_line == 0){
373         PrintError("Ne2k: IRQ_LINE: %d\n", irq_line);
374         return -1;
375     }
376
377     PrintDebug("ne2k_update_irq: irq_line: %d\n", irq_line);
378
379
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);
385     }
386
387     return 0;
388 }
389
390
391
392 static void ne2k_init_state(struct vm_device * dev) {
393     struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
394     int i;
395     uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, 0x60};
396
397     nic_state->vm = dev->vm;
398
399     nic_state->isr.reset = 1;
400     nic_state->imr.val = 0x00;
401     nic_state->cmd.val = 0x22;
402
403     for (i = 0; i < 5; i++) {
404         nic_state->mac_addr[i] = mac[i];
405     }
406
407     memset(nic_state->mcast_addr, 0xff, sizeof(nic_state->mcast_addr));
408
409     // Not sure what this is about....
410     memset(nic_state->mem, 0xff, 32); 
411
412     memcpy(nic_state->mem, nic_state->mac_addr, 6);
413     nic_state->mem[14] = 0x57;
414     nic_state->mem[15] = 0x57;
415
416 #ifdef CONFIG_DEBUG_NE2K
417     dump_state(dev);
418 #endif
419
420 }
421
422 static int ne2k_send_packet(struct vm_device *dev, uchar_t *pkt, int length) {
423     int i;
424   
425     PrintDebug("\nNe2k: Sending Packet\n");
426
427     for (i = 0; i < length; i++) {
428         PrintDebug("%x ",pkt[i]);
429     }
430
431     PrintDebug("\n");
432         
433     PrintError("Implement Send Packet interface\n");
434
435     return -1;
436 }
437
438 static int ne2k_rxbuf_full(struct vm_device *dev) {
439     int empty;
440     int index;
441     int boundary;
442     struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
443
444     index = nic_state->curpag << 8;
445     boundary = nic_state->boundary << 8;
446
447     if (index < boundary) {
448         empty = boundary - index;
449     } else {
450         empty = ((nic_state->pgstop - nic_state->pgstart) << 8) - (index - boundary);
451     }
452
453     if (empty < (MAX_ETH_FRAME_SIZE + 4)) {
454         return 1;
455     }
456
457     return 0;
458 }
459
460 #define MIN_BUF_SIZE 60
461
462
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;
466     uchar_t * p;
467     uint32_t total_len;
468     uint32_t next;
469     uint32_t len;
470     uint32_t index;
471     uint32_t empty;
472     uchar_t buf[60];
473     uint32_t start;
474     uint32_t stop;
475
476     start = nic_state->pgstart << 8;
477     stop = nic_state->pgstop << 8;
478    
479     if (nic_state->cmd.stop) {
480         return;
481     }
482
483     if (ne2k_rxbuf_full(dev)) {
484         PrintError("Ne2k: received buffer overflow\n");
485         return;
486     }
487
488
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);
493         pkt = buf;
494         length = MIN_BUF_SIZE;
495     }
496
497     index = nic_state->curpag << 8;
498
499     //header, 4 bytes
500     total_len = length + 4;
501
502     //address for next packet (4 bytes for CRC)
503     next = index + ((total_len + 4 + 255) & ~0xff);
504
505     if (next >= stop) {
506         next -= (stop - start);
507     }
508
509     p = nic_state->mem + index;
510     nic_state->rsr.val = 0;
511     nic_state->rsr.rx_pkt_ok = 1;
512
513     if (pkt[0] & 0x01) {
514         nic_state->rsr.phy = 1;
515     }
516
517     p[0] = nic_state->rsr.val;
518     p[1] = next >> 8;
519     p[2] = total_len;
520     p[3] = total_len >> 8;
521     index += 4;
522
523     while (length > 0) {
524         if (index <= stop) {
525             empty = stop - index;
526         } else {
527             empty = 0;
528         }
529
530         len = length;
531
532         if (len > empty) {
533             len = empty;
534         }
535
536         memcpy(nic_state->mem + index, pkt, len);
537         pkt += len;
538         index += len;
539
540         if (index == stop) {
541             index = start;
542         }
543
544         length -= len;
545     }
546
547     nic_state->curpag = next >> 8;
548
549     nic_state->isr.pkt_rx = 1;
550     ne2k_update_irq(dev);
551 }
552
553
554
555
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 };
559     int i;
560   
561 #ifdef CONFIG_DEBUG_NE2K
562     PrintDebug("\nNe2k: Packet Received:\nSource:");
563     for (i = 6; i < 12; i++) {
564         PrintDebug("%x ", pkt[i]);
565     }
566
567     PrintDebug("\n");
568
569     for(i = 0; i < size; i++) {
570         PrintDebug("%x ", pkt[i]);
571     }    
572     PrintDebug("\n");
573 #endif    
574
575
576     if (nic_state->rcr.prom_phys_enable == 1) {
577         //promiscuous mode
578         ne2k_receive(ne2ks[i], pkt, size);
579     } else if (compare_mac(pkt,  brocast_mac) && (nic_state->rcr.bcast_ok)) {
580         //broadcast packet
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);
587     }
588     
589     return 0;
590 }
591
592
593 static void ne2k_mem_writeb(struct ne2k_context * nic_state, uint32_t addr, uint32_t val) {
594     uchar_t tmp;
595
596     tmp = (uchar_t) (val & 0x000000ff);
597
598     if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
599         nic_state->mem[addr] = tmp;
600     }
601
602     PrintDebug("wmem addr: %x val: %x\n", addr, val);
603 }
604
605 static void ne2k_mem_writew(struct ne2k_context * nic_state, 
606                             uint32_t addr,
607                             uint32_t val) {
608     addr &= ~1; //XXX: check exact behaviour if not even
609
610     if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
611         *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
612     }
613
614     PrintDebug("wmem addr: %x val: %x\n", addr, val);
615 }
616
617 static void ne2k_mem_writel(struct ne2k_context *nic_state,
618                             uint32_t addr,
619                             uint32_t val) {
620     addr &= ~1; // XXX: check exact behaviour if not even
621
622     if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
623         *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
624     }
625
626     PrintDebug("wmem addr: %x val: %x\n", addr, val);
627 }
628
629 static uchar_t  ne2k_mem_readb(struct ne2k_context *nic_state, uint32_t addr) {
630     PrintDebug("rmem addr: %x\n", addr);
631         
632     if ((addr < 32) || (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE)) {
633         return nic_state->mem[addr];
634     } else {
635         return 0xff;
636     }
637 }
638
639 static ushort_t ne2k_mem_readw(struct ne2k_context *nic_state, uint32_t addr) {
640     PrintDebug("rmem addr: %x\n", addr);
641         
642     addr &= ~1; //XXX: check exact behaviour if not even 
643
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));
646     } else {
647         return 0xffff;
648     }
649 }
650
651 static uint32_t ne2k_mem_readl(struct ne2k_context *nic_state, uint32_t addr) {
652     PrintDebug("rmem addr: %x\n", addr);
653
654     addr &= ~1; //XXX: check exact behaviour if not even
655
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));
658     } else {
659         return 0xffffffff;
660     }
661 }
662
663
664 static void ne2k_dma_update(struct vm_device *dev, int len) {           
665     struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
666         
667     nic_state->rsar += len;
668
669     // wrap
670     if (nic_state->rsar == nic_state->pgstop) {
671         nic_state->rsar = nic_state->pgstart;
672     }
673
674     if (nic_state->rbcr <= len) {
675         nic_state->rbcr = 0;
676         nic_state->isr.rem_dma_done = 1;
677         ne2k_update_irq(dev);
678     } else {
679         nic_state->rbcr -= len;
680     }
681 }
682
683
684 //for data port read/write
685 static int ne2k_data_read(ushort_t port, void * dst, uint_t length, struct vm_device *dev) {
686     uint32_t val;
687     struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
688     
689     // current dma address
690     uint32_t addr = nic_state->rsar;
691
692     switch (length){
693         case 1:
694             val = ne2k_mem_readb(nic_state, addr);
695             break;
696         case 2:
697             val = ne2k_mem_readw(nic_state, addr);
698             break;
699         case 4:
700             val = ne2k_mem_readl(nic_state, addr);
701             break;
702         default:
703             PrintError("ne2k_data_read error: invalid length %d\n", length);
704             val = 0x0;
705     }
706     
707     ne2k_dma_update(dev, length);
708
709     memcpy(dst, &val, length);
710
711     PrintDebug("ne2k_read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
712
713     return length;
714 }
715
716 static int ne2k_data_write(ushort_t port, void * src, uint_t length, struct vm_device *dev) {
717     uint32_t val;
718     struct ne2k_context * nic_state = (struct ne2k_context *)dev->private_data;
719     uint32_t addr = nic_state->rsar;
720
721     if (nic_state->rbcr == 0) {
722         return length;
723     }
724
725     memcpy(&val, src, length);
726
727     switch (length) {
728         case 1:
729             ne2k_mem_writeb(nic_state, addr, val);
730             break;
731         case 2:
732             ne2k_mem_writew(nic_state, addr, val);
733             break;
734         case 4:
735             ne2k_mem_writel(nic_state, addr, val);
736             break;
737         default:
738             PrintError("nic_data_write error: invalid length %d\n", length);
739     }
740     
741     ne2k_dma_update(dev, length);
742
743     PrintDebug("ne2k_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
744     
745     return length;
746 }
747
748 static int ne2k_reset_device(struct vm_device * dev) {  
749     PrintDebug("vnic: reset device\n");
750
751     init_ne2k_context(dev);
752
753     return 0;
754 }
755
756
757 //for 0xc11f port
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);
760
761     memset(dst, 0, length);
762     ne2k_reset_device(dev);
763
764     return length;
765 }
766
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);                  
769     return length;
770 }
771
772
773
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;
776
777     if (length != 1) {
778         PrintError("Invalid write length to ne2k Command register\n");
779         return -1;
780     }
781
782     nic_state->cmd.val = *(uint8_t *)src;
783
784     if (!(nic_state->cmd.stop)) {
785         nic_state->isr.reset = 0;
786         
787
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);
792         }
793         
794         if (nic_state->cmd.tx_pkt) {
795             int offset = (nic_state->tpsr << 8);
796             
797             if (offset >= NE2K_PMEM_END) {
798                 offset -= NE2K_PMEM_SIZE;
799             }
800
801             if (offset + nic_state->tbcr <= NE2K_PMEM_END) {
802                 ne2k_send_packet(dev, nic_state->mem + offset, nic_state->tbcr);
803             }
804
805             
806             nic_state->tsr.val = 0;        // clear the tx status reg
807             nic_state->tsr.pkt_tx_ok = 1;  // indicate successful tx
808
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);
812         }
813     } else {
814         // stop the controller
815     }
816
817     return length;
818 }
819
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;
822
823     PrintDebug("ne2k_read: port:0x%x  val: 0x%x\n", port, *(uint8_t *)dst);
824     return length;
825 }
826
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;
831
832     if (length != 1
833         PrintError("ne2k_write error: length %d\n", length);  
834         return -1;
835     }
836
837     PrintDebug("ne2k_write: port:0x%x  val: 0x%x\n", port, (int)val);
838     
839
840     if (page == 0) {
841         switch (port) {
842             case EN0_STARTPG:
843                 nic_state->pgstart = val;
844                 break;
845             case EN0_STOPPG:
846                 nic_state->pgstop = val;
847                 break;
848             case EN0_BOUNDARY:
849                 nic_state->boundary = val;
850                 break;
851             case EN0_TPSR:
852                 nic_state->tpsr = val;
853                 break;
854             case EN0_TCNTLO:
855                 nic_state->tbcr0 = val;
856                 break;
857             case EN0_TCNTHI:
858                 nic_state->tbcr1 = val;
859                 break;
860             case EN0_ISR:
861                 nic_state->isr.val &= ~(val & 0x7f);
862                 ne2k_update_irq(dev);
863                 break;
864             case EN0_RSARLO:
865                 nic_state->rsar0 = val;
866                 break;
867             case EN0_RSARHI:
868                 nic_state->rsar1 = val;
869                 break;
870             case EN0_RCNTLO:
871                 nic_state->rbcr0 = val;
872                 break;
873             case EN0_RCNTHI:
874                 nic_state->rbcr1 = val;
875                 break;
876             case EN0_RXCR:
877                 nic_state->rcr.val = val;
878                 break;
879             case EN0_TXCR:
880                 nic_state->tcr.val = val;
881                 break;
882             case EN0_DCFG:
883                 nic_state->dcr.val = val;
884                 break;  
885             case EN0_IMR:
886                 nic_state->imr.val = val;
887                 //PrintError("ne2k_write error: write IMR:0x%x\n", (int)val);
888                 ne2k_update_irq(dev);
889                 break;
890             default:
891                 PrintError("ne2k_write error: invalid port:0x%x\n", port);
892                 return -1;
893         }
894     } else if (page == 1) {
895         switch (port) {
896             case EN1_PHYS ... EN1_PHYS + 5:
897                 nic_state->mac_addr[port - EN1_PHYS] = val;
898                 break;
899             case EN1_CURPAG:
900                 nic_state->curpag = val;
901                 break;
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;
905                 break;
906             default:
907                 PrintError("ne2k_write error: invalid port:0x%x\n", port);
908                 return -1;
909         }
910     } else if (page == 2) {
911         switch (port) {
912             case EN2_LDMA0:
913                 nic_state->clda0 = val;
914                 break;
915             case EN2_LDMA1:
916                 nic_state->clda1 = val;
917                 break;
918             case EN2_RNPR:
919                 nic_state->rnpp = val;
920                 break;
921             case EN2_LNRP:
922                 nic_state->lnpp = val;
923                 break;
924             case EN2_ACNT0:
925                 nic_state->addcnt0 = val;
926                 break;
927             case EN2_ACNT1: 
928                 nic_state->addcnt1 = val;
929                 break;
930             default:
931                 PrintError("ne2k_write error: invalid port:0x%x\n", port);
932                 return -1;
933         }
934     } else {
935         PrintError("Invalid Register Page Value\n");
936         return -1;
937     }
938
939
940     return length;
941         
942 }
943
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;
948
949     if (length > 1) {
950         PrintError("ne2k_read error: length %d\n", length);
951         return length;
952     }
953
954     if (page == 0) {
955
956         switch (index) {                
957             case EN0_CLDALO:
958                 *(uint8_t *)dst = nic_state->clda0;
959                 break;
960             case EN0_CLDAHI:
961                 *(uint8_t *)dst = nic_state->clda1;
962                 break;
963             case EN0_BOUNDARY:
964                 *(uint8_t *)dst = nic_state->boundary;
965                 break;
966             case EN0_TSR:
967                 *(uint8_t *)dst = nic_state->tsr.val;
968                 break;
969             case EN0_NCR:
970                 *(uint8_t *)dst = nic_state->ncr;
971                 break;
972             case EN0_FIFO:
973                 *(uint8_t *)dst = nic_state->fifo;
974                 break;
975             case EN0_ISR:
976                 *(uint8_t *)dst = nic_state->isr.val;
977                 ne2k_update_irq(dev);
978                 break;
979             case EN0_CRDALO:
980                 *(uint8_t *)dst = nic_state->crda0;
981                 break;
982             case EN0_CRDAHI:
983                 *(uint8_t *)dst = nic_state->crda1;
984                 break;
985             case EN0_RSR:
986                 *(uint8_t *)dst = nic_state->rsr.val;
987                 break;
988             case EN0_COUNTER0:
989                 *(uint8_t *)dst = nic_state->cntr0;
990                 break;
991             case EN0_COUNTER1:
992                 *(uint8_t *)dst = nic_state->cntr1;
993                 break;  
994             case EN0_COUNTER2:
995                 *(uint8_t *)dst = nic_state->cntr2;
996                 break;
997             default:
998                 PrintError("ne2k_read error: invalid port:0x%x\n", port);
999                 return -1;
1000         }
1001
1002     } else if (page == 1) {
1003
1004         switch (index) {
1005             case EN1_PHYS ... EN1_PHYS + 5:
1006                 *(uint8_t *)dst = nic_state->mac_addr[index - EN1_PHYS];
1007                 break;
1008             case EN1_CURPAG:
1009                 *(uint8_t *)dst = nic_state->curpag;
1010                 break;
1011             case EN1_MULT ... EN1_MULT + 7:
1012                 *(uint8_t *)dst = nic_state->mcast_addr[index - EN1_MULT];
1013                 break;
1014             default:
1015                 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1016                 return -1;
1017         }
1018
1019     } else if (page == 2) {
1020
1021         switch (index) {
1022             case EN2_STARTPG:
1023                 *(uint8_t *)dst = nic_state->pgstart;
1024                 break;
1025             case EN2_STOPPG:
1026                 *(uint8_t *)dst = nic_state->pgstop;
1027                 break;
1028             case EN2_RNPR:
1029                 *(uint8_t *)dst = nic_state->rnpp;
1030                 break;
1031             case EN2_LNRP:
1032                 *(uint8_t *)dst = nic_state->lnpp;
1033                 break;
1034             case EN2_TPSR:
1035                 *(uint8_t *)dst = nic_state->tpsr;
1036                 break;
1037             case EN2_ACNT0:
1038                 *(uint8_t *)dst = nic_state->addcnt0;
1039                 break;
1040             case EN2_ACNT1: 
1041                 *(uint8_t *)dst = nic_state->addcnt1;
1042                 break;
1043             case EN2_RCR:
1044                 *(uint8_t *)dst = nic_state->rcr.val;
1045                 break;
1046             case EN2_TCR:
1047                 *(uint8_t *)dst = nic_state->tcr.val;
1048                 break;
1049             case EN2_DCR:
1050                 *(uint8_t *)dst = nic_state->dcr.val;
1051                 break;
1052             case EN2_IMR:
1053                 *(uint8_t *)dst = nic_state->imr.val;
1054                 break;
1055             default:
1056                 PrintError("ne2k_read error: invalid port:0x%x\n", port);
1057                 return -1;
1058         }
1059     } else {
1060         PrintError("Invalid Register Page Value\n");
1061         return -1;
1062     }
1063
1064     
1065     PrintDebug("ne2k_read: port:0x%x  val: 0x%x\n", port, *(uint8_t *)dst);
1066
1067     return length;
1068 }
1069
1070
1071 static int ne2k_start_device(struct vm_device * dev) {
1072     PrintDebug("vnic: start device\n");
1073   
1074     return 0;
1075 }
1076
1077
1078 static int ne2k_stop_device(struct vm_device * dev) {
1079     PrintDebug("vnic: stop device\n");
1080   
1081     return 0;
1082 }
1083
1084
1085
1086
1087 static int ne2k_init_device(struct vm_device * dev) {
1088     struct ne2k_context * nic_state = (struct ne2k_context *)(dev->private_data);
1089     
1090     PrintDebug("Initializing NE2K\n");
1091
1092     init_ne2k_context(dev);
1093
1094     if (nic_state->pci_bus == NULL) {
1095         PrintDebug("NE2k: Not attached to pci\n");
1096
1097         v3_dev_hook_io(dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
1098
1099         for (i = 1; i < 16; i++){       
1100             v3_dev_hook_io(dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
1101         }
1102
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);
1105
1106     } else {
1107
1108         struct v3_pci_bar bars[6];
1109         struct pci_device * pci_dev = NULL;
1110         int i;
1111
1112         PrintDebug("NE2k: PCI Enabled\n");
1113
1114         for (i = 0; i < 6; i++) {
1115             bars[i].type = PCI_BAR_NONE;
1116         }
1117
1118         bars[0].type = PCI_BAR_IO;
1119         bars[0].default_base_port = NIC_REG_BASE_PORT;
1120         bars[0].num_ports = 256;
1121
1122         bars[0].io_read = ne2k_pci_read;
1123         bars[0].io_write = ne2k_pci_write;
1124
1125         pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0, 
1126                                          "NE2000", bars,
1127                                          pci_config_update, NULL, NULL, dev);
1128
1129         if (pci_dev == NULL) {
1130             PrintError("Failed to register NE2K with PCI\n");
1131             return -1;
1132         }
1133
1134         pci_dev->config_header.vendor_id = 0x10ec;
1135         pci_dev->config_header.device_id = 0x8029;
1136         pci_dev->config_header.revision = 0x00;
1137
1138         pci_dev->config_header.subclass = 0x00;
1139         pci_dev->config_header.class = 0x02;
1140         pci_dev->config_header.header_type = 0x00;
1141
1142         pci_dev->config_header.intr_line = 11;
1143         pci_dev->config_header.intr_pin = 1;
1144
1145         nic_state->pci_dev = pci_dev;
1146     }
1147     
1148
1149 #ifdef CONFIG_DEBUG_NE2K
1150     dump_state(dev);
1151 #endif
1152
1153     return 0;
1154 }
1155
1156
1157
1158 static int ne2k_deinit_device(struct vm_device *dev) {
1159     int i;
1160   
1161     for (i = 0; i < 16; i++){           
1162         v3_dev_unhook_io(dev, NIC_REG_BASE_PORT + i);
1163     }
1164     
1165     v3_dev_unhook_io(dev, NIC_DATA_PORT);
1166     v3_dev_unhook_io(dev, NIC_RESET_PORT);
1167   
1168     return 0;
1169 }
1170
1171
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,
1178 };
1179
1180
1181 struct vm_device * v3_create_ne2k(struct vm_device * pci) {
1182     struct ne2k_context * nic_state = V3_Malloc(sizeof(struct ne2k_context));
1183
1184     memset(nic_state, 0, sizeof(struct ne2k_context));
1185
1186     nic_state->pci_bus = pci;
1187
1188     struct vm_device * device = v3_create_device("NE2K", &dev_ops, nic_state);
1189     
1190     return device;
1191 }
1192