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 , ®, 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 , ®, 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, ®s, &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