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