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