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