Ignore:
File:
1 edited

Legend:

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

    r9cd8165 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;
     81        /* Initialize packet manager */
     82        return pm_init();
    7983}
    8084
     
    8993    nic_iface_t *iface)
    9094{
     95        if (driver_ops) {
     96                if (!driver_ops->device_added)
     97                        driver_ops->device_added = nic_device_added_impl;
     98        }
     99
    91100        if (dev_ops) {
    92101                if (!dev_ops->open)
     
    105114                if (!iface->set_state)
    106115                        iface->set_state = nic_set_state_impl;
    107                 if (!iface->send_frame)
    108                         iface->send_frame = nic_send_frame_impl;
    109                 if (!iface->callback_create)
    110                         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;
    111120                if (!iface->get_address)
    112121                        iface->get_address = nic_get_address_impl;
     
    153162
    154163/**
    155  * 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
    156165 * if the nic_send_message_impl function is used for sending messages (filled
    157166 * as send_message member of the nic_iface_t structure). The function must not
     
    159168 *
    160169 * @param nic_data
    161  * @param sffunc        Function handling the send_frame request
    162  */
    163 void nic_set_send_frame_handler(nic_t *nic_data, send_frame_handler sffunc)
    164 {
    165         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;
    166175}
    167176
     
    261270}
    262271
    263 /** 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
    264290 *
    265291 *  @param nic_data     The NIC driver data
    266  *  @param size         Frame size in bytes
     292 *  @param packet_size  Size of packet
     293 *  @param offload_size Size of packet offload
    267294 *  @return pointer to allocated frame if success, NULL otherwise
    268295 */
    269 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)
    270297{
    271298        nic_frame_t *frame;
     
    286313        }
    287314
    288         frame->data = malloc(size);
    289         if (frame->data == NULL) {
     315        packet_t *packet = nic_alloc_packet(nic_data, packet_size);
     316        if (!packet) {
    290317                free(frame);
    291318                return NULL;
    292319        }
    293320
    294         frame->size = size;
     321        frame->packet = packet;
    295322        return frame;
    296323}
     
    305332        if (!frame)
    306333                return;
    307 
    308         if (frame->data != NULL) {
    309                 free(frame->data);
    310                 frame->data = NULL;
    311                 frame->size = 0;
    312         }
    313 
     334        if (frame->packet != NULL) {
     335                nic_release_packet(nic_data, frame->packet);
     336        }
    314337        fibril_mutex_lock(&nic_globals.lock);
    315338        if (nic_globals.frame_cache_size >= NIC_GLOBALS_MAX_CACHE_SIZE) {
     
    424447
    425448/**
    426  * 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
    427450 * the add_device handler, thus no locking is required.
    428451 *
     
    431454 * @return EOK          If connection was successful.
    432455 * @return EINVAL       If the IRC service cannot be determined.
    433  * @return EREFUSED     If IRC service cannot be connected.
     456 * @return EREFUSED     If NET or IRC service cannot be connected.
    434457 */
    435458int nic_connect_to_services(nic_t *nic_data)
    436459{
     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       
    437466        /* IRC service */
    438467        sysarg_t apic;
     
    451480       
    452481        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);
    453504}
    454505
     
    495546       
    496547        /* Notify NIL layer (and uppper) if bound - not in add_device */
    497         if (nic_data->client_session != NULL) {
    498                 int rc = nic_ev_addr_changed(nic_data->client_session,
    499                     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);
    500551                if (rc != EOK) {
    501552                        fibril_rwlock_write_unlock(&nic_data->main_lock);
     
    553604
    554605/**
    555  * 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
    556607 * be set anywhere.
    557608 *
     
    562613{
    563614        /*
    564          * 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
    565616         * locked so no race can happen.
    566617         * Otherwise, when it is unexpectedly set to 0 (even with main lock held
     
    571622
    572623/**
    573  * This is the function that the driver should call when it receives a frame.
    574  * The frame is checked by filters and then sent up to the NIL layer or
    575  * discarded. The frame is released.
    576  *
    577  * @param nic_data
    578  * @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
    579630 */
    580631void nic_received_frame(nic_t *nic_data, nic_frame_t *frame)
    581632{
     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{
    582648        /* Note: this function must not lock main lock, because loopback driver
    583          *               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       
    584652        fibril_rwlock_read_lock(&nic_data->rxc_lock);
    585653        nic_frame_type_t frame_type;
    586         int check = nic_rxc_check(&nic_data->rx_control, frame->data,
    587             frame->size, &frame_type);
     654        int check = nic_rxc_check(&nic_data->rx_control, packet, &frame_type);
    588655        fibril_rwlock_read_unlock(&nic_data->rxc_lock);
    589656        /* Update statistics */
    590657        fibril_rwlock_write_lock(&nic_data->stats_lock);
    591 
     658        /* Both sending message up and releasing packet are atomic IPC calls */
    592659        if (nic_data->state == NIC_STATE_ACTIVE && check) {
    593660                nic_data->stats.receive_packets++;
    594                 nic_data->stats.receive_bytes += frame->size;
     661                nic_data->stats.receive_bytes += packet_get_data_length(packet);
    595662                switch (frame_type) {
    596663                case NIC_FRAME_MULTICAST:
     
    604671                }
    605672                fibril_rwlock_write_unlock(&nic_data->stats_lock);
    606                 nic_ev_received(nic_data->client_session, frame->data,
    607                     frame->size);
     673                nil_received_msg(nic_data->nil_session, nic_data->device_id, pid);
    608674        } else {
    609675                switch (frame_type) {
     
    619685                }
    620686                fibril_rwlock_write_unlock(&nic_data->stats_lock);
    621         }
    622         nic_release_frame(nic_data, frame);
     687                nic_release_packet(nic_data, packet);
     688        }
    623689}
    624690
    625691/**
    626692 * This function is to be used only in the loopback driver. It's workaround
    627  * for the situation when the frame does not contain ethernet address.
     693 * for the situation when the packet does not contain ethernet address.
    628694 * The filtering is therefore not applied here.
    629695 *
    630696 * @param nic_data
    631  * @param data          Frame data
    632  * @param size          Frame size in bytes
    633  */
    634 void nic_received_noneth_frame(nic_t *nic_data, void *data, size_t size)
     697 * @param packet
     698 */
     699void nic_received_noneth_packet(nic_t *nic_data, packet_t *packet)
    635700{
    636701        fibril_rwlock_write_lock(&nic_data->stats_lock);
    637702        nic_data->stats.receive_packets++;
    638         nic_data->stats.receive_bytes += size;
     703        nic_data->stats.receive_bytes += packet_get_data_length(packet);
    639704        fibril_rwlock_write_unlock(&nic_data->stats_lock);
    640705       
    641         nic_ev_received(nic_data->client_session, data, size);
    642 }
    643 
    644 /**
    645  * Some NICs can receive multiple frames during single interrupt. These can
     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
    646712 * send them in whole list of frames (actually nic_frame_t structures), then
    647  * the list is deallocated and each frame is passed to the
     713 * the list is deallocated and each packet is passed to the
    648714 * nic_received_packet function.
    649715 *
     
    660726
    661727                list_remove(&frame->link);
    662                 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);
    663731        }
    664732        nic_driver_release_frame_list(frames);
     
    690758        nic_data->dev = NULL;
    691759        nic_data->fun = NULL;
     760        nic_data->device_id = NIC_DEVICE_INVALID_ID;
    692761        nic_data->state = NIC_STATE_STOPPED;
    693         nic_data->client_session = NULL;
     762        nic_data->net_session = NULL;
     763        nic_data->nil_session = NULL;
    694764        nic_data->irc_session = NULL;
    695765        nic_data->poll_mode = NIC_POLL_IMMEDIATE;
    696766        nic_data->default_poll_mode = NIC_POLL_IMMEDIATE;
    697         nic_data->send_frame = NULL;
     767        nic_data->write_packet = NULL;
    698768        nic_data->on_activating = NULL;
    699769        nic_data->on_going_down = NULL;
     
    745815 */
    746816static void nic_destroy(nic_t *nic_data) {
    747         if (nic_data->client_session != NULL) {
    748                 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);
    749823        }
    750824
     
    772846
    773847/**
     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/**
    774885 * Set information about current HW filtering.
    775886 *  1 ...       Only those frames we want to receive are passed through HW
     
    9861097{
    9871098        return nic_data->fun;
    988 }
    989 
    990 /**
    991  * @param nic_data
    992  * @param fun
    993  */
    994 void nic_set_ddf_fun(nic_t *nic_data, ddf_fun_t *fun)
    995 {
    996         nic_data->fun = fun;
    9971099}
    9981100
     
    12271329}
    12281330
     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
    12291367/** @}
    12301368 */
Note: See TracChangeset for help on using the changeset viewer.