Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/nic/src/nic_driver.c

    r77ad86c r49bd793b  
    4646#include <ipc/irc.h>
    4747#include <sysinfo.h>
    48 #include <as.h>
     48
    4949#include <devman.h>
    5050#include <ddf/interrupt.h>
     51#include <net_interface.h>
    5152#include <ops/nic.h>
     53#include <packet_client.h>
     54#include <packet_remote.h>
     55#include <net/packet_header.h>
    5256#include <errno.h>
    5357
    5458#include "nic_driver.h"
    55 #include "nic_ev.h"
    5659#include "nic_impl.h"
    5760
     
    6164
    6265/**
    63  * Initializes libraries required for NIC framework - logger
     66 * Initializes libraries required for NIC framework - logger, packet manager
    6467 *
    6568 * @param name  Name of the device/driver (used in logging)
     
    7679        snprintf(buffer, 256, "drv/" DEVICE_CATEGORY_NIC "/%s", name);
    7780       
    78         return EOK;
    79 }
    80 
    81 /** Fill in the default implementations for device options and NIC interface.
     81        /* Initialize packet manager */
     82        return pm_init();
     83}
     84
     85/**
     86 * Fill in the default implementations for device options and NIC interface.
    8287 *
    8388 * @param driver_ops
     
    8893    nic_iface_t *iface)
    8994{
     95        if (driver_ops) {
     96                if (!driver_ops->device_added)
     97                        driver_ops->device_added = nic_device_added_impl;
     98        }
     99
    90100        if (dev_ops) {
    91101                if (!dev_ops->open)
     
    104114                if (!iface->set_state)
    105115                        iface->set_state = nic_set_state_impl;
    106                 if (!iface->send_frame)
    107                         iface->send_frame = nic_send_frame_impl;
    108                 if (!iface->callback_create)
    109                         iface->callback_create = nic_callback_create_impl;
     116                if (!iface->send_message)
     117                        iface->send_message = nic_send_message_impl;
     118                if (!iface->connect_to_nil)
     119                        iface->connect_to_nil = nic_connect_to_nil_impl;
    110120                if (!iface->get_address)
    111121                        iface->get_address = nic_get_address_impl;
     
    152162
    153163/**
    154  * Setup send frame handler. This MUST be called in the add_device handler
     164 * Setup write packet handler. This MUST be called in the add_device handler
    155165 * if the nic_send_message_impl function is used for sending messages (filled
    156166 * as send_message member of the nic_iface_t structure). The function must not
     
    158168 *
    159169 * @param nic_data
    160  * @param sffunc        Function handling the send_frame request
    161  */
    162 void nic_set_send_frame_handler(nic_t *nic_data, send_frame_handler sffunc)
    163 {
    164         nic_data->send_frame = sffunc;
     170 * @param wpfunc                Function handling the write_packet request
     171 */
     172void nic_set_write_packet_handler(nic_t *nic_data, write_packet_handler wpfunc)
     173{
     174        nic_data->write_packet = wpfunc;
    165175}
    166176
     
    260270}
    261271
    262 /** Allocate frame
     272/**
     273 * Just a wrapper over the packet_get_1_remote function
     274 */
     275packet_t *nic_alloc_packet(nic_t *nic_data, size_t data_size)
     276{
     277        return packet_get_1_remote(nic_data->net_session, data_size);
     278}
     279
     280
     281/**
     282 * Just a wrapper over the pq_release_remote function
     283 */
     284void nic_release_packet(nic_t *nic_data, packet_t *packet)
     285{
     286        pq_release_remote(nic_data->net_session, packet_get_id(packet));
     287}
     288
     289/** Allocate frame and packet
    263290 *
    264291 *  @param nic_data     The NIC driver data
    265  *  @param size         Frame size in bytes
     292 *  @param packet_size  Size of packet
     293 *  @param offload_size Size of packet offload
    266294 *  @return pointer to allocated frame if success, NULL otherwise
    267295 */
    268 nic_frame_t *nic_alloc_frame(nic_t *nic_data, size_t size)
     296nic_frame_t *nic_alloc_frame(nic_t *nic_data, size_t packet_size)
    269297{
    270298        nic_frame_t *frame;
     
    285313        }
    286314
    287         frame->data = malloc(size);
    288         if (frame->data == NULL) {
     315        packet_t *packet = nic_alloc_packet(nic_data, packet_size);
     316        if (!packet) {
    289317                free(frame);
    290318                return NULL;
    291319        }
    292320
    293         frame->size = size;
     321        frame->packet = packet;
    294322        return frame;
    295323}
     
    304332        if (!frame)
    305333                return;
    306 
    307         if (frame->data != NULL) {
    308                 free(frame->data);
    309                 frame->data = NULL;
    310                 frame->size = 0;
    311         }
    312 
     334        if (frame->packet != NULL) {
     335                nic_release_packet(nic_data, frame->packet);
     336        }
    313337        fibril_mutex_lock(&nic_globals.lock);
    314338        if (nic_globals.frame_cache_size >= NIC_GLOBALS_MAX_CACHE_SIZE) {
     
    423447
    424448/**
    425  * Connect to IRC service. This function should be called only from
     449 * Connect to the NET and IRQ services. This function should be called only from
    426450 * the add_device handler, thus no locking is required.
    427451 *
     
    430454 * @return EOK          If connection was successful.
    431455 * @return EINVAL       If the IRC service cannot be determined.
    432  * @return EREFUSED     If IRC service cannot be connected.
     456 * @return EREFUSED     If NET or IRC service cannot be connected.
    433457 */
    434458int nic_connect_to_services(nic_t *nic_data)
    435459{
     460        /* NET service */
     461        nic_data->net_session = service_connect_blocking(EXCHANGE_SERIALIZE,
     462                SERVICE_NETWORKING, 0, 0);
     463        if (nic_data->net_session == NULL)
     464                return errno;
     465       
    436466        /* IRC service */
    437467        sysarg_t apic;
     
    450480       
    451481        return EOK;
     482}
     483
     484/** Notify the NET service that the device is ready
     485 *
     486 * @param nic NICF structure
     487 *
     488 * @return EOK on success
     489 *
     490 */
     491int nic_ready(nic_t *nic)
     492{
     493        fibril_rwlock_read_lock(&nic->main_lock);
     494       
     495        async_sess_t *session = nic->net_session;
     496        devman_handle_t handle = nic->dev->handle;
     497       
     498        fibril_rwlock_read_unlock(&nic->main_lock);
     499       
     500        if (session == NULL)
     501                return EINVAL;
     502       
     503        return net_driver_ready(session, handle);
    452504}
    453505
     
    494546       
    495547        /* Notify NIL layer (and uppper) if bound - not in add_device */
    496         if (nic_data->client_session != NULL) {
    497                 int rc = nic_ev_addr_changed(nic_data->client_session,
    498                     address);
     548        if (nic_data->nil_session != NULL) {
     549                int rc = nil_addr_changed_msg(nic_data->nil_session,
     550                    nic_data->device_id, address);
    499551                if (rc != EOK) {
    500552                        fibril_rwlock_write_unlock(&nic_data->main_lock);
     
    552604
    553605/**
    554  * The busy flag can be set to 1 only in the send_frame handler, to 0 it can
     606 * The busy flag can be set to 1 only in the write_packet handler, to 0 it can
    555607 * be set anywhere.
    556608 *
     
    561613{
    562614        /*
    563          * When the function is called in send_frame handler the main lock is
     615         * When the function is called in write_packet handler the main lock is
    564616         * locked so no race can happen.
    565617         * Otherwise, when it is unexpectedly set to 0 (even with main lock held
     
    570622
    571623/**
    572  * This is the function that the driver should call when it receives a frame.
    573  * The frame is checked by filters and then sent up to the NIL layer or
    574  * discarded. The frame is released.
    575  *
    576  * @param nic_data
    577  * @param frame         The received frame
     624 * Provided for correct naming conventions.
     625 * The packet is checked by filters and then sent up to the NIL layer or
     626 * discarded, the frame is released.
     627 *
     628 * @param nic_data
     629 * @param frame         The frame containing received packet
    578630 */
    579631void nic_received_frame(nic_t *nic_data, nic_frame_t *frame)
    580632{
     633        nic_received_packet(nic_data, frame->packet);
     634        frame->packet = NULL;
     635        nic_release_frame(nic_data, frame);
     636}
     637
     638/**
     639 * This is the function that the driver should call when it receives a packet.
     640 * The packet is checked by filters and then sent up to the NIL layer or
     641 * discarded.
     642 *
     643 * @param nic_data
     644 * @param packet                The received packet
     645 */
     646void nic_received_packet(nic_t *nic_data, packet_t *packet)
     647{
    581648        /* Note: this function must not lock main lock, because loopback driver
    582          *               calls it inside send_frame handler (with locked main lock) */
     649         *               calls it inside write_packet handler (with locked main lock) */
     650        packet_id_t pid = packet_get_id(packet);
     651       
    583652        fibril_rwlock_read_lock(&nic_data->rxc_lock);
    584653        nic_frame_type_t frame_type;
    585         int check = nic_rxc_check(&nic_data->rx_control, frame->data,
    586             frame->size, &frame_type);
     654        int check = nic_rxc_check(&nic_data->rx_control, packet, &frame_type);
    587655        fibril_rwlock_read_unlock(&nic_data->rxc_lock);
    588656        /* Update statistics */
    589657        fibril_rwlock_write_lock(&nic_data->stats_lock);
    590 
     658        /* Both sending message up and releasing packet are atomic IPC calls */
    591659        if (nic_data->state == NIC_STATE_ACTIVE && check) {
    592660                nic_data->stats.receive_packets++;
    593                 nic_data->stats.receive_bytes += frame->size;
     661                nic_data->stats.receive_bytes += packet_get_data_length(packet);
    594662                switch (frame_type) {
    595663                case NIC_FRAME_MULTICAST:
     
    603671                }
    604672                fibril_rwlock_write_unlock(&nic_data->stats_lock);
    605                 nic_ev_received(nic_data->client_session, frame->data,
    606                     frame->size);
     673                nil_received_msg(nic_data->nil_session, nic_data->device_id, pid);
    607674        } else {
    608675                switch (frame_type) {
     
    618685                }
    619686                fibril_rwlock_write_unlock(&nic_data->stats_lock);
    620         }
    621         nic_release_frame(nic_data, frame);
    622 }
    623 
    624 /**
    625  * Some NICs can receive multiple frames during single interrupt. These can
     687                nic_release_packet(nic_data, packet);
     688        }
     689}
     690
     691/**
     692 * This function is to be used only in the loopback driver. It's workaround
     693 * for the situation when the packet does not contain ethernet address.
     694 * The filtering is therefore not applied here.
     695 *
     696 * @param nic_data
     697 * @param packet
     698 */
     699void nic_received_noneth_packet(nic_t *nic_data, packet_t *packet)
     700{
     701        fibril_rwlock_write_lock(&nic_data->stats_lock);
     702        nic_data->stats.receive_packets++;
     703        nic_data->stats.receive_bytes += packet_get_data_length(packet);
     704        fibril_rwlock_write_unlock(&nic_data->stats_lock);
     705       
     706        nil_received_msg(nic_data->nil_session, nic_data->device_id,
     707            packet_get_id(packet));
     708}
     709
     710/**
     711 * Some NICs can receive multiple packets during single interrupt. These can
    626712 * send them in whole list of frames (actually nic_frame_t structures), then
    627  * the list is deallocated and each frame is passed to the
     713 * the list is deallocated and each packet is passed to the
    628714 * nic_received_packet function.
    629715 *
     
    640726
    641727                list_remove(&frame->link);
    642                 nic_received_frame(nic_data, frame);
     728                nic_received_packet(nic_data, frame->packet);
     729                frame->packet = NULL;
     730                nic_release_frame(nic_data, frame);
    643731        }
    644732        nic_driver_release_frame_list(frames);
     
    670758        nic_data->dev = NULL;
    671759        nic_data->fun = NULL;
     760        nic_data->device_id = NIC_DEVICE_INVALID_ID;
    672761        nic_data->state = NIC_STATE_STOPPED;
    673         nic_data->client_session = NULL;
     762        nic_data->net_session = NULL;
     763        nic_data->nil_session = NULL;
    674764        nic_data->irc_session = NULL;
    675765        nic_data->poll_mode = NIC_POLL_IMMEDIATE;
    676766        nic_data->default_poll_mode = NIC_POLL_IMMEDIATE;
    677         nic_data->send_frame = NULL;
     767        nic_data->write_packet = NULL;
    678768        nic_data->on_activating = NULL;
    679769        nic_data->on_going_down = NULL;
     
    725815 */
    726816static void nic_destroy(nic_t *nic_data) {
    727         if (nic_data->client_session != NULL) {
    728                 async_hangup(nic_data->client_session);
     817        if (nic_data->net_session != NULL) {
     818                async_hangup(nic_data->net_session);
     819        }
     820
     821        if (nic_data->nil_session != NULL) {
     822                async_hangup(nic_data->nil_session);
    729823        }
    730824
     
    752846
    753847/**
     848 * Creates an exposed DDF function for the device, named "port0".
     849 * Device options are set as this function's options. The function is bound
     850 * (see ddf_fun_bind) and then registered to the DEVICE_CATEGORY_NIC class.
     851 * Note: this function should be called only from add_device handler, therefore
     852 * we don't need to use locks.
     853 *
     854 * @param nic_data      The NIC structure
     855 * @param ops           Device options for the DDF function.
     856 */
     857int nic_register_as_ddf_fun(nic_t *nic_data, ddf_dev_ops_t *ops)
     858{
     859        int rc;
     860        assert(nic_data);
     861
     862        nic_data->fun = ddf_fun_create(nic_data->dev, fun_exposed, "port0");
     863        if (nic_data->fun == NULL)
     864                return ENOMEM;
     865       
     866        nic_data->fun->ops = ops;
     867        nic_data->fun->driver_data = nic_data;
     868
     869        rc = ddf_fun_bind(nic_data->fun);
     870        if (rc != EOK) {
     871                ddf_fun_destroy(nic_data->fun);
     872                return rc;
     873        }
     874
     875        rc = ddf_fun_add_to_category(nic_data->fun, DEVICE_CATEGORY_NIC);
     876        if (rc != EOK) {
     877                ddf_fun_destroy(nic_data->fun);
     878                return rc;
     879        }
     880       
     881        return EOK;
     882}
     883
     884/**
    754885 * Set information about current HW filtering.
    755886 *  1 ...       Only those frames we want to receive are passed through HW
     
    9661097{
    9671098        return nic_data->fun;
    968 }
    969 
    970 /**
    971  * @param nic_data
    972  * @param fun
    973  */
    974 void nic_set_ddf_fun(nic_t *nic_data, ddf_fun_t *fun)
    975 {
    976         nic_data->fun = fun;
    9771099}
    9781100
     
    12071329}
    12081330
     1331// FIXME: Later
     1332#if 0
     1333
     1334/** Lock packet for DMA usage
     1335 *
     1336 * @param packet
     1337 * @return physical address of packet
     1338 */
     1339void *nic_dma_lock_packet(packet_t *packet)
     1340{
     1341        void *phys_addr;
     1342        size_t locked;
     1343        int rc = dma_lock(packet, &phys_addr, 1, &locked);
     1344        if (rc != EOK)
     1345                return NULL;
     1346       
     1347        assert(locked == 1);
     1348        return phys_addr;
     1349}
     1350
     1351/** Unlock packet after DMA usage
     1352 *
     1353 * @param packet
     1354 */
     1355void nic_dma_unlock_packet(packet_t *packet)
     1356{
     1357        size_t unlocked;
     1358        int rc = dma_unlock(packet, 1, &unlocked);
     1359        if (rc != EOK)
     1360                return;
     1361       
     1362        assert(unlocked == 1);
     1363}
     1364
     1365#endif
     1366
    12091367/** @}
    12101368 */
Note: See TracChangeset for help on using the changeset viewer.