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