Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hw/netif/dp8390/dp8390.c

    r7300c37 r3c106e88  
    5454#include <errno.h>
    5555#include <libarch/ddi.h>
     56#include <netif_skel.h>
    5657#include <net/packet.h>
     58#include <nil_interface.h>
    5759#include <packet_client.h>
    5860#include "dp8390.h"
     
    7981
    8082/** NE2000 retry count */
    81 #define NE2K_RETRY  0x1000
     83#define NE2K_RETRY  100
    8284
    8385/** NE2000 error messages rate limiting */
     
    184186                memcpy(&word, buf, 1);
    185187                pio_write_16(ne2k->data_port, word);
    186         }
    187 }
    188 
    189 static void ne2k_init(ne2k_t *ne2k)
    190 {
    191         unsigned int i;
    192        
    193         /* Reset the ethernet card */
    194         uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
    195         usleep(2000);
    196         pio_write_8(ne2k->port + NE2K_RESET, val);
    197         usleep(2000);
    198        
    199         /* Reset the DP8390 */
    200         pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
    201         for (i = 0; i < NE2K_RETRY; i++) {
    202                 if (pio_read_8(ne2k->port + DP_ISR) != 0)
    203                         break;
    204188        }
    205189}
     
    226210        ne2k->up = false;
    227211       
    228         ne2k_init(ne2k);
     212        /* Reset the ethernet card */
     213        uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
     214        usleep(2000);
     215        pio_write_8(ne2k->port + NE2K_RESET, val);
     216        usleep(2000);
     217       
     218        /* Reset the DP8390 */
     219        pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
     220        for (i = 0; i < 0x1000; i++) {
     221                if (pio_read_8(ne2k->port + DP_ISR) != 0)
     222                        break;
     223        }
    229224       
    230225        /* Check if the DP8390 is really there */
    231         uint8_t val = pio_read_8(ne2k->port + DP_CR);
     226        val = pio_read_8(ne2k->port + DP_CR);
    232227        if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
    233228                return EXDEV;
     
    247242        for (i = 0; i < ETH_ADDR; i++)
    248243                ne2k->mac[i] = pio_read_16(ne2k->data_port);
    249        
    250         ne2k->probed = true;
    251         return EOK;
    252 }
    253 
    254 /** Start the network interface.
    255  *
    256  * @param[in,out] ne2k Network interface structure.
    257  *
    258  * @return EOK on success.
    259  * @return EXDEV if the network interface is disabled.
    260  *
    261  */
    262 int ne2k_up(ne2k_t *ne2k)
    263 {
    264         if (!ne2k->probed)
    265                 return EXDEV;
    266        
    267         ne2k_init(ne2k);
    268244       
    269245        /*
     
    342318       
    343319        /* Step 10: */
    344         pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA);
     320        pio_write_8(ne2k->port + DP_CR, CR_DM_ABORT | CR_STA);
    345321       
    346322        /* Step 11: */
     
    353329       
    354330        /* Finish the initialization */
     331        ne2k->probed = true;
     332        return EOK;
     333}
     334
     335/** Start the network interface.
     336 *
     337 * @param[in,out] ne2k Network interface structure.
     338 *
     339 * @return EOK on success.
     340 * @return EXDEV if the network interface is disabled.
     341 *
     342 */
     343int ne2k_up(ne2k_t *ne2k)
     344{
     345        if (!ne2k->probed)
     346                return EXDEV;
     347       
     348        pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
     349        pio_write_8(ne2k->port + DP_RCR, RCR_AB);
     350       
    355351        ne2k->up = true;
    356352        return EOK;
     
    366362        if ((ne2k->probed) && (ne2k->up)) {
    367363                pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
    368                 ne2k_init(ne2k);
     364               
     365                /* Reset the ethernet card */
     366                uint8_t val = pio_read_8(ne2k->port + NE2K_RESET);
     367                usleep(2000);
     368                pio_write_8(ne2k->port + NE2K_RESET, val);
     369               
    369370                ne2k->up = false;
    370371        }
     
    419420        pio_write_8(ne2k->port + DP_RBCR1, 0);
    420421       
    421         for (i = 0; i < NE2K_RETRY; i++) {
     422        for (i = 0; i < 0x1000; i++) {
    422423                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
    423424                        break;
     
    429430       
    430431        /* Acknowledge the ISR_RDC (remote DMA) interrupt */
    431         for (i = 0; i < NE2K_RETRY; i++) {
     432        for (i = 0; i < 0x1000; i++) {
    432433                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
    433434                        break;
     
    447448}
    448449
    449 static frame_t *ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length)
    450 {
    451         frame_t *frame = (frame_t *) malloc(sizeof(frame_t));
    452         if (frame == NULL)
    453                 return NULL;
    454        
    455         link_initialize(&frame->link);
    456        
    457         frame->packet = netif_packet_get_1(length);
    458         if (frame->packet == NULL) {
    459                 free(frame);
    460                 return NULL;
    461         }
    462        
    463         void *buf = packet_suffix(frame->packet, length);
     450static uint8_t ne2k_isr_ack(ne2k_t *ne2k)
     451{
     452        uint8_t isr = pio_read_8(ne2k->port + DP_ISR);
     453        if (isr != 0)
     454                pio_write_8(ne2k->port + DP_ISR, isr);
     455       
     456        return isr;
     457}
     458
     459static void ne2k_receive_frame(ne2k_t *ne2k, uint8_t page, size_t length,
     460    int nil_phone, device_id_t device_id)
     461{
     462        packet_t *packet = netif_packet_get_1(length);
     463        if (!packet)
     464                return;
     465       
     466        void *buf = packet_suffix(packet, length);
    464467        bzero(buf, length);
    465468        uint8_t last = page + length / DP_PAGE;
     
    478481       
    479482        ne2k->stats.receive_packets++;
    480         return frame;
    481 }
    482 
    483 static link_t *ne2k_receive(ne2k_t *ne2k)
    484 {
    485         /*
    486          * Allocate memory for the list of received frames.
    487          * If the allocation fails here we still receive the
    488          * frames from the network, but they will be lost.
    489          */
    490         link_t *frames = (link_t *) malloc(sizeof(link_t));
    491         if (frames != NULL)
    492                 list_initialize(frames);
    493        
     483        nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
     484}
     485
     486static void ne2k_receive(ne2k_t *ne2k, int nil_phone, device_id_t device_id)
     487{
    494488        while (true) {
    495489                uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
     
    540534                        ne2k->overruns++;
    541535                        next = current;
    542                 } else if ((header.status & RSR_PRX) && (ne2k->up)) {
    543                         frame_t *frame = ne2k_receive_frame(ne2k, boundary, length);
    544                         if ((frame != NULL) && (frames != NULL))
    545                                 list_append(&frame->link, frames);
    546                 }
     536                } else if ((header.status & RSR_PRX) && (ne2k->up))
     537                        ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id);
    547538               
    548539                /*
     
    559550                pio_write_8(ne2k->port + DP_BNRY, next);
    560551        }
    561        
    562         return frames;
    563 }
    564 
    565 link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
    566 {
    567         /* List of received frames */
    568         link_t *frames = NULL;
    569        
    570         if (isr & (ISR_PTX | ISR_TXE)) {
    571                 if (isr & ISR_TXE)
    572                         ne2k->stats.send_errors++;
    573                 else {
    574                         if (tsr & TSR_PTX)
    575                                 ne2k->stats.send_packets++;
    576                        
    577                         if (tsr & TSR_COL)
    578                                 ne2k->stats.collisions++;
    579                        
    580                         if (tsr & TSR_ABT)
    581                                 ne2k->stats.send_aborted_errors++;
    582                        
    583                         if (tsr & TSR_CRS)
    584                                 ne2k->stats.send_carrier_errors++;
    585                        
    586                         if (tsr & TSR_FU) {
    587                                 ne2k->underruns++;
    588                                 if (ne2k->underruns < NE2K_ERL)
    589                                         fprintf(stderr, "%s: FIFO underrun\n", NAME);
     552}
     553
     554void ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, int nil_phone, device_id_t device_id)
     555{
     556        bool signal = false;
     557        bool stopped = false;
     558       
     559        for (; (isr & 0x7f) != 0; isr = ne2k_isr_ack(ne2k)) {
     560                if (isr & (ISR_PTX | ISR_TXE)) {
     561                        if (isr & ISR_TXE)
     562                                ne2k->stats.send_errors++;
     563                        else {
     564                                uint8_t tsr = pio_read_8(ne2k->port + DP_TSR);
     565                               
     566                                if (tsr & TSR_PTX)
     567                                        ne2k->stats.send_packets++;
     568                               
     569                                if (tsr & TSR_COL)
     570                                        ne2k->stats.collisions++;
     571                               
     572                                if (tsr & TSR_ABT)
     573                                        ne2k->stats.send_aborted_errors++;
     574                               
     575                                if (tsr & TSR_CRS)
     576                                        ne2k->stats.send_carrier_errors++;
     577                               
     578                                if (tsr & TSR_FU) {
     579                                        ne2k->underruns++;
     580                                        if (ne2k->underruns < NE2K_ERL)
     581                                                fprintf(stderr, "%s: FIFO underrun\n", NAME);
     582                                }
     583                               
     584                                if (tsr & TSR_CDH) {
     585                                        ne2k->stats.send_heartbeat_errors++;
     586                                        if (ne2k->stats.send_heartbeat_errors < NE2K_ERL)
     587                                                fprintf(stderr, "%s: CD heartbeat failure\n", NAME);
     588                                }
     589                               
     590                                if (tsr & TSR_OWC)
     591                                        ne2k->stats.send_window_errors++;
    590592                        }
    591593                       
    592                         if (tsr & TSR_CDH) {
    593                                 ne2k->stats.send_heartbeat_errors++;
    594                                 if (ne2k->stats.send_heartbeat_errors < NE2K_ERL)
    595                                         fprintf(stderr, "%s: CD heartbeat failure\n", NAME);
     594                        fibril_mutex_lock(&ne2k->sq_mutex);
     595                       
     596                        if (ne2k->sq.dirty) {
     597                                /* Prepare the buffer for next packet */
     598                                ne2k->sq.dirty = false;
     599                                ne2k->sq.size = 0;
     600                                signal = true;
     601                        } else {
     602                                ne2k->misses++;
     603                                if (ne2k->misses < NE2K_ERL)
     604                                        fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
    596605                        }
    597606                       
    598                         if (tsr & TSR_OWC)
    599                                 ne2k->stats.send_window_errors++;
     607                        fibril_mutex_unlock(&ne2k->sq_mutex);
    600608                }
    601609               
    602                 fibril_mutex_lock(&ne2k->sq_mutex);
    603                
    604                 if (ne2k->sq.dirty) {
    605                         /* Prepare the buffer for next packet */
    606                         ne2k->sq.dirty = false;
    607                         ne2k->sq.size = 0;
    608                        
    609                         /* Signal a next frame to be sent */
    610                         fibril_condvar_broadcast(&ne2k->sq_cv);
    611                 } else {
    612                         ne2k->misses++;
    613                         if (ne2k->misses < NE2K_ERL)
    614                                 fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
     610                if (isr & ISR_PRX)
     611                        ne2k_receive(ne2k, nil_phone, device_id);
     612               
     613                if (isr & ISR_RXE)
     614                        ne2k->stats.receive_errors++;
     615               
     616                if (isr & ISR_CNT) {
     617                        ne2k->stats.receive_crc_errors +=
     618                            pio_read_8(ne2k->port + DP_CNTR0);
     619                        ne2k->stats.receive_frame_errors +=
     620                            pio_read_8(ne2k->port + DP_CNTR1);
     621                        ne2k->stats.receive_missed_errors +=
     622                            pio_read_8(ne2k->port + DP_CNTR2);
    615623                }
    616624               
    617                 fibril_mutex_unlock(&ne2k->sq_mutex);
    618         }
    619        
    620         if (isr & ISR_RXE)
    621                 ne2k->stats.receive_errors++;
    622        
    623         if (isr & ISR_CNT) {
    624                 ne2k->stats.receive_crc_errors +=
    625                     pio_read_8(ne2k->port + DP_CNTR0);
    626                 ne2k->stats.receive_frame_errors +=
    627                     pio_read_8(ne2k->port + DP_CNTR1);
    628                 ne2k->stats.receive_missed_errors +=
    629                     pio_read_8(ne2k->port + DP_CNTR2);
    630         }
    631        
    632         if (isr & ISR_PRX)
    633                 frames = ne2k_receive(ne2k);
    634        
    635         if (isr & ISR_RST) {
     625                if (isr & ISR_RST) {
     626                        /*
     627                         * This means we got an interrupt but the ethernet
     628                         * chip is shutdown. We set the flag 'stopped'
     629                         * and continue processing arrived packets. When the
     630                         * receive buffer is empty, we reset the DP8390.
     631                         */
     632                        stopped = true;
     633                }
     634        }
     635       
     636        if (stopped) {
    636637                /*
    637638                 * The chip is stopped, and all arrived
     
    641642        }
    642643       
    643         /* Unmask interrupts to be processed in the next round */
    644         pio_write_8(ne2k->port + DP_IMR,
    645             IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
    646        
    647         return frames;
     644        /* Signal a next frame to be sent */
     645        if (signal)
     646                fibril_condvar_broadcast(&ne2k->sq_cv);
    648647}
    649648
Note: See TracChangeset for help on using the changeset viewer.