solaflare: driver removing old filter code
[barrelfish] / usr / drivers / solarflare / sfn5122f_cdriver.c
1 /*
2  * Copyright (c) 2007-2011, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include <net_queue_manager/net_queue_manager.h>
15 #include <barrelfish/nameservice_client.h>
16 #include <barrelfish/spawn_client.h>
17 #include <barrelfish/deferred.h>
18 #include <netd/netd.h>
19 #include <net_device_manager/net_device_manager.h>
20 #include <pci/pci.h>
21 #include <ipv4/lwip/inet.h>
22 #include <barrelfish/debug.h>
23 #include <if/sfn5122f_defs.h>
24 #include <if/sfn5122f_devif_defs.h>
25 #include <if/net_filter_defs.h>
26 #include <if/net_ARP_defs.h>
27 #include <if/net_ARP_defs.h>
28
29 #include "sfn5122f.h"
30 #include "sfn5122f_debug.h"
31 #include "buffer_tbl.h"
32 #include "sfn5122f_qdriver.h"
33
34
35 struct queue_state {
36     bool enabled;
37     bool userspace;
38     bool use_irq;
39
40     struct sfn5122f_binding *binding;
41     struct sfn5122f_devif_binding *devif;
42     struct capref tx_frame;
43     struct capref rx_frame;
44     struct capref ev_frame;
45     uint32_t rxbufsz;
46
47     //bool userspace;
48     uint64_t rx_head;
49     uint64_t tx_head;
50     uint64_t ev_head;
51
52     // first entries of the buffer table to make up queue
53     uint32_t rx_buf_tbl;
54     uint32_t tx_buf_tbl;
55     uint32_t ev_buf_tbl;
56
57     // MSI-X information
58     size_t msix_index;
59     int16_t msix_intvec;
60     uint8_t msix_intdest;
61 };
62
63 static bool use_msix = false;
64 static const char *service_name = "sfn5122f";
65 static sfn5122f_t *d = NULL;
66 static void* d_virt;
67 //static sfn5122f_msix_t *d_msix = NULL;
68 static uint64_t d_mac[2];
69 static int initialized = 0;
70 static struct capref *regframe;
71 /* Interrupt state  */
72 static struct capref int_ker;
73 static void* int_ker_virt;
74 /*  MAC stats  */
75 static struct capref mac_stats;
76 static void* mac_virt;
77 static uint64_t mac_phys;
78 /*        */
79
80 // Port  info
81 static uint32_t cap[2];
82 static uint32_t speed[2];
83 static uint32_t flags[2];
84 static uint32_t fcntl [2];
85
86 // Phy info
87 static uint32_t phy_caps[2];
88 static uint32_t phy_flags[2];
89 static uint32_t phy_media[2];
90 /* Loopback mode none and speed */
91 static uint32_t phy_loopback_mode = 0;
92 //static uint32_t phy_loopback_speed = 0;
93 //WoL Filter id
94 static uint32_t wol_filter_id = 0;
95
96 // ARP rpc client
97 //static struct net_ARP_binding *arp_binding;
98 //static bool net_arp_connected = false;
99
100 static bool csum_offload = 1;
101 // TX / RX
102 static uint32_t rx_indir_tbl[128];
103
104 // Queues
105 static struct queue_state queues[1024];
106 /* PCI device address passed on command line */
107 static uint32_t pci_bus = PCI_DONT_CARE;
108 static uint32_t pci_device = PCI_DONT_CARE;
109 static uint32_t pci_vendor = PCI_DONT_CARE;
110 static uint32_t pci_devid = PCI_DONT_CARE;
111 static uint32_t pci_function = 0;
112
113 static struct bmallocator msix_alloc;
114 static size_t cdriver_msix = -1;
115 static uint8_t cdriver_vector;
116
117 static bool use_interrupt = true;
118
119 // first to start everything
120 static bool first = 1;
121
122 /* Hash key */
123 uint8_t rx_hash_key[40];
124 uint8_t mc_hash[32];
125
126 // Filters
127
128 enum filter_type_ip {
129     OTHER,
130     UDP_FULL,
131     TCP_FULL,
132     TCP_WILDCARD,
133     UDP_WILDCARD
134 };
135
136 /*
137 enum filter_type_mac {
138     OTHER,
139     MAC_FULL,
140     MAC_WILDCARD
141 };
142 */
143
144 struct sfn5122f_filter_ip {
145     bool enabled;
146     bool scatter;
147     bool rss;
148
149     uint8_t queue;
150
151     uint32_t src_ip;
152     uint32_t dst_ip;
153     uint16_t src_port;
154     uint16_t dst_port;
155
156     uint16_t type_ip;
157     uint16_t hash;
158 };
159
160 /*
161 struct sfn5122f_filter_mac {
162     bool enabled;
163     bool wildcard_match;
164     bool scatter;
165     bool rss;
166     bool ip_override;
167
168     uint8_t queue;
169
170     uint64_t dst_mac;
171     uint16_t vlan_id;
172
173     uint16_t type_mac;
174     uint16_t hash;
175 };
176 */
177
178 /* scatter and rss enable */
179 static bool rss_en = 0;
180 static bool scatter_en = 0;
181 static struct sfn5122f_filter_ip filters_rx_ip[NUM_FILTERS_IP];
182 //static struct sfn5122f_filter_ip filters_tx_ip[NUM_FILTERS_IP];
183
184 /*
185 static struct sfn5122f_filter_mac filters_rx_ip[NUM_FILTERS_MAC];
186 static struct sfn5122f_filter_mac filters_tx_ip[NUM_FILTERS_MAC];
187 */
188
189
190 /******************************************************************************/
191 /* Prototypes */
192 void qd_main(void) __attribute__((weak));
193 void qd_argument(const char *arg) __attribute__((weak));
194 void qd_interrupt(void) __attribute__((weak));
195 void qd_queue_init_data(struct sfn5122f_binding *b, struct capref registers,
196                         uint64_t macaddr) __attribute__((weak));
197 void qd_queue_memory_registered(struct sfn5122f_binding *b) __attribute__((weak));
198 void qd_write_queue_tails(struct sfn5122f_binding *b) __attribute__((weak));
199
200
201 void cd_request_device_info(struct sfn5122f_binding *b);
202 void cd_register_queue_memory(struct sfn5122f_binding *b,
203                               uint16_t queue,
204                               struct capref tx,
205                               struct capref rx,
206                               struct capref ev,
207                               uint32_t rxbufsz,
208                               bool use_interrupts,
209                               bool userspace,
210                               uint8_t vector,
211                               uint16_t core);
212
213 static void idc_write_queue_tails(struct sfn5122f_binding *b);
214
215 static void device_init(void);
216 static void start_all(void);
217 static void probe_all(void);
218 static uint32_t init_txq(uint16_t n, lpaddr_t phys, bool csum, bool userspace);
219 static uint32_t init_rxq(uint16_t n, lpaddr_t phys, bool userspace);
220 static uint32_t init_evq(uint16_t n, lpaddr_t phys, bool interrupt);
221 static void queue_hw_stop(uint16_t n);
222
223 static void setup_interrupt(size_t *msix_index, uint8_t core, uint8_t vector);
224 static void global_interrupt_handler(void* arg);
225
226 /*
227 static void bind_arp(struct waitset *ws);
228 static errval_t arp_ip_info(void);
229 */
230 /***************************************************************************/
231 /* Filters */
232
233 static void sfn5122f_filter_port_setup(int idx, struct sfn5122f_filter_ip* filter)
234 {
235     sfn5122f_rx_filter_tbl_lo_t filter_lo = 0;
236     sfn5122f_rx_filter_tbl_hi_t filter_hi = 0;
237
238     if (filter->type_ip == net_filter_PORT_UDP) {
239
240         // Add destination IP
241         filter_hi = sfn5122f_rx_filter_tbl_hi_dest_ip_insert(filter_hi,
242                                                              filter->dst_ip);
243         filter_lo = sfn5122f_rx_filter_tbl_lo_src_ip_insert(filter_lo,
244                                                             0);
245         filter_hi = sfn5122f_rx_filter_tbl_hi_tcp_udp_insert(filter_hi, 1);
246         filter_lo = sfn5122f_rx_filter_tbl_lo_src_tcp_dest_udp_insert(
247                                                 filter_lo, filter->dst_port);
248
249         filter_hi = sfn5122f_rx_filter_tbl_hi_rss_en_insert(filter_hi, 0);
250         filter_hi = sfn5122f_rx_filter_tbl_hi_scatter_en_insert(filter_hi, 0);
251         DEBUG("UPD filter index %d: ip_dst %x port_dst %d ip_src %x port_src %d"
252                " queue %d \n",
253                idx, filter->dst_ip, filter->dst_port,
254                filter->src_ip, filter->src_port, filter->queue);
255     }
256
257     if (filter->type_ip == net_filter_PORT_TCP) {
258         // Add dst IP and port
259         filter_hi = sfn5122f_rx_filter_tbl_hi_dest_ip_insert(filter_hi,
260                                                              filter->dst_ip);
261         filter_lo = sfn5122f_rx_filter_tbl_lo_src_ip_insert(filter_lo,
262                                                             filter->src_ip);
263         filter_lo = sfn5122f_rx_filter_tbl_lo_dest_port_tcp_insert(filter_lo,
264                                                                    filter->dst_port);
265         filter_hi = sfn5122f_rx_filter_tbl_hi_tcp_udp_insert(filter_hi, 0);
266         filter_hi = sfn5122f_rx_filter_tbl_hi_rss_en_insert(filter_hi, 0);
267         filter_hi = sfn5122f_rx_filter_tbl_hi_scatter_en_insert(filter_hi, 0);
268         DEBUG("TCP filter index %d: ip_dst %x port_dst %d ip_src %x port_src %d"
269                " queue %d \n",
270                idx, filter->dst_ip, filter->dst_port,
271                filter->src_ip, filter->src_port, filter->queue);
272     }
273
274     filter_hi = sfn5122f_rx_filter_tbl_hi_rxq_id_insert(filter_hi, filter->queue);
275     filter_hi = sfn5122f_rx_filter_tbl_hi_rss_en_insert(filter_hi, rss_en);
276     filter_hi = sfn5122f_rx_filter_tbl_hi_scatter_en_insert(filter_hi, scatter_en);
277
278     sfn5122f_rx_filter_tbl_lo_wr(d, idx, filter_lo);
279     sfn5122f_rx_filter_tbl_hi_wr(d, idx, filter_hi);
280 }
281
282 static uint32_t build_key(struct sfn5122f_filter_ip* f)
283 {
284     uint32_t data[4] = {0,0,0,0};
285     uint32_t host1;
286     uint32_t host2;
287     uint16_t port1;
288     uint16_t port2;
289     host1 = f->src_ip;
290     host2 = f->dst_ip;
291     
292     if (f->type_ip == sfn5122f_PORT_UDP) {
293        port1 = f->dst_port;
294        port2 = f->src_port;
295        data[3] = 1;
296     } else {
297        port1 = f->src_port;
298        port2 = f->dst_port;
299        data[3] = 0;
300     }
301
302     data[0] = host1 << 16 | port1;
303     data[1] = port2 << 16 | host1 >> 16;
304     data[2] = host2;
305
306     return data[0] ^ data[1] ^ data[2] ^ data[3];
307 }
308
309 static uint16_t filter_hash(uint32_t key)
310 {
311     uint16_t tmp;
312
313     /* First 16 rounds */
314     tmp = 0x1fff ^ key >> 16;
315     tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
316     tmp = tmp ^ tmp >> 9;
317     /* Last 16 rounds */
318     tmp = tmp ^ tmp << 13 ^ key;
319     tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
320     return tmp ^ tmp >> 9;
321 }
322
323 /*
324 static bool filter_equals(struct sfn5122f_filter_ip* f1,
325                           struct sfn5122f_filter_ip* f2)
326 {
327     if (f1->type_ip != f2->type_ip) {
328         return false;
329     } else if ((f1->src_ip != f2->src_ip) ||
330                (f1->dst_ip != f2->dst_ip) ||
331                (f1->queue != f2->queue)) {
332         return false;
333     } else if ((f1->src_port != f2->src_port) &&
334                (f2->dst_port != f1->dst_port)) {
335         return false;
336     } else {
337         return true;
338     }
339 }
340 */
341 static uint16_t filter_increment(uint32_t key)
342 {
343     return key * 2 - 1;
344 }
345
346 static int ftqf_alloc(struct sfn5122f_filter_ip* f)
347 {
348     // Documentation suggest hashing using a certain algorithm
349     int key = 0;
350     uint16_t hash = 0;
351     unsigned int incr = 0;
352     uint16_t depth = 0;
353     key = build_key(f);
354     hash = filter_hash(key);
355     incr = filter_increment(key);
356     
357     key = hash & (NUM_FILTERS_IP - 1);
358
359     while (true) {
360         if (filters_rx_ip[key].enabled == false) {
361             return key;
362         } 
363         
364         if (depth > 3) {
365             return -1;
366         }
367             
368         key = (key + incr) & (NUM_FILTERS_IP - 1);
369         depth++;
370     }
371
372     return key;
373 }
374
375 static errval_t reg_port_filter(struct sfn5122f_filter_ip* f, uint64_t* fid)
376 {
377     int filt_ind;
378
379     DEBUG("reg_port_filter: called\n");
380
381     if ((filt_ind=ftqf_alloc(f)) < 0) {
382         return FILTER_ERR_NOT_ENOUGH_MEMORY;
383     }
384
385     filters_rx_ip[filt_ind] = *f;
386     filters_rx_ip[filt_ind].enabled = true;
387
388     sfn5122f_filter_port_setup(filt_ind, f);
389
390     // TODO +1 needed?
391     *fid = filt_ind;
392
393     return SYS_ERR_OK;
394 }
395
396
397 /***************************************************************************/
398 /* Helper functions*/
399 static void decode_link(uint32_t fcntl1 , uint32_t flags1 , uint32_t speed1)
400 {
401     switch(fcntl1){
402     case 0x3:
403         DEBUG("LINK MODE: AUTO \n");
404         break;
405     case 0x2:
406         DEBUG("LINK MODE: RX/TX \n");
407         break;
408     case 0x1:
409         DEBUG("LINK MODE: RESPOND \n");
410         break;
411     case 0x0:
412         DEBUG("LINK MODE: NONE \n");
413         break;
414     }
415     DEBUG("LINK SPEED: %"PRIu32" \n", speed1);
416     DEBUG("LINK FLAGS: %8lX \n", (long unsigned int) flags1);
417     if (!!(flags1 & 1)) {
418        DEBUG("LINK IS UP \n");
419     }
420
421     if (!!(flags1 & 1 << 0x1)) {
422        DEBUG("LINK IS FULL DUPLEX \n");
423     }
424
425 }
426
427 static void handle_assertions(void)
428 {
429     uint8_t in[4];
430     uint8_t out[140];
431     uint32_t outlen = 0;
432     errval_t err;
433
434     memset(in, 0, sizeof(in));
435     in[CMD_GET_ASSERTS_IN_CLEAR_OFFSET] = 0;
436
437     err = mcdi_rpc(CMD_GET_ASSERTS, in , CMD_GET_ASSERTS_IN_LEN, out,
438                    CMD_GET_ASSERTS_OUT_LEN, &outlen, pci_function, d);
439     assert(err_is_ok(err));
440
441     if(out[0] != 0x1){
442           /* TODO handle assertions */
443          printf("THERE WERE ASSERTIONS: %"PRIu8" \n ", out[0]);
444          /* exit assertions -> special reboot*/
445          in[0] = 0x1;
446          err = mcdi_rpc(CMD_REBOOT, in, CMD_REBOOT_IN_LEN ,
447                         NULL, 0, NULL, pci_function, d);
448          assert(err_is_ok(err));
449     }
450
451 }
452
453 /* Get Link and write settings into global variables  */
454 static void get_link(uint8_t port)
455 {
456     uint8_t out[CMD_GET_LINK_OUT_LEN];
457     errval_t err;
458
459     err = mcdi_rpc(CMD_GET_LINK, NULL, 0 , out, CMD_GET_LINK_OUT_LEN, NULL, port,d);
460     assert(err_is_ok(err));
461
462     memcpy(&cap[port], out, 4);
463     memcpy(&speed[port], out+CMD_GET_LINK_OUT_SPEED_OFFSET, 4);
464     memcpy(&fcntl[port], out+CMD_GET_LINK_OUT_FCNTL_OFFSET, 4);
465     memcpy(&flags[port], out+CMD_GET_LINK_OUT_FLAGS_OFFSET, 4);
466    
467     decode_link(fcntl[port], flags[port], speed[port]);
468
469 }
470
471
472 /* Init port */
473 static void init_port(uint8_t port)
474 {
475     uint8_t in[CMD_SET_MAC_IN_LEN];
476     uint32_t reg;
477     errval_t err;
478
479     memcpy(in + CMD_SET_MAC_IN_ADR_OFFSET, &d_mac[port], 6 );
480     /* linux driver sets these bits */
481     in[14] = 0xFF;
482     in[15] = 0xFF;
483     /* set MTU */
484     reg = MTU_MAX;
485     memcpy(in + CMD_SET_MAC_IN_MTU_OFFSET , &reg, 4);
486     
487     in[CMD_SET_MAC_IN_DRAIN_OFFSET] = 0;
488     /* Reject unicast packets?   */
489     in[CMD_SET_MAC_IN_REJECT_OFFSET] = 1;
490     /* Set wanted flow control of the card 2 -> bidirectional*/
491     in[CMD_SET_MAC_IN_FCTNL_OFFSET] = 2;
492     err = mcdi_rpc(CMD_SET_MAC, in, CMD_SET_MAC_IN_LEN, NULL, 0, NULL, port, d);
493     assert(err_is_ok(err));
494
495     memset(mc_hash, 0, sizeof(mc_hash));
496     err = mcdi_rpc(CMD_SET_MCAST_HASH, mc_hash , CMD_SET_MCAST_HASH_IN_LEN,
497                    NULL, 0 , NULL, port, d);
498     assert(err_is_ok(err));
499
500     memset(in, 0 , sizeof(in));
501     memcpy(in + CMD_SET_LINK_IN_CAP_OFFSET, &cap[pci_function], 4);
502     
503     err = mcdi_rpc(CMD_SET_LINK, in, CMD_SET_LINK_IN_LEN, NULL, 0, NULL, 0, d);
504     assert(err_is_ok(err));
505 }
506 /*  start port        */
507 static void start_port(uint8_t port)
508 {
509     uint8_t in[CMD_SET_MAC_IN_LEN];
510     uint64_t reg;
511     errval_t err;
512
513     memset(&in, 0, sizeof(in));
514
515     err = mcdi_rpc(CMD_SET_MCAST_HASH, mc_hash , CMD_SET_MCAST_HASH_IN_LEN,
516                    NULL, 0 , NULL, port, d);
517     assert(err_is_ok(err));
518
519     /* mac address */
520     memcpy(in + CMD_SET_MAC_IN_ADR_OFFSET, &d_mac[port], 6 );
521     /* seems like the linux driver sets all bits not set
522        from the MAC address to 1*/
523     in[14] = 0xFF;
524     in[15] = 0xFF;
525     /* set MTU*/
526     reg = MTU_MAX;
527     memcpy(in + CMD_SET_MAC_IN_MTU_OFFSET , &reg, 4);
528     in[CMD_SET_MAC_IN_DRAIN_OFFSET] = 0;
529     /* Reject unicast packets ?  */
530     in[CMD_SET_MAC_IN_REJECT_OFFSET] = 1;
531     /* Set wanted functionality (flow control) of card -> set to 2 for RX/TX
532        And on*/
533     in[CMD_SET_MAC_IN_FCTNL_OFFSET] = 2;
534     err = mcdi_rpc(CMD_SET_MAC, in, CMD_SET_MAC_IN_LEN, NULL, 0, NULL, port, d);
535     assert(err_is_ok(err));
536
537     err = mcdi_rpc(CMD_SET_MCAST_HASH, mc_hash , CMD_SET_MCAST_HASH_IN_LEN,
538                    NULL, 0 , NULL, port, d);
539
540     assert(err_is_ok(err));
541 }
542
543 /******************************************************************************
544  * Device init
545  *****************************************************************************/
546
547 static void probe_all(void)
548 {
549     uint32_t offset = 0;
550     uint32_t outlen = 0;
551     
552     uint64_t reg = 0;
553     
554     uint8_t in[16];
555     uint8_t out[252];
556      
557     struct frame_identity frameid = { .base = 0, .bytes = 0 };
558     errval_t r;
559
560     // init MCDI
561     init_mcdi_mutex();
562     // Test and clear MC-reboot flag for port/function
563     offset = MCDI_REBOOT_OFFSET(pci_function);
564     reg =  sfn5122f_mc_treg_smem_rd(d,offset);
565     if (reg != 0) {
566         sfn5122f_mc_treg_smem_wr(d,offset,0);
567     }
568
569     /*print out any assertions */
570     handle_assertions();
571     // Let BMC know that driver is in charg of filter/link setttings
572     // before we can restet NIC
573     memset(&in, 0, sizeof(in));
574     memset(&out, 0 , sizeof(out));
575     
576     r = mcdi_rpc(CMD_GET_VERSION, NULL, 0, out, CMD_GET_VERSION_OUT_LEN,
577                  &outlen, pci_function, d);
578     assert(err_is_ok(r));
579
580
581     memset(&out, 0 , sizeof(out));
582
583     // driver is operating / + update
584     in[0] = 0x1;
585     in[4] = 0x1;
586     r = mcdi_rpc(CMD_DRV_ATTACH, in, CMD_DRV_ATTACH_IN_LEN, out,
587                  CMD_DRV_ATTACH_OUT_LEN, &outlen, pci_function, d);
588     assert(err_is_ok(r));
589
590     /* reset card */
591     r = mcdi_rpc(CMD_PORT_RESET, NULL, 0, NULL, 0, NULL, pci_function, d);
592     assert(err_is_ok(r));
593
594     // init WoL Filter
595     if(mcdi_rpc(CMD_WOL_FILTER_GET, NULL, 0, out, CMD_WOL_FILTER_GET_OUT_LEN,
596        &outlen, pci_function, d) == SYS_ERR_OK) {
597         memcpy(&wol_filter_id, out , 4);
598     } else {
599       // Reset filter of card
600       mcdi_rpc(CMD_WOL_FILTER_RESET, NULL, 0, NULL, 0, NULL, pci_function, d);
601     }
602  
603     //  memory for INT_KER
604     int_ker_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE,
605                                    2*sizeof(uint64_t), &int_ker);
606     memset(int_ker_virt, 0, 2*sizeof(uint64_t));
607     // Read in non volatile configuration
608     memset(&out, 0, sizeof(out));
609     r = mcdi_rpc(CMD_GET_BOARD_CONFIG, NULL, 0, out,
610                  CMD_GET_BOARD_CONFIG_OUT_LEN, &outlen, pci_function, d);
611     assert(err_is_ok(r));
612
613     memcpy(&d_mac[0], out+MCDI_MAC_PORT_OFFSET(0) ,6);
614     memcpy(&d_mac[1], out+MCDI_MAC_PORT_OFFSET(1) ,6);
615     
616     // read phy configuration
617     r = mcdi_rpc(CMD_GET_PHY_CFG, NULL, 0, out, CMD_GET_PHY_CFG_OUT_LEN, &outlen,
618                  pci_function, d);
619     assert(err_is_ok(r));
620
621     memcpy(&phy_caps[pci_function], out+CMD_GET_PHY_CFG_OUT_CAP_OFFSET, 4);
622     memcpy(&phy_flags[pci_function], out+CMD_GET_PHY_CFG_OUT_FLAGS_OFFSET, 4);
623     memcpy(&phy_media[pci_function], out+CMD_GET_PHY_CFG_OUT_MEDIA_OFFSET, 4);
624
625     // get loopback modes
626     r = mcdi_rpc(CMD_GET_LOOPBACK_MODES, NULL, 0, out,
627                  CMD_GET_LOOPBACK_MODES_OUT_LEN, &outlen, pci_function, d);
628     assert(err_is_ok(r));
629     memcpy(&phy_loopback_mode, out+CMD_GET_LOOPBACK_MODES_SUGGESTED_OFFSET,4);
630     // loopback mode NONE is no valid condition
631     phy_loopback_mode &= ~(1);
632    
633
634     // MAC STATS INIT
635     mac_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE,
636                                NUM_MAC_STATS*sizeof(uint64_t),
637                                &mac_stats);
638
639     assert(mac_virt != NULL);
640     r = invoke_frame_identify(mac_stats, &frameid);
641     assert(err_is_ok(r));
642     mac_phys = frameid.base;
643     memset(mac_virt, 0, NUM_MAC_STATS*sizeof(uint64_t));
644
645
646     memset(&in, 0, sizeof(in));
647     memcpy(in, &mac_phys, 8);
648
649      // Settings for DMA of MAC stats
650     in[CMD_MAC_STATS_IN_CMD_OFFSET] = 0x6;
651     in[CMD_MAC_STATS_IN_DMA_LEN_OFFSET] = 8;
652     in[CMD_MAC_STATS_IN_DMA_LEN_OFFSET+1] = 3;
653     r = mcdi_rpc(CMD_MAC_STATS, in, CMD_MAC_STATS_IN_LEN, NULL, 0, NULL,
654                 pci_function, d);
655     assert(err_is_ok(r));
656
657 }
658
659
660
661 // Init card IP filters
662 static void init_rx_filter_config(void)
663 {
664     uint64_t reg_hi, reg_lo;
665
666     for (int i = 0; i < NUM_FILTERS_IP; i++) {
667         sfn5122f_rx_filter_tbl_lo_wr(d, i, 0);
668         sfn5122f_rx_filter_tbl_hi_wr(d, i, 0);
669     }
670
671     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_rd(d);
672     reg_hi = sfn5122f_rx_filter_ctl_reg_hi_rd(d);
673
674     reg_hi = sfn5122f_rx_filter_ctl_reg_hi_ethernet_full_search_limit_insert(reg_hi, 1);
675     reg_hi = sfn5122f_rx_filter_ctl_reg_hi_ethernet_wildcard_search_limit_insert(reg_hi, 3);
676
677     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_multicast_nomatch_q_id_lo_insert(reg_lo, 0);
678     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_unicast_nomatch_q_id_insert(reg_lo, 0);
679     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_unicast_nomatch_rss_enabled_insert(reg_lo, 0);
680     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_multicast_nomatch_rss_enabled_insert(reg_lo, 0);
681
682     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_udp_full_srch_limit_insert(reg_lo, 1);
683     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_udp_wild_srch_limit_insert(reg_lo, 3);
684     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_tcp_full_srch_limit_insert(reg_lo, 1);
685     reg_lo = sfn5122f_rx_filter_ctl_reg_lo_tcp_wild_srch_limit_insert(reg_lo, 3);
686
687
688     sfn5122f_rx_filter_ctl_reg_lo_wr(d,reg_lo);
689     sfn5122f_rx_filter_ctl_reg_hi_wr(d,reg_hi);
690
691 }
692
693 static void device_init(void)
694 {
695     errval_t r;
696     struct frame_identity frameid = { .base = 0, .bytes = 0 };
697     uint64_t reg, reg2; // tmp_key = 0;
698     uint8_t in[24]; // set length to biggest in length needed
699
700     memset(&in, 0, sizeof(in));
701
702     // recover from failed assertion post-reset
703     handle_assertions();
704
705     /* ignore TX of packets 16 bytes and less */
706     reg = sfn5122f_tx_reserved_reg_lo_rd(d);
707     reg = sfn5122f_tx_reserved_reg_lo_tx_flush_min_len_en_insert(reg, 1);
708     sfn5122f_tx_reserved_reg_lo_wr(d, reg);
709     sfn5122f_tx_reserved_reg_hi_wr(d, sfn5122f_tx_reserved_reg_hi_rd(d));
710     //Disable TX_NO_EOP_DISC_EN because else would limit packets to 16
711     reg = sfn5122f_tx_cfg_reg_lo_rd(d);
712     reg = sfn5122f_tx_cfg_reg_lo_tx_no_eop_disc_en_insert(reg, 0);
713     reg = sfn5122f_tx_cfg_reg_lo_tx_ownerr_ctl_insert(reg, 1);
714     reg = sfn5122f_tx_cfg_reg_lo_tx_filter_en_bit_insert(reg, 1);
715     sfn5122f_tx_cfg_reg_lo_wr(d, reg);
716     sfn5122f_tx_cfg_reg_hi_wr(d, sfn5122f_tx_cfg_reg_hi_rd(d));
717
718     reg = sfn5122f_rx_cfg_reg_lo_rd(d);
719     // unset bit and set other bit which are not in documentation (43 and 47)
720     reg = sfn5122f_rx_cfg_reg_lo_rx_desc_push_en_insert(reg, 0) ;
721     reg = sfn5122f_rx_cfg_reg_lo_rx_ingr_en_insert(reg, 1);
722     //reg = sfn5122f_rx_cfg_reg_lo_rx_usr_buf_size_insert(reg, (MTU_MAX-256) >> 5);
723     reg = sfn5122f_rx_cfg_reg_lo_rx_usr_buf_size_insert(reg, 4096 >> 5);
724     //reg = sfn5122f_rx_cfg_reg_lo_rx_ownerr_ctl_insert(reg, 1);
725     reg = sfn5122f_rx_cfg_reg_lo_rx_ip_hash_insert(reg, 1);
726     //reg = sfn5122f_rx_cfg_reg_lo_rx_hash_insrt_hdr_insert(reg, 1);
727     reg = sfn5122f_rx_cfg_reg_lo_rx_hash_alg_insert(reg, 1);
728     sfn5122f_rx_cfg_reg_lo_wr(d, reg);
729     sfn5122f_rx_cfg_reg_hi_wr(d, sfn5122f_rx_cfg_reg_hi_rd(d));
730     /* enable event logging, no UART
731       Event destination is queue 0 */
732     in[0] = 0x2;
733     r = mcdi_rpc(CMD_LOG_CTRL, in, CMD_LOG_CTRL_IN_LEN,
734                  NULL, 0, NULL, pci_function, d);
735     assert(err_is_ok(r));
736
737     /* Set destination of TX/RX flush event */
738     
739     sfn5122f_dp_ctrl_reg_lo_fls_evq_id_wrf(d, 0);
740     sfn5122f_dp_ctrl_reg_hi_wr(d, sfn5122f_dp_ctrl_reg_hi_rd(d));
741   
742     /* Disalbe user events for now     */
743     sfn5122f_usr_ev_cfg_lo_usrev_dis_wrf(d , 1);
744     sfn5122f_usr_ev_cfg_hi_wr(d, sfn5122f_usr_ev_cfg_hi_rd(d));
745
746
747     // This seems to be not device specific i.e. works for other
748     // Solarflare cards
749     /* Set position of descriptor caches in SRAM */
750     sfn5122f_srm_tx_dc_cfg_reg_lo_wr(d, TX_DC_BASE);
751     sfn5122f_srm_tx_dc_cfg_reg_hi_wr(d, sfn5122f_srm_tx_dc_cfg_reg_hi_rd(d));
752     sfn5122f_srm_rx_dc_cfg_reg_lo_srm_rx_dc_base_adr_wrf(d, RX_DC_BASE);
753     sfn5122f_srm_rx_dc_cfg_reg_hi_wr(d, sfn5122f_srm_rx_dc_cfg_reg_hi_rd(d));
754
755     /* Set TX descriptor cache size to 16 */
756     sfn5122f_tx_dc_cfg_reg_lo_tx_dc_size_wrf(d, 1);
757     sfn5122f_tx_dc_cfg_reg_hi_wr(d, sfn5122f_tx_dc_cfg_reg_hi_rd(d));
758
759     /* Set RX descriptor cache size to 64 and low watermark */
760     sfn5122f_rx_dc_cfg_reg_lo_rx_dc_size_wrf(d, 3);
761     sfn5122f_rx_dc_cfg_reg_hi_wr(d, sfn5122f_rx_dc_cfg_reg_hi_rd(d));
762
763     reg = 0;
764     reg = sfn5122f_rx_dc_pf_wm_reg_lo_rx_dc_pf_lwm_insert(reg, RX_DESC_CACHE_SIZE -8);
765     sfn5122f_rx_dc_pf_wm_reg_lo_wr(d, reg);
766     sfn5122f_rx_dc_pf_wm_reg_hi_wr(d, sfn5122f_rx_dc_pf_wm_reg_hi_rd(d));
767    
768    /*programm init ker address for interrupts */
769     r = invoke_frame_identify(int_ker, &frameid);
770     assert(err_is_ok(r));
771
772     sfn5122f_int_adr_reg_ker_lo_wr(d, frameid.base);
773     reg = sfn5122f_int_adr_reg_ker_hi_rd(d);
774
775     // disable vector write if we use MSI-X
776     if (use_msix) {
777         reg = sfn5122f_int_adr_reg_ker_hi_norm_int_vec_dis_ker_insert(reg, 1);
778         if (cdriver_msix == -1) {
779             r = pci_setup_inthandler(global_interrupt_handler, NULL, &cdriver_vector);
780             assert(err_is_ok(r));
781             setup_interrupt(&cdriver_msix, disp_get_core_id(), cdriver_vector);
782         }
783     } else {
784         reg = sfn5122f_int_adr_reg_ker_hi_norm_int_vec_dis_ker_insert(reg, 0);
785     }
786     sfn5122f_int_adr_reg_ker_hi_wr(d, reg);
787    
788     /* Enable all the genuinley fatal interrupts */
789     reg = sfn5122f_fatal_intr_reg_ker_lo_ill_adr_int_ker_en_insert(reg, 1);
790     /* Enable rxbuf/txbuf interrupt  fields not documented.
791        Set bits 39 and 38*/
792     reg = sfn5122f_fatal_intr_reg_ker_lo_rxbuf_own_int_ker_en_insert(reg, 1);
793     reg = sfn5122f_fatal_intr_reg_ker_lo_txbuf_own_int_ker_en_insert(reg, 1);
794     
795     //reg = sfn5122f_fatal_intr_reg_ker_lo_sram_perr_int_p_ker_en_insert(reg, 1);
796     sfn5122f_fatal_intr_reg_ker_lo_wr(d, ~reg);
797     sfn5122f_fatal_intr_reg_ker_hi_wr(d, 0XFFFFFFFFFFFFFFFF);
798
799     /* Setup RSS indirection table (maps from hash value to packet to RXQ) */
800     for (int i = 0; i < 128; i++) {
801         rx_indir_tbl[i] = 0;
802         sfn5122f_rx_indirection_tbl_wr( d, i, rx_indir_tbl[i]);
803     }
804
805     /* Disable the ugly timer-based TX DMA backoff and allow TX DMA to be
806      * controlled by the RX FIFO fill level. Set arbitration to one pkt/Q.
807       (from linux driver) */
808     reg = sfn5122f_tx_reserved_reg_lo_rd(d);
809     reg = sfn5122f_tx_reserved_reg_lo_tx_rx_spacer_en_insert(reg, 1);
810     reg = sfn5122f_tx_reserved_reg_lo_tx_one_pkt_per_q_insert(reg, 0);
811     reg = sfn5122f_tx_reserved_reg_lo_tx_dis_non_ip_ev_insert(reg, 1);
812
813     /* Enable software events */
814     reg = sfn5122f_tx_reserved_reg_lo_tx_soft_evt_en_insert(reg, 1);
815     /* Prefetch threshold 2 => fetch when descriptor cache half empty */
816     reg = sfn5122f_tx_reserved_reg_lo_tx_pref_threshold_insert(reg, 2);
817     /* Disable hardware watchdog which can misfire */
818     reg = sfn5122f_tx_reserved_reg_lo_tx_pref_wd_tmr_insert(reg, 0x3fffff);
819     /* Squash TX of packets of 16 bytes or less */
820     reg = sfn5122f_tx_reserved_reg_lo_tx_flush_min_len_en_insert(reg, 1);
821  
822     reg2 = sfn5122f_tx_reserved_reg_hi_rd(d);
823     reg2 = sfn5122f_tx_reserved_reg_hi_tx_push_en_insert(reg2, 0);
824     reg2 = sfn5122f_tx_reserved_reg_hi_tx_push_chk_dis_insert(reg2, 0);
825     //reg2 = sfn5122f_tx_reserved_reg_hi_tx_rx_spacer_insert(reg2, 0xfe);
826     reg2 = sfn5122f_tx_reserved_reg_hi_tx_rx_spacer_insert(reg2, 0x1);
827     sfn5122f_tx_reserved_reg_lo_wr(d, reg);
828     sfn5122f_tx_reserved_reg_hi_wr(d, reg2);
829
830     init_port(pci_function);
831     get_link(pci_function);
832     DEBUG("BASIC CARD INIT DONE  \n");
833 }
834
835 static void start_all(void)
836 {
837     uint64_t reg;
838  
839     start_port(pci_function);
840
841     memset(int_ker_virt, 0, 2*sizeof(uint64_t));
842     /*  Enable interrupts   */
843     /* Use an interrupt level unused by event queues */
844     reg = sfn5122f_int_en_reg_ker_lo_rd(d);
845     if (use_msix) {
846         reg = sfn5122f_int_en_reg_ker_lo_ker_int_leve_sel_insert(reg, 0);
847     } else {
848         // legacy
849         reg = sfn5122f_int_en_reg_ker_lo_ker_int_leve_sel_insert(reg, 0x1f);
850     }
851     reg = sfn5122f_int_en_reg_ker_lo_drv_int_en_ker_insert(reg, 1);
852
853     /*   undocumented field   */
854     reg = sfn5122f_int_en_reg_ker_lo_ker_int_ker_insert(reg, 0);
855     sfn5122f_int_en_reg_ker_lo_wr(d, reg);
856     sfn5122f_int_en_reg_ker_hi_wr(d, sfn5122f_int_en_reg_ker_hi_rd(d));
857
858     /* Start MAC stats            */
859     /*
860     uint8_t in[CMD_MAC_STATS_IN_LEN];
861     unsigned long long* stats = (unsigned long long *) mac_virt;
862     uint8_t* pointer;
863
864     memset(in, 0, sizeof(in));
865     stats[0x60] = (unsigned long long) (-1);
866     memcpy(in, &mac_phys, 8);
867     pointer = (uint8_t *) &mac_phys;
868     in[CMD_MAC_STATS_IN_CMD_OFFSET] = 0xD;
869     in[10] = 0xE8;
870     in[11] = 3;
871     in[CMD_MAC_STATS_IN_DMA_LEN_OFFSET] = 8;
872     in[CMD_MAC_STATS_IN_DMA_LEN_OFFSET+1] = 3;
873     errval_t err = mcdi_rpc(CMD_MAC_STATS, in, CMD_MAC_STATS_IN_LEN,
874                             NULL, 0, NULL, pci_function, d);
875     assert(err_is_ok(err));
876     */
877 }
878
879 /**************************************************************************
880  Queue init and stop
881 ***************************************************************************/
882
883
884 static void queue_hw_stop(uint16_t n)
885 {
886
887     uint64_t reg = 0;
888     /* flush TX queue */
889     reg = sfn5122f_tx_flush_descq_reg_lo_rd(d);
890     reg = sfn5122f_tx_flush_descq_reg_lo_tx_flush_descq_insert(reg, n);
891     reg = sfn5122f_tx_flush_descq_reg_lo_tx_flush_descq_cmd_insert(reg, 1);
892     sfn5122f_tx_flush_descq_reg_lo_wr(d, reg);
893     sfn5122f_tx_flush_descq_reg_hi_wr(d, sfn5122f_tx_flush_descq_reg_hi_rd(d));
894     /* flush RX queue */
895     reg = sfn5122f_rx_flush_descq_reg_lo_rd(d);
896     reg = sfn5122f_rx_flush_descq_reg_lo_rx_flush_descq_insert(reg, n);
897     reg = sfn5122f_rx_flush_descq_reg_lo_rx_flush_descq_cmd_insert(reg, 1);
898     sfn5122f_rx_flush_descq_reg_lo_wr(d, reg);
899     sfn5122f_rx_flush_descq_reg_hi_wr(d, sfn5122f_rx_flush_descq_reg_hi_rd(d));
900
901     /*   TODO Wait for DRIVER_EVENT    */
902     /* clear pointer table entries */
903     sfn5122f_tx_desc_ptr_tbl_lo_wr(d, n, 0);
904     sfn5122f_tx_desc_ptr_tbl_hi_wr(d, n, 0);
905     sfn5122f_rx_desc_ptr_tbl_lo_wr(d, n, 0);
906     sfn5122f_rx_desc_ptr_tbl_hi_wr(d, n, 0);
907
908     /*Free RX queue tbl entries*/
909     reg = 0;
910     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_cmd_insert(reg, 1);
911     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_start_id_insert(reg,
912                                               queues[n].rx_buf_tbl);
913
914     if (queues[n].userspace) {
915        reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_end_id_insert(reg,
916                                   queues[n].rx_buf_tbl + NUM_ENT_RX_USR);
917     } else {
918         reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_end_id_insert(reg,
919                                        queues[n].rx_buf_tbl + NUM_ENT_RX);
920     }
921
922     /*Free TX queue tbl entries*/
923     reg = 0;
924     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_cmd_insert(reg, 1);
925     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_end_id_insert(reg,
926                               queues[n].tx_buf_tbl + NUM_ENT_TX );
927     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_start_id_insert(reg,
928                                               queues[n].tx_buf_tbl);
929
930     /*Free EV queue tbl entries*/
931     reg = 0;
932     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_cmd_insert(reg, 1);
933     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_end_id_insert(reg,
934                               queues[n].ev_buf_tbl + NUM_ENT_EVQ );
935     reg = sfn5122f_buf_tbl_upd_reg_lo_buf_clr_start_id_insert(reg,
936                                              queues[n].ev_buf_tbl);
937 }
938
939
940
941 static uint32_t init_evq(uint16_t n, lpaddr_t phys, bool interrupt)
942 {
943
944     //errval_t r;
945     //struct frame_identity frameid = { .base = 0, .bytes = 0 };
946     uint64_t reg, buffer_offset;
947     reg = 0;
948
949     reg = sfn5122f_timer_tbl_lo_timer_q_en_insert(reg, 1);
950     // set to 0 if interrupts for receives/sends should be generated
951     if (use_msix) {
952         reg = sfn5122f_timer_tbl_lo_host_notify_mode_insert(reg, 0);
953     } else {
954         reg = sfn5122f_timer_tbl_lo_int_pend_insert(reg, 0);
955         reg = sfn5122f_timer_tbl_lo_int_armd_insert(reg, 0);
956         if (use_interrupt && interrupt) {
957             reg = sfn5122f_timer_tbl_lo_host_notify_mode_insert(reg, 0);
958         } else {
959             reg = sfn5122f_timer_tbl_lo_host_notify_mode_insert(reg, 1);
960         }
961     }
962     // timer mode disabled
963     reg = sfn5122f_timer_tbl_lo_timer_mode_insert(reg, 0);
964     sfn5122f_timer_tbl_lo_wr(d, n, reg);
965     sfn5122f_timer_tbl_hi_wr(d, n, sfn5122f_timer_tbl_hi_rd(d, n));
966
967     /*
968     r = invoke_frame_identify(queues[n].ev_frame, &frameid);
969     assert(err_is_ok(r));
970     ev_phys = frameid.base;
971     */
972
973     buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_EVQ, 0, 0, d);
974     if (buffer_offset == -1) {
975         return -1;
976     }
977
978     DEBUG("EV_QUEUE_%d: buf_off %ld, phys 0x%lx\n",n , buffer_offset, phys);
979     //  setup EV queue
980     reg = sfn5122f_evq_ptr_tbl_lo_rd(d, n);
981     reg = sfn5122f_evq_ptr_tbl_lo_evq_en_insert(reg, 1);
982     reg = sfn5122f_evq_ptr_tbl_lo_evq_size_insert(reg, 6);
983     reg = sfn5122f_evq_ptr_tbl_lo_evq_buf_base_id_insert(reg,
984            buffer_offset);
985
986     sfn5122f_evq_ptr_tbl_lo_wr(d, n, reg);
987     sfn5122f_evq_ptr_tbl_hi_wr(d, n, sfn5122f_evq_ptr_tbl_hi_rd(d, n));
988
989     /* No write collection for this register   */
990     reg = sfn5122f_timer_command_reg_lo_rd(d,n);
991     reg = sfn5122f_timer_command_reg_lo_tc_timer_val_insert(reg, 0);
992     if (use_msix) {
993         reg = sfn5122f_timer_command_reg_lo_tc_timer_mode_insert(reg, 0);
994     } else {
995         reg = sfn5122f_timer_command_reg_lo_tc_timer_mode_insert(reg, 0);
996     }
997
998     sfn5122f_timer_command_reg_lo_wr(d, n, reg);
999
1000     sfn5122f_evq_rptr_reg_wr(d, n, queues[n].ev_head);
1001
1002     return buffer_offset;
1003 }
1004
1005 static uint32_t init_rxq(uint16_t n, lpaddr_t phys, bool userspace)
1006 {
1007     uint64_t reg_lo, reg_hi,  buffer_offset;
1008    /*
1009     * This will define a buffer in the buffer table, allowing
1010     * it to be used for event queues, descriptor rings etc.
1011     */
1012     /* Get physical addresses for rx/tx rings and event queue */
1013
1014     /* RX   */
1015     if (userspace) {
1016         buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_RX_USR, 0, false, d);
1017     } else {
1018         buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_RX, 0, false, d);
1019     }
1020
1021     if (buffer_offset == -1) {
1022        return -1;
1023     }
1024
1025     DEBUG("RX_QUEUE_%d: buf_off %ld, phys %lx\n", n,
1026           buffer_offset, phys);
1027     /* setup RX queue */
1028     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rd(d, n);
1029     reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rd(d, n);
1030     /*  Which buffer table entries are used (which is the first entry) */
1031     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_buf_base_id_insert(reg_lo, buffer_offset);
1032     /*  Which event queue is associated with this queue*/
1033     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_evq_id_insert(reg_lo, n);
1034     
1035     if (!userspace) {
1036         reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_owner_id_insert(reg_lo, 0);
1037     } else {
1038         reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_owner_id_insert(reg_lo, n+1);
1039     }
1040
1041     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_label_insert(reg_lo, n);
1042
1043     /*  1024 entries = 1   (512 = 0; 2048 = 2 ; 4096 = 3)   */
1044     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_size_insert(reg_lo, 3);
1045
1046     if (!userspace) {
1047         reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_type_insert(reg_lo, 0);
1048     } else {
1049         reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_type_insert(reg_lo, 1);
1050     }
1051     /*   No scatter */
1052     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_jumbo_insert(reg_lo, 0);
1053     /*  Enable queue */
1054     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rx_descq_en_insert(reg_lo, 1);
1055    
1056     /*   Hardware verifies data digest  */
1057     reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rx_iscsi_ddig_en_insert(reg_hi, 0);
1058     reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rx_iscsi_hdig_en_insert(reg_hi, 0);
1059
1060     sfn5122f_rx_desc_ptr_tbl_lo_wr(d, n, reg_lo);
1061     sfn5122f_rx_desc_ptr_tbl_hi_wr(d, n, reg_hi);
1062
1063     return buffer_offset;
1064 }
1065
1066
1067 static uint32_t init_txq(uint16_t n, uint64_t phys,
1068                          bool csum, bool userspace)
1069 {
1070
1071     uint64_t reg, reg1, buffer_offset;
1072   
1073     buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_TX, 0, 0, d);
1074     
1075     if (buffer_offset == -1) {
1076        return -1;
1077     }
1078
1079     DEBUG("TX_QUEUE_%d: buf_off %ld, phys %lx\n",n , buffer_offset, phys);
1080     /* setup TX queue */
1081     reg = sfn5122f_tx_desc_ptr_tbl_lo_rd(d, n);
1082     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_rd(d, n);
1083     /*  Which buffer table entries are used (which is the first entry) */
1084     reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_buf_base_id_insert(reg,
1085                         buffer_offset);
1086     /*  Which event queue is associated with this queue */
1087     reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_evq_id_insert(reg , n);
1088     if (!userspace) {
1089         reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_owner_id_insert(reg, 0);
1090     } else {
1091         reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_owner_id_insert(reg, n+1);
1092     }
1093     reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_label_insert(reg , n);
1094     /*  1024 entries = 1   (512 = 0; 2048 = 2 ; 4096 = 3)   */
1095     reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_size_insert(reg , 3);
1096
1097     /*  No user lvl networking   */
1098     if (!userspace) {
1099         reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_type_insert(reg, 0);
1100     } else {
1101         reg = sfn5122f_tx_desc_ptr_tbl_lo_tx_descq_type_insert(reg, 1);
1102     }
1103
1104     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_tx_iscsi_ddig_en_insert(reg1, 0);
1105     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_tx_iscsi_hdig_en_insert(reg1, 0);
1106    
1107     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_tx_non_ip_drop_dis_insert(reg1, 1);
1108  
1109     /*   Enable queue  */
1110     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_tx_descq_en_insert(reg1 , 1);
1111
1112     /* Enable offload of checksum */
1113     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_tx_ip_chksm_dis_insert(reg1, !csum);
1114     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_tx_tcp_chksm_dis_insert(reg1, !csum);
1115     sfn5122f_tx_desc_ptr_tbl_lo_wr(d, n, reg);
1116     sfn5122f_tx_desc_ptr_tbl_hi_wr(d, n, reg1);
1117  
1118     return buffer_offset;
1119 }
1120
1121
1122 static void setup_interrupt(size_t *msix_index, uint8_t core, uint8_t vector)
1123 {
1124     bool res;
1125     errval_t err;
1126     uint8_t dest;
1127
1128     res = bmallocator_alloc(&msix_alloc, msix_index);
1129     assert(res);
1130
1131     err = get_apicid_from_core(core, &dest);
1132     assert(err_is_ok(err));
1133
1134     err = pci_msix_vector_init(*msix_index, dest, vector);
1135     assert(err_is_ok(err));
1136
1137     DEBUG("MSI-X vector setup index=%"PRIx64", core=%d apic=%d swvec=%x\n",
1138             *msix_index, core, dest, vector);
1139 }
1140
1141 static void resend_interrupt(void* arg)
1142 {
1143     errval_t err;
1144     uint64_t i = (uint64_t) arg;
1145     err = queues[i].devif->tx_vtbl.interrupt(queues[i].devif, NOP_CONT, i);
1146     // If the queue is busy, there is already an oustanding message
1147     if (err_is_fail(err) && err != FLOUNDER_ERR_TX_BUSY) {
1148         USER_PANIC("Error when sending interrupt %s \n", err_getstring(err));
1149     } 
1150 }
1151
1152 /** Here are the global interrupts handled. */
1153 static void global_interrupt_handler(void* arg)
1154 {
1155     //uint64_t reg;
1156     errval_t err;
1157     uint32_t q_to_check;
1158     errval_t syserr;
1159     uint8_t* net_ivec_fatal = (uint8_t *) int_ker_virt;
1160
1161     // bit 64 is indicator for a fatal event
1162     syserr = (net_ivec_fatal[8] & 0x1);
1163     if (syserr) {
1164         // TODO handle fatal interrupt
1165         USER_PANIC("FATAL INTERRUPT");
1166     } else {
1167
1168     }
1169
1170     q_to_check = sfn5122f_int_isr0_reg_lo_rd(d);
1171
1172     for (uint64_t i = 1; i < 32; i++) {
1173         if ((q_to_check >> i) & 0x1) {
1174             if (queues[i].use_irq && queues[i].devif != NULL) {
1175                 DEBUG("Interrupt to queue %lu \n", i);
1176                 err = queues[i].devif->tx_vtbl.interrupt(queues[i].devif, NOP_CONT, i);
1177                 if (err_is_fail(err)) {
1178                     err = queues[i].devif->register_send(queues[i].devif, 
1179                                                          get_default_waitset(),
1180                                                          MKCONT(resend_interrupt, (void*)i));
1181                 }
1182             }
1183         }
1184     }
1185
1186     if (q_to_check & 0x1) {
1187         DEBUG("Interrupt to queue 0 \n");
1188         check_queue_0();
1189     }
1190
1191
1192    
1193     // Don't need to start event queues because we're already polling
1194
1195 }
1196 /******************************************************************************/
1197 /* Management interface implemetation */
1198
1199 static void idc_queue_init_data(struct sfn5122f_binding *b,
1200                                 struct capref registers,
1201                                 uint64_t macaddr)
1202 {
1203     errval_t r;
1204
1205     r = sfn5122f_queue_init_data__tx(b, NOP_CONT, registers, macaddr);
1206     // TODO: handle busy
1207     assert(err_is_ok(r));
1208 }
1209
1210 /** Tell queue driver that we are done initializing the queue. */
1211 static void idc_queue_memory_registered(struct sfn5122f_binding *b)
1212 {
1213     errval_t r;
1214     r = sfn5122f_queue_memory_registered__tx(b, NOP_CONT);
1215     // TODO: handle busy
1216     assert(err_is_ok(r));
1217 }
1218
1219 /** Send request to queue driver to rewrite the tail pointers of its queues. */
1220 static void idc_write_queue_tails(struct sfn5122f_binding *b)
1221 {
1222     errval_t r;
1223     if (b == NULL) {
1224         qd_write_queue_tails(b);
1225         return;
1226     }
1227
1228     r = sfn5122f_write_queue_tails__tx(b, NOP_CONT);
1229     // TODO: handle busy
1230     assert(err_is_ok(r));
1231 }
1232
1233 /** Request from queue driver for register memory cap */
1234 void cd_request_device_info(struct sfn5122f_binding *b)
1235 {
1236     if (b == NULL) {
1237         qd_queue_init_data(b, *regframe, d_mac[pci_function]);
1238         return;
1239     }
1240     idc_queue_init_data(b, *regframe, d_mac[pci_function]);
1241 }
1242
1243 /** Request from queue driver to initialize hardware queue. */
1244 void cd_register_queue_memory(struct sfn5122f_binding *b,
1245                               uint16_t n,
1246                               struct capref tx_frame,
1247                               struct capref rx_frame,
1248                               struct capref ev_frame,
1249                               uint32_t rxbufsz,
1250                               bool use_irq,
1251                               bool userspace,
1252                               uint8_t vector,
1253                               uint16_t core)
1254 {
1255     // Save state so we can restore the configuration in case we need to do a
1256     // reset
1257     errval_t err;
1258
1259     bool failed = 0;
1260     queues[n].enabled = false;
1261     queues[n].tx_frame = tx_frame;
1262     queues[n].rx_frame = rx_frame;
1263     queues[n].ev_frame = ev_frame;
1264     queues[n].tx_head = 0;
1265     queues[n].rx_head = 0;
1266     queues[n].ev_head = 0;
1267     queues[n].rxbufsz = rxbufsz;
1268     queues[n].binding = b;
1269     queues[n].use_irq = use_irq;
1270     queues[n].userspace = userspace;
1271     queues[n].msix_index = -1;
1272     queues[n].msix_intvec = vector;
1273     queues[n].msix_intdest = core;
1274
1275     struct frame_identity id;
1276     err = invoke_frame_identify(ev_frame, &id);
1277     assert(err_is_ok(err));
1278     queues[n].ev_buf_tbl = init_evq(n, id.base, use_irq);
1279
1280
1281     // enable checksums
1282     err = invoke_frame_identify(tx_frame, &id);
1283     assert(err_is_ok(err));
1284     queues[n].tx_buf_tbl = init_txq(n, id.base, csum_offload, userspace);
1285
1286     err = invoke_frame_identify(rx_frame, &id);
1287     assert(err_is_ok(err));
1288     queues[n].rx_buf_tbl = init_rxq(n, id.base, userspace);
1289
1290
1291     if(queues[n].ev_buf_tbl == -1 ||
1292        queues[n].tx_buf_tbl == -1 ||
1293        queues[n].rx_buf_tbl == -1){
1294        failed = 1;
1295        DEBUG("Allocating queue failed \n");
1296        return;
1297     }
1298
1299     queues[n].enabled = true;
1300
1301     if (queues[n].use_irq) {
1302         if (queues[n].msix_intvec != 0) {
1303             if (queues[n].msix_index == -1) {
1304                 setup_interrupt(&queues[n].msix_index, queues[n].msix_intdest,
1305                                 queues[n].msix_intvec);
1306             }
1307         }
1308     }
1309
1310     idc_write_queue_tails(queues[n].binding);
1311
1312     if (b == NULL) {
1313         qd_queue_memory_registered(b);
1314         return;
1315     }
1316
1317     idc_queue_memory_registered(b);
1318
1319     if (first){
1320        start_all();
1321        first = 0;
1322     }
1323 }
1324
1325 static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref frame,
1326                             bool user, bool interrupt, uint8_t core, uint8_t msix_vector)
1327 {
1328     DEBUG("cd_create_queue \n");
1329     errval_t err;
1330     struct frame_identity id;
1331
1332     int n = -1;
1333     for (int i = 1; i < NUM_QUEUES; i++) {
1334         if (queues[i].enabled == false) {
1335             n = i;
1336             break;
1337         }
1338     }
1339
1340     if (n == -1) {
1341         err = NIC_ERR_ALLOC_QUEUE;
1342         err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, 0, NULL_CAP, err);
1343         //err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, err);
1344         assert(err_is_ok(err));
1345     }
1346     
1347     queues[n].use_irq = interrupt;
1348     queues[n].enabled = false;
1349     queues[n].tx_frame = frame;
1350     queues[n].tx_head = 0;
1351     queues[n].rx_head = 0;
1352     queues[n].ev_head = 0;
1353     queues[n].rxbufsz = MTU_MAX;
1354     queues[n].devif = b;
1355     queues[n].userspace = user;
1356     queues[n].msix_index = -1;
1357     queues[n].msix_intdest = core;
1358     queues[n].msix_intvec = msix_vector;
1359
1360     if (queues[n].use_irq && use_msix) {
1361         if (queues[n].msix_intvec != 0) {
1362             if (queues[n].msix_index == -1) {
1363                 setup_interrupt(&queues[n].msix_index, queues[n].msix_intdest,
1364                                 queues[n].msix_intvec);
1365             }
1366         }
1367     }
1368
1369     err = invoke_frame_identify(frame, &id);
1370     assert(err_is_ok(err));
1371     // enable checksums
1372     queues[n].tx_buf_tbl = init_txq(n, id.base, csum_offload, user);
1373     queues[n].rx_buf_tbl = init_rxq(n, id.base+ sizeof(uint64_t)*TX_ENTRIES, user);
1374
1375     queues[n].ev_buf_tbl = init_evq(n, id.base+sizeof(uint64_t)*(TX_ENTRIES+RX_ENTRIES), 
1376                                     interrupt);
1377     if(queues[n].ev_buf_tbl == -1 ||
1378        queues[n].tx_buf_tbl == -1 ||
1379        queues[n].rx_buf_tbl == -1){
1380         err = NIC_ERR_ALLOC_QUEUE;
1381         //err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, err);
1382         err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, 0, NULL_CAP, err);
1383         assert(err_is_ok(err));
1384     }
1385
1386     queues[n].enabled = true;
1387     DEBUG("created queue %d \n", n);
1388     //err = b->tx_vtbl.create_queue_response(b, NOP_CONT, n, *regframe, SYS_ERR_OK);a
1389
1390     struct capref regs;
1391     err = slot_alloc(&regs);
1392     assert(err_is_ok(err));
1393     err = cap_copy(regs, *regframe);
1394     assert(err_is_ok(err));
1395
1396     err = b->tx_vtbl.create_queue_response(b, NOP_CONT, d_mac[pci_function], n, 
1397                                            regs, SYS_ERR_OK);
1398     assert(err_is_ok(err));
1399     DEBUG("cd_create_queue end\n");
1400 }
1401
1402 static void cd_register_region(struct sfn5122f_devif_binding *b, uint16_t qid,
1403                                struct capref region)
1404 {
1405     errval_t err;
1406     struct frame_identity id;
1407     uint64_t buffer_offset = 0;
1408
1409     err = invoke_frame_identify(region, &id);
1410     if (err_is_fail(err)) {
1411         err = b->tx_vtbl.register_region_response(b, NOP_CONT, 0, NIC_ERR_REGISTER_REGION);
1412         assert(err_is_ok(err));
1413     }
1414
1415     size_t size = id.bytes;
1416     lpaddr_t addr = id.base;
1417
1418     // TODO unsigned/signed 
1419     buffer_offset = alloc_buf_tbl_entries(addr, size/BUF_SIZE, qid, true, d);
1420     if (buffer_offset == -1) {
1421         err = b->tx_vtbl.register_region_response(b, NOP_CONT, 0, NIC_ERR_REGISTER_REGION);
1422         assert(err_is_ok(err));
1423     }
1424     
1425     err = b->tx_vtbl.register_region_response(b, NOP_CONT, buffer_offset, SYS_ERR_OK);
1426     if (err_is_fail(err)) {
1427        
1428     }
1429 }
1430
1431
1432 static void cd_deregister_region(struct sfn5122f_devif_binding *b, uint64_t buftbl_id,
1433                                  uint64_t size)
1434 {
1435     errval_t err;
1436     free_buf_tbl_entries(buftbl_id, size/BUF_SIZE, d);
1437    
1438     err = b->tx_vtbl.deregister_region_response(b, NOP_CONT, SYS_ERR_OK);
1439     assert(err_is_ok(err));
1440 }
1441
1442 static void cd_destroy_queue(struct sfn5122f_devif_binding *b, uint16_t qid)
1443 {
1444     errval_t err;
1445     queue_hw_stop(qid);
1446
1447     queues[qid].enabled = false;
1448     queues[qid].binding = NULL;
1449
1450     err = b->tx_vtbl.destroy_queue_response(b, NOP_CONT, SYS_ERR_OK);
1451     assert(err_is_ok(err));
1452 }
1453
1454
1455 static struct sfn5122f_devif_rx_vtbl rx_vtbl_devif = {
1456     .create_queue_call = cd_create_queue,
1457     .destroy_queue_call = cd_destroy_queue,
1458     .register_region_call = cd_register_region,
1459     .deregister_region_call = cd_deregister_region,
1460 };
1461
1462 static void export_devif_cb(void *st, errval_t err, iref_t iref)
1463 {
1464     const char *suffix = "_sfn5122fmng_devif";
1465     char name[strlen(service_name) + strlen(suffix) + 1];
1466
1467     assert(err_is_ok(err));
1468
1469     // Build label for interal management service
1470     sprintf(name, "%s%s", service_name, suffix);
1471
1472     err = nameservice_register(name, iref);
1473     assert(err_is_ok(err));
1474     DEBUG("Devif Management interface exported\n");
1475     initialized = true;
1476 }
1477
1478
1479 static errval_t connect_devif_cb(void *st, struct sfn5122f_devif_binding *b)
1480 {
1481     DEBUG("New connection on devif management interface\n");
1482     b->rx_vtbl = rx_vtbl_devif;
1483     return SYS_ERR_OK;
1484 }
1485
1486
1487 /****************************************************************************/
1488 /* Net filter interface implementation                                      */
1489 /****************************************************************************/
1490
1491
1492 static errval_t cb_install_filter(struct net_filter_binding *b,
1493                                   net_filter_filter_type_t type,
1494                                   uint64_t qid,
1495                                   uint32_t src_ip,
1496                                   uint32_t dst_ip,
1497                                   uint16_t src_port,
1498                                   uint16_t dst_port,
1499                                   uint64_t* fid)
1500 {
1501     struct sfn5122f_filter_ip f = {
1502             .dst_port = dst_port,
1503             .src_port = src_port,
1504             .dst_ip = htonl(dst_ip),
1505             .src_ip = htonl(src_ip),
1506             .type_ip = type,
1507             .queue = qid,
1508     };
1509
1510
1511     errval_t err = reg_port_filter(&f, fid);
1512     assert(err_is_ok(err));
1513     DEBUG("filter registered: err=%"PRIu64", fid=%"PRIu64"\n", err, *fid);
1514     return SYS_ERR_OK;
1515 }
1516
1517
1518 static errval_t cb_remove_filter(struct net_filter_binding *b,
1519                                  net_filter_filter_type_t type,
1520                                  uint64_t filter_id,
1521                                  errval_t* err)
1522 {
1523     if ((type == net_filter_PORT_UDP || type == net_filter_PORT_TCP)
1524         && filters_rx_ip[filter_id].enabled == true) {
1525         filters_rx_ip[filter_id].enabled = false;  
1526
1527         sfn5122f_rx_filter_tbl_lo_wr(d, filter_id, 0);
1528         sfn5122f_rx_filter_tbl_hi_wr(d, filter_id, 0);
1529         *err = SYS_ERR_OK;
1530     } else {
1531         *err = NET_FILTER_ERR_NOT_FOUND;
1532     }
1533
1534     DEBUG("unregister_filter: called (%"PRIx64")\n", filter_id);
1535     return SYS_ERR_OK;
1536 }
1537
1538 static struct net_filter_rpc_rx_vtbl net_filter_rpc_rx_vtbl = {
1539     .install_filter_ip_call = cb_install_filter,
1540     .remove_filter_call = cb_remove_filter,
1541     .install_filter_mac_call = NULL,
1542 };
1543
1544 static void net_filter_export_cb(void *st, errval_t err, iref_t iref)
1545 {
1546
1547     printf("exported net filter interface\n");
1548     err = nameservice_register("net_filter_sfn5122f", iref);
1549     assert(err_is_ok(err));
1550     DEBUG("Net filter interface exported\n");
1551 }
1552
1553
1554 static errval_t net_filter_connect_cb(void *st, struct net_filter_binding *b)
1555 {
1556     printf("New connection on net filter interface\n");
1557     b->rpc_rx_vtbl = net_filter_rpc_rx_vtbl;
1558     return SYS_ERR_OK;
1559 }
1560
1561 /**
1562  * Initialize management interface for queue drivers.
1563  * This has to be done _after_ the hardware is initialized.
1564  */
1565 static void initialize_mngif(void)
1566 {
1567     errval_t r;
1568
1569     /*
1570     r = sfn5122f_export(NULL, export_cb, connect_cb, get_default_waitset(),
1571                     IDC_BIND_FLAGS_DEFAULT);
1572     assert(err_is_ok(r));
1573     */
1574     r = sfn5122f_devif_export(NULL, export_devif_cb, connect_devif_cb,
1575                               get_default_waitset(), 1);
1576     assert(err_is_ok(r));
1577
1578     r = net_filter_export(NULL, net_filter_export_cb, net_filter_connect_cb,
1579                           get_default_waitset(), 1);
1580     assert(err_is_ok(r));
1581 }
1582
1583 /******************************************************************************/
1584 /* Initialization code for driver */
1585
1586 /** Callback from pci to initialize a specific PCI device. */
1587 static void pci_init_card(struct device_mem* bar_info, int bar_count)
1588 {
1589     errval_t err;
1590     bool res;
1591
1592     d = malloc(sizeof(*d));
1593     /* Map first BAR for register access */
1594     assert(bar_count >= 1);
1595     DEBUG("BAR count %d \n", bar_count);
1596     map_device(&bar_info[0]);
1597     regframe = bar_info[0].frame_cap;
1598     DEBUG("BAR[0] mapped (v=%llx p=%llx l=%llx)\n",
1599             (unsigned long long) bar_info[0].vaddr,
1600             (unsigned long long) bar_info[0].paddr,
1601             (unsigned long long) bar_info[0].bytes);
1602
1603     /* Initialize Mackerel binding */
1604     sfn5122f_initialize(d, (void*) bar_info[0].vaddr);
1605     d_virt = bar_info[0].vaddr;
1606
1607     // Initialize manager for MSI-X vectors
1608     if (use_msix) {
1609         //d_msix = malloc(sizeof(*d_msix));
1610         //map_device(&bar_info[1]);
1611         //sfn5122f_msix_initialize(d_msix, (void*) bar_info[1].vaddr);
1612         DEBUG("Enabling MSI-X interrupts\n");
1613         uint16_t msix_count = 0;
1614         err = pci_msix_enable(&msix_count);
1615         assert(err_is_ok(err));
1616         assert(msix_count > 0);
1617         DEBUG("MSI-X #vecs=%d\n", msix_count);
1618
1619         res = bmallocator_init(&msix_alloc, msix_count);
1620         assert(res);
1621     } else {
1622         DEBUG("Using legacy interrupts\n");
1623     }
1624
1625     /* Get all information needed  */
1626     probe_all();
1627     /* Initialize hardware registers etc. */
1628     /* Start interrups / mac_stats etc.  */
1629     device_init();
1630     /* Init rx filters */
1631     init_rx_filter_config();
1632     /* initalize managemnt interface   */
1633     initialize_mngif();
1634
1635     if (first){
1636        start_all();
1637        first = 0;
1638     }
1639 }
1640
1641 static void parse_cmdline(int argc, char **argv)
1642 {
1643     /*
1644      * XXX: the following contains a hack only to start the driver when
1645      *      the supplied bus/dev/funct matches the Kaluga start arguments.
1646      */
1647     int i;
1648     uint32_t tmp;
1649     for (i = 1; i < argc; i++) {
1650         if (strncmp(argv[i], "cardname=", strlen("cardname=") - 1) == 0) {
1651             service_name = argv[i] + strlen("cardname=");
1652         } else if (strncmp(argv[i], "bus=", strlen("bus=") - 1) == 0) {
1653             tmp = atol(argv[i] + strlen("bus="));
1654             if (pci_bus == PCI_DONT_CARE) {
1655                 pci_bus = tmp;
1656             }
1657
1658             if (pci_bus != tmp) {
1659                 printf("DRIVER STARTED FOR BUS: 0x%x/0x%x\n", pci_bus, tmp);
1660                 exit(1);
1661             }
1662             pci_bus = atol(argv[i] + strlen("bus="));
1663         } else if (strncmp(argv[i], "device=", strlen("device=") - 1) == 0) {
1664             tmp = atol(argv[i] + strlen("device="));
1665             if (pci_device == PCI_DONT_CARE) {
1666                 pci_device = tmp;
1667             }
1668
1669             if (pci_device != tmp) {
1670                 printf("DRIVER STARTED FOR DEVICE: 0x%x/0x%x\n", pci_device, tmp);
1671                 exit(1);
1672             }
1673
1674         } else if (strncmp(argv[i], "function=", strlen("function=") - 1) == 0){
1675             tmp = atol(argv[i] + strlen("function="));
1676             if (pci_function == PCI_DONT_CARE) {
1677                 pci_function = tmp;
1678             }
1679
1680             if (pci_function != tmp) {
1681                 printf("DRIVER STARTED FOR FUNCTION: 0x%x/0x%x\n", pci_bus, tmp);
1682                 exit(1);
1683             }
1684
1685             if (pci_function != 0) {
1686                 USER_PANIC("Second port not implemented, please use function=0")
1687             }
1688         } else if (strncmp(argv[i], "msix=", strlen("msix=") - 1) == 0){
1689             USER_PANIC("MSI-X not fully supported yet");
1690             use_msix = !!atol(argv[i] + strlen("msix="));
1691             //qd_rgument(argv[i]);
1692         } else {
1693             printf("Unrecognized argument %s ignored \n", argv[i]);
1694             continue;
1695         }
1696     }
1697 }
1698
1699 static void eventloop(void)
1700 {
1701     struct waitset *ws;
1702
1703     ws = get_default_waitset();
1704     DEBUG("SFN5122F enter event loop \n");
1705     while (1) {
1706         event_dispatch(ws);
1707     }
1708 }
1709
1710 static void cd_main(void)
1711 {
1712     eventloop();
1713 }
1714
1715
1716 int main(int argc, char** argv)
1717 {
1718     DEBUG("SFN5122F driver started \n");
1719     errval_t err;
1720
1721     if (argc > 1) {
1722         uint32_t parsed = sscanf(argv[argc - 1], "%x:%x:%x:%x:%x", &pci_vendor,
1723                                  &pci_devid, &pci_bus, &pci_device, &pci_function);
1724         if (parsed != 5) {
1725             pci_vendor = PCI_DONT_CARE;
1726             pci_devid = PCI_DONT_CARE;
1727             pci_bus = PCI_DONT_CARE;
1728             pci_device = PCI_DONT_CARE;
1729             pci_function = 0;
1730         } else {
1731             if ((pci_vendor != PCI_VENDOR_SOLARFLARE) || (pci_devid != DEVICE_ID)) {
1732                 printf("VENDOR/DEVICE ID MISMATCH: %x/%x %x/%x\n",
1733                         pci_vendor, PCI_VENDOR_SOLARFLARE, pci_devid, DEVICE_ID);
1734             }
1735             argc--;
1736         }
1737     }
1738
1739     parse_cmdline(argc, argv);
1740
1741
1742     /* Register our device driver */
1743     err = pci_client_connect();
1744     assert(err_is_ok(err));
1745     err = pci_register_driver_irq(pci_init_card, PCI_CLASS_ETHERNET,
1746                                 PCI_DONT_CARE, PCI_DONT_CARE,
1747                                 pci_vendor, pci_devid,
1748                                 pci_bus, pci_device, pci_function,
1749                                 global_interrupt_handler, NULL);
1750
1751     while (!initialized) {
1752         event_dispatch(get_default_waitset());
1753     }
1754
1755     init_queue_0("sfn5122f", d_mac[pci_function], d_virt,
1756                  use_interrupt, false, &queues[0].ev_frame, 
1757                  &queues[0].tx_frame, &queues[0].rx_frame);
1758
1759     queues[0].enabled = false;
1760     queues[0].tx_head = 0;
1761     queues[0].rx_head = 0;
1762     queues[0].ev_head = 0;
1763     queues[0].rxbufsz = MTU_MAX;
1764     queues[0].binding = NULL;
1765     queues[0].use_irq = true;
1766     queues[0].userspace = false;
1767
1768     struct frame_identity id;
1769     err = invoke_frame_identify(queues[0].ev_frame, &id);
1770     assert(err_is_ok(err));
1771     queues[0].ev_buf_tbl = init_evq(0, id.base, queues[0].use_irq);
1772     // enable checksums
1773     err = invoke_frame_identify(queues[0].tx_frame, &id);
1774     assert(err_is_ok(err));
1775     queues[0].tx_buf_tbl = init_txq(0, id.base, csum_offload, false);
1776
1777     err = invoke_frame_identify(queues[0].rx_frame, &id);
1778     assert(err_is_ok(err));
1779     queues[0].rx_buf_tbl = init_rxq(0, id.base, false);
1780
1781     write_queue_tails();
1782
1783     start_all();    
1784     
1785     /* loop myself */
1786     cd_main();
1787 }