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