Ignore:
File:
1 edited

Legend:

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

    r3c106e88 r7300c37  
    5454#include <errno.h>
    5555#include <libarch/ddi.h>
    56 #include <netif_skel.h>
    5756#include <net/packet.h>
    58 #include <nil_interface.h>
    5957#include <packet_client.h>
    6058#include "dp8390.h"
     
    8179
    8280/** NE2000 retry count */
    83 #define NE2K_RETRY  100
     81#define NE2K_RETRY  0x1000
    8482
    8583/** NE2000 error messages rate limiting */
     
    186184                memcpy(&word, buf, 1);
    187185                pio_write_16(ne2k->data_port, word);
     186        }
     187}
     188
     189static 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;
    188204        }
    189205}
     
    210226        ne2k->up = false;
    211227       
    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         }
     228        ne2k_init(ne2k);
    224229       
    225230        /* Check if the DP8390 is really there */
    226         val = pio_read_8(ne2k->port + DP_CR);
     231        uint8_t val = pio_read_8(ne2k->port + DP_CR);
    227232        if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
    228233                return EXDEV;
     
    242247        for (i = 0; i < ETH_ADDR; i++)
    243248                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 */
     262int ne2k_up(ne2k_t *ne2k)
     263{
     264        if (!ne2k->probed)
     265                return EXDEV;
     266       
     267        ne2k_init(ne2k);
    244268       
    245269        /*
     
    318342       
    319343        /* Step 10: */
    320         pio_write_8(ne2k->port + DP_CR, CR_DM_ABORT | CR_STA);
     344        pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_DM_ABORT | CR_STA);
    321345       
    322346        /* Step 11: */
     
    329353       
    330354        /* 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  */
    343 int 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        
    351355        ne2k->up = true;
    352356        return EOK;
     
    362366        if ((ne2k->probed) && (ne2k->up)) {
    363367                pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
    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                
     368                ne2k_init(ne2k);
    370369                ne2k->up = false;
    371370        }
     
    420419        pio_write_8(ne2k->port + DP_RBCR1, 0);
    421420       
    422         for (i = 0; i < 0x1000; i++) {
     421        for (i = 0; i < NE2K_RETRY; i++) {
    423422                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
    424423                        break;
     
    430429       
    431430        /* Acknowledge the ISR_RDC (remote DMA) interrupt */
    432         for (i = 0; i < 0x1000; i++) {
     431        for (i = 0; i < NE2K_RETRY; i++) {
    433432                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
    434433                        break;
     
    448447}
    449448
    450 static 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 
    459 static 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);
     449static 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);
    467464        bzero(buf, length);
    468465        uint8_t last = page + length / DP_PAGE;
     
    481478       
    482479        ne2k->stats.receive_packets++;
    483         nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
    484 }
    485 
    486 static void ne2k_receive(ne2k_t *ne2k, int nil_phone, device_id_t device_id)
    487 {
     480        return frame;
     481}
     482
     483static 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       
    488494        while (true) {
    489495                uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
     
    534540                        ne2k->overruns++;
    535541                        next = current;
    536                 } else if ((header.status & RSR_PRX) && (ne2k->up))
    537                         ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id);
     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                }
    538547               
    539548                /*
     
    550559                pio_write_8(ne2k->port + DP_BNRY, next);
    551560        }
    552 }
    553 
    554 void 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++;
     561       
     562        return frames;
     563}
     564
     565link_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);
    592590                        }
    593591                       
    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);
     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);
    605596                        }
    606597                       
    607                         fibril_mutex_unlock(&ne2k->sq_mutex);
     598                        if (tsr & TSR_OWC)
     599                                ne2k->stats.send_window_errors++;
    608600                }
    609601               
    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);
     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);
    623615                }
    624616               
    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) {
     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) {
    637636                /*
    638637                 * The chip is stopped, and all arrived
     
    642641        }
    643642       
    644         /* Signal a next frame to be sent */
    645         if (signal)
    646                 fibril_condvar_broadcast(&ne2k->sq_cv);
     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;
    647648}
    648649
Note: See TracChangeset for help on using the changeset viewer.