Changeset 7fc092a in mainline for uspace/srv/hw/netif/ne2000/dp8390.c


Ignore:
Timestamp:
2011-01-27T22:09:29Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
db7ed07
Parents:
9ee87f6 (diff), 6265a2b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Changes from development branch

File:
1 moved

Legend:

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

    r9ee87f6 r7fc092a  
    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                        if (frames != NULL) {
     544                                frame_t *frame = ne2k_receive_frame(ne2k, boundary, length);
     545                                if (frame != NULL)
     546                                        list_append(&frame->link, frames);
     547                        }
     548                }
    538549               
    539550                /*
     
    550561                pio_write_8(ne2k->port + DP_BNRY, next);
    551562        }
    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++;
     563       
     564        return frames;
     565}
     566
     567link_t *ne2k_interrupt(ne2k_t *ne2k, uint8_t isr, uint8_t tsr)
     568{
     569        /* List of received frames */
     570        link_t *frames = NULL;
     571       
     572        if (isr & (ISR_PTX | ISR_TXE)) {
     573                if (isr & ISR_TXE)
     574                        ne2k->stats.send_errors++;
     575                else {
     576                        if (tsr & TSR_PTX)
     577                                ne2k->stats.send_packets++;
     578                       
     579                        if (tsr & TSR_COL)
     580                                ne2k->stats.collisions++;
     581                       
     582                        if (tsr & TSR_ABT)
     583                                ne2k->stats.send_aborted_errors++;
     584                       
     585                        if (tsr & TSR_CRS)
     586                                ne2k->stats.send_carrier_errors++;
     587                       
     588                        if (tsr & TSR_FU) {
     589                                ne2k->underruns++;
     590                                if (ne2k->underruns < NE2K_ERL)
     591                                        fprintf(stderr, "%s: FIFO underrun\n", NAME);
    592592                        }
    593593                       
    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);
     594                        if (tsr & TSR_CDH) {
     595                                ne2k->stats.send_heartbeat_errors++;
     596                                if (ne2k->stats.send_heartbeat_errors < NE2K_ERL)
     597                                        fprintf(stderr, "%s: CD heartbeat failure\n", NAME);
    605598                        }
    606599                       
    607                         fibril_mutex_unlock(&ne2k->sq_mutex);
     600                        if (tsr & TSR_OWC)
     601                                ne2k->stats.send_window_errors++;
    608602                }
    609603               
    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);
     604                fibril_mutex_lock(&ne2k->sq_mutex);
     605               
     606                if (ne2k->sq.dirty) {
     607                        /* Prepare the buffer for next packet */
     608                        ne2k->sq.dirty = false;
     609                        ne2k->sq.size = 0;
     610                       
     611                        /* Signal a next frame to be sent */
     612                        fibril_condvar_broadcast(&ne2k->sq_cv);
     613                } else {
     614                        ne2k->misses++;
     615                        if (ne2k->misses < NE2K_ERL)
     616                                fprintf(stderr, "%s: Spurious PTX interrupt\n", NAME);
    623617                }
    624618               
    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) {
     619                fibril_mutex_unlock(&ne2k->sq_mutex);
     620        }
     621       
     622        if (isr & ISR_RXE)
     623                ne2k->stats.receive_errors++;
     624       
     625        if (isr & ISR_CNT) {
     626                ne2k->stats.receive_crc_errors +=
     627                    pio_read_8(ne2k->port + DP_CNTR0);
     628                ne2k->stats.receive_frame_errors +=
     629                    pio_read_8(ne2k->port + DP_CNTR1);
     630                ne2k->stats.receive_missed_errors +=
     631                    pio_read_8(ne2k->port + DP_CNTR2);
     632        }
     633       
     634        if (isr & ISR_PRX)
     635                frames = ne2k_receive(ne2k);
     636       
     637        if (isr & ISR_RST) {
    637638                /*
    638639                 * The chip is stopped, and all arrived
     
    642643        }
    643644       
    644         /* Signal a next frame to be sent */
    645         if (signal)
    646                 fibril_condvar_broadcast(&ne2k->sq_cv);
     645        /* Unmask interrupts to be processed in the next round */
     646        pio_write_8(ne2k->port + DP_IMR,
     647            IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
     648       
     649        return frames;
    647650}
    648651
Note: See TracChangeset for help on using the changeset viewer.