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