1 /* Copyright (c) 2007-2011, ETH Zurich.
4 * This file is distributed under the terms in the attached LICENSE file.
5 * If you do not find this file, copies can be found by writing to:
6 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 #include <net_queue_manager/net_queue_manager.h>
13 #include <barrelfish/nameservice_client.h>
14 #include <barrelfish/spawn_client.h>
15 #include <barrelfish/debug.h>
16 #include <barrelfish/deferred.h>
20 #include <if/sfn5122f_defs.h>
21 #include <dev/sfn5122f_dev.h>
22 #include <dev/sfn5122f_q_dev.h>
26 #include "sfn5122f_queue.h"
27 #include "sfn5122f_debug.h"
28 #include "buffer_tbl.h"
30 /******************************************************************************/
33 static void idc_register_queue_memory(uint8_t queue,
34 struct capref tx_frame,
35 struct capref ev_frame,
36 struct capref rx_frame,
41 static void idc_terminate_queue(void);
43 void qd_queue_init_data(struct sfn5122f_binding *b, struct capref registers,
45 void qd_queue_memory_registered(struct sfn5122f_binding *b);
46 void qd_write_queue_tails(struct sfn5122f_binding *b);
48 void qd_argument(const char *arg);
50 int main(int argc, char **argv) __attribute__((weak));
53 static const char* service_name = "sfn5122f";
55 /** Binding to the internal sfn5122f management service */
56 static struct sfn5122f_binding *binding = NULL;
58 /** Queue index for this manager instance */
61 /** Mackerel handle for device */
62 static sfn5122f_t *d = NULL;
64 /** Queue handle for queue management library */
65 static sfn5122f_queue_t *q;
67 /** MAC address to be used */
68 static uint64_t mac_address = 0;
70 /** Indicates if the initialization is done */
71 static int initialized = 0;
74 * Indicates whether we should rely on cache coherence for the descriptor
77 static bool cache_coherence = true;
79 /** Indicates whether Interrupts should be used */
80 static bool use_interrupts = false;
81 static bool use_msix = false;
82 static coreid_t core = 0;
83 static uint8_t vector = 0;
85 /** Capability for hardware TX ring */
86 static struct capref tx_frame;
88 /** Capability for hardware RX ring */
89 static struct capref rx_frame;
91 /** Capability for hardware EV ring */
92 static struct capref ev_frame;
94 //static void* mac_virt;
95 uint64_t mac_stats_array[NUM_MAC_STATS];
97 /** Userspace networking enable */
98 static bool userspace = 0;
100 /******************************************************************************/
102 static uint64_t find_tx_free_slot_count_fn(void)
104 return sfn5122f_queue_free_txslots(q);
107 static errval_t transmit_pbuf_list_fn(struct driver_buffer *buffers,
112 if (find_tx_free_slot_count_fn() < count) {
113 return ETHERSRV_ERR_CANT_TRANSMIT;
116 for (i = 0; i < count; i++) {
117 sfn5122f_queue_add_txbuf(q, buffers[i].pa,
118 buffers[i].len, buffers[i].opaque,
122 sfn5122f_queue_bump_txtail(q);
127 static bool handle_free_tx_slot_fn(void)
134 /******************************************************************************/
137 static uint64_t find_rx_free_slot_count_fn(void)
139 return sfn5122f_queue_free_rxslots(q);
142 static errval_t register_rx_buffer_fn(uint64_t paddr, void *vaddr, void *opaque)
144 if (find_rx_free_slot_count_fn() == 0) {
145 printf("SFN5122F_%d: Not enough space in RX ring, not adding buffer\n",
147 return ETHERSRV_ERR_TOO_MANY_BUFFERS;
150 sfn5122f_queue_add_rxbuf(q, paddr, opaque);
151 sfn5122f_queue_bump_rxtail(q);
157 /* polling event queue for new events */
158 static size_t check_for_new_events(void)
164 struct driver_rx_buffer buf[16];
166 // need to block until initalized
171 ev_code = sfn5122f_get_event_code(q);
172 while (ev_code != 15 && count < 100){
174 ev_code = sfn5122f_get_event_code(q);
178 // TODO multiple packets
179 if (sfn5122f_queue_handle_rx_ev(q, &op, &len) == SYS_ERR_OK) {
182 process_received_packet(buf, 1, 0);
184 // TODO how to tell the the upper layer that it can reuse
188 DEBUG_QUEUE(" RX_EV Q_ID: %d len %ld \n", qi, len);
189 sfn5122f_queue_bump_evhead(q);
192 if (sfn5122f_queue_handle_tx_ev(q, &op) == SYS_ERR_OK) {
193 DEBUG_QUEUE("TX EVENT OK %d \n", qi);
196 DEBUG_QUEUE("TX EVENT ERR %d \n", qi);
198 sfn5122f_queue_bump_evhead(q);
201 //DEBUG_QUEUE("DRIVER EVENT %d\n", qi);
202 sfn5122f_handle_drv_ev(q, qi);
203 sfn5122f_queue_bump_evhead(q);
205 case EV_CODE_DRV_GEN:
206 DEBUG_QUEUE("DRIVER GENERATED EVENT \n");
207 sfn5122f_queue_bump_evhead(q);
210 DEBUG_QUEUE("USER EVENT \n");
211 sfn5122f_queue_bump_evhead(q);
214 //DEBUG_QUEUE("MCDI EVENT \n");
215 sfn5122f_queue_handle_mcdi_event(q);
216 sfn5122f_queue_bump_evhead(q);
219 DEBUG_QUEUE("GLOBAL EVENT \n");
220 sfn5122f_queue_bump_evhead(q);
225 /* update event queue tail */
227 sfn5122f_evq_rptr_reg_wr(d, qi, q->ev_head);
234 static errval_t update_rxtail(void *opaque, size_t tail)
239 reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_wptr_insert(reg, tail);
240 /* don't want to push an additional rx descriptor with the write pointer */
241 reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_push_cmd_insert(reg, 0);
242 /* the lower register will be ignored */
243 sfn5122f_rx_desc_upd_reg_lo_wr(d, qi, 0);
244 sfn5122f_rx_desc_upd_reg_hi_wr(d, qi, reg);
249 static errval_t update_txtail(void *opaque, size_t tail)
253 reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_wptr_insert(reg, tail);
254 /* don't want to push an additional tx descriptor with the write pointer */
255 reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_push_cmd_insert(reg, 0);
256 reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_insert(reg, 0);
258 /* the lower register will be ignored */
259 sfn5122f_tx_desc_upd_reg_lo_wr(d, qi, 0);
260 sfn5122f_tx_desc_upd_reg_hi_wr(d, qi, reg);
264 /** Callback to get card's MAC address */
265 static void get_mac_address_fn(uint8_t* mac)
267 memcpy(mac, &mac_address, 6);
269 /******************************************************************************/
272 static void qd_interrupt(void)
276 count = check_for_new_events();
278 DEBUG_QUEUE("qd_int_%d: qid=%d no events \n", disp_get_core_id(), qi);
280 DEBUG_QUEUE("qd_int_%d: qid=%d events processed=%ld \n", disp_get_core_id(),
286 static void interrupt_handler(void *data)
291 /******************************************************************************/
292 /* Device/queue initialization */
294 /** Allocate queue n and return handle for queue manager */
296 static void setup_queue(void)
298 size_t tx_size, rx_size, ev_size;
299 void *tx_virt, *rx_virt, *ev_virt;
300 vregion_flags_t flags_vreg;
302 struct sfn5122f_queue_ops ops = {
303 .update_txtail = update_txtail,
304 .update_rxtail = update_rxtail
307 // Decide on which flags to use for the mappings
308 flags_vreg = (cache_coherence ? VREGION_FLAGS_READ_WRITE :
309 VREGION_FLAGS_READ_WRITE_NOCACHE);
312 /* Allocate memory for descriptor rings
313 No difference for userspace networking*/
314 tx_size = sfn5122f_q_tx_ker_desc_size * TX_ENTRIES;
315 tx_virt = alloc_map_frame(flags_vreg, tx_size, &tx_frame);
317 assert(tx_virt != NULL);
320 rx_size = sfn5122f_q_rx_ker_desc_size * RX_ENTRIES;
322 rx_size = sfn5122f_q_rx_user_desc_size * RX_ENTRIES;
325 rx_virt = alloc_map_frame(flags_vreg, rx_size, &rx_frame);
326 assert(rx_virt != NULL);
328 ev_size = sfn5122f_q_event_entry_size * EV_ENTRIES;
329 ev_virt = alloc_map_frame(flags_vreg, ev_size, &ev_frame);
330 assert(ev_virt != NULL);
332 if (use_interrupts && use_msix) {
333 DEBUG_QUEUE("Enabling MSI-X interrupts\n");
334 errval_t err = pci_setup_inthandler(interrupt_handler, NULL, &vector);
335 assert(err_is_ok(err));
336 core = disp_get_core_id();
338 if (use_interrupts) {
339 DEBUG_QUEUE("Enabling legacy interrupts\n");
346 // Initialize queue manager
347 q = sfn5122f_queue_init(tx_virt, TX_ENTRIES, rx_virt, RX_ENTRIES,
348 ev_virt, EV_ENTRIES, &ops, NULL, userspace);
349 idc_register_queue_memory(qi, tx_frame, rx_frame,
350 ev_frame, MTU_MAX, vector, core);
354 /** Terminate this queue driver */
355 static void terminate_queue_fn(void)
357 idc_terminate_queue();
360 /******************************************************************************/
361 /* Management interface implemetation */
363 /** Request device register cap from card driver */
365 static void idc_request_device_info(void)
369 DEBUG_QUEUE("idc_request_device_info()\n");
371 r = sfn5122f_request_device_info__tx(binding, NOP_CONT);
373 assert(err_is_ok(r));
376 /** Send memory caps to card driver */
377 static void idc_register_queue_memory(uint8_t queue,
387 DEBUG_QUEUE("idc_register_queue_memory()\n");
389 r = sfn5122f_register_queue_memory__tx(binding, NOP_CONT, queue,
391 use_interrupts, userspace,
394 assert(err_is_ok(r));
397 // Callback from device manager
398 void qd_queue_init_data(struct sfn5122f_binding *b, struct capref registers,
401 struct frame_identity frameid = { .base = 0, .bytes = 0 };
405 DEBUG_QUEUE("idc_queue_init_data\n");
407 mac_address = macaddr;
409 // Map device registers
410 invoke_frame_identify(registers, &frameid);
411 err = vspace_map_one_frame_attr(&virt, frameid.bytes, registers,
412 VREGION_FLAGS_READ_WRITE_NOCACHE, NULL, NULL);
414 assert(err_is_ok(err));
416 // Initialize mackerel device
417 d = malloc(sizeof(*d));
418 sfn5122f_initialize(d, virt);
423 /** Tell card driver to stop this queue. */
424 static void idc_terminate_queue(void)
427 DEBUG_QUEUE("idc_terminate_queue()\n");
429 r = sfn5122f_terminate_queue__tx(binding, NOP_CONT, qi);
431 assert(err_is_ok(r));
434 // Callback from device manager
435 void qd_queue_memory_registered(struct sfn5122f_binding *b)
438 // Register queue with queue_mgr library
439 DEBUG_QUEUE("Called ethersrv_init() \n");
440 ethersrv_init((char*) service_name, qi,
443 transmit_pbuf_list_fn,
444 find_tx_free_slot_count_fn,
445 handle_free_tx_slot_fn,
447 register_rx_buffer_fn,
448 find_rx_free_slot_count_fn);
451 // Callback from device manager
452 void qd_write_queue_tails(struct sfn5122f_binding *b)
454 DEBUG_QUEUE("idc_write_queue_tails()\n");
456 sfn5122f_queue_bump_rxtail(q);
457 sfn5122f_queue_bump_txtail(q);
461 // Callback from device manager
462 static void idc_queue_terminated(struct sfn5122f_binding *b)
466 DEBUG_QUEUE("idc_queue_terminated()\n");
468 // Free memory for hardware ring buffers
470 err = vspace_unmap(q->tx_ring.user);
471 assert(err_is_ok(err));
472 err = vspace_unmap(q->rx_ring.user);
473 assert(err_is_ok(err));
475 err = vspace_unmap(q->tx_ring.ker);
476 assert(err_is_ok(err));
477 err = vspace_unmap(q->rx_ring.ker);
478 assert(err_is_ok(err));
481 err = vspace_unmap(q->ev_ring);
482 assert(err_is_ok(err));
483 err = cap_delete(tx_frame);
484 assert(err_is_ok(err));
485 err = cap_delete(rx_frame);
486 assert(err_is_ok(err));
487 err = cap_delete(ev_frame);
488 assert(err_is_ok(err));
493 static struct sfn5122f_rx_vtbl rx_vtbl = {
494 .queue_init_data = qd_queue_init_data,
495 .queue_memory_registered = qd_queue_memory_registered,
496 .write_queue_tails = qd_write_queue_tails,
497 .queue_terminated = idc_queue_terminated,
500 static void bind_cb(void *st, errval_t err, struct sfn5122f_binding *b)
502 assert(err_is_ok(err));
504 DEBUG_QUEUE("Sucessfully connected to management interface\n");
506 b->rx_vtbl = rx_vtbl;
509 idc_request_device_info();
512 /** Connect to the management interface */
513 static void connect_to_mngif(void)
517 const char *suffix = "_sfn5122fmng";
518 char name[strlen(service_name) + strlen(suffix) + 1];
520 // Build label for interal management service
521 sprintf(name, "%s%s", service_name, suffix);
523 // Connect to service
524 DEBUG_QUEUE("Looking up management interface (%s)\n", name);
525 r = nameservice_blocking_lookup(name, &iref);
526 assert(err_is_ok(r));
528 DEBUG_QUEUE("Binding to management interface\n");
529 r = sfn5122f_bind(iref, bind_cb, NULL, get_default_waitset(),
530 IDC_BIND_FLAGS_DEFAULT);
531 assert(err_is_ok(r));
534 void qd_argument(const char *arg)
536 if (strncmp(arg, "cardname=", strlen("cardname=") - 1) == 0) {
537 service_name = arg + strlen("cardname=");
538 ethersrv_argument(arg);
540 } else if (strncmp(arg, "queue=", strlen("queue=") - 1) == 0) {
541 qi = atol(arg + strlen("queue="));
542 ethersrv_argument(arg);
544 } else if (strncmp(arg, "cache_coherence=",
545 strlen("cache_coherence=") - 1) == 0) {
546 cache_coherence = !!atol(arg + strlen("cache_coherence="));
548 } else if (strncmp(arg, "interrupts=", strlen("interrupts=") - 1) == 0) {
549 use_interrupts = !!atol(arg + strlen("interrupts="));
550 DEBUG_QUEUE("Interrupts enabled: legacy interrupts for fatal device errors\n");
551 } else if (strncmp(arg, "msix=", strlen("msix=") - 1) == 0) {
552 USER_PANIC("MSI-X not fully implemented yet!");
553 use_msix = !!atol(arg + strlen("msix="));
554 DEBUG_QUEUE("Using msix \n");
555 } else if (strncmp(arg, "userspace=", strlen("userspace=") - 1) == 0) {
556 USER_PANIC("Userspace networking for SFN5122F not implemented!");
558 userspace = atol(arg + strlen("userspace="));
559 ethersrv_argument(arg);
562 ethersrv_argument(arg);
566 static void parse_cmdline(int argc, char **argv)
569 for (i = 1; i < argc; i++) {
570 qd_argument(argv[i]);
574 static void eventloop(void)
579 DEBUG_QUEUE("eventloop()\n");
581 ws = get_default_waitset();
583 err = event_dispatch_non_block(ws);
584 do_pending_work_for_all();
585 check_for_new_events();
589 static void eventloop_ints(void)
592 DEBUG_QUEUE("eventloop_ints()\n");
594 ws = get_default_waitset();
597 do_pending_work_for_all();
603 // Validate some settings
605 USER_PANIC("For queue driver the queue= parameter has to be specified "
606 "on the command line!");
611 if (use_interrupts) {
618 int main(int argc, char **argv)
620 DEBUG_QUEUE("Started\n");
621 parse_cmdline(argc, argv);