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.


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