Changeset 3c106e88 in mainline for uspace/srv/hw/netif/dp8390/dp8390.c


Ignore:
Timestamp:
2011-01-09T23:09:02Z (14 years ago)
Author:
martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
774e6d1a
Parents:
7ea7db31
Message:

complete rewrite of the NE2000 network interface driver

  • remove almost all stuff which was not directly related to NE2000 ISA to improve readability (optional support for NE1000, already defunct host DMA support, etc.)
  • correct input and output buffering and correct synchronization w.r.t. fibrils (the only remaining fibril-related question is whether multiple overlaping IRQ notifications can cause any troubles)

this implementation finally provides solid foundations for the next lowest networking layers (ARP, IP) and provide a way to debug UDP and TCP

File:
1 edited

Legend:

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

    r7ea7db31 r3c106e88  
    3838 */
    3939
    40 /** @addtogroup dp8390
     40/** @addtogroup ne2000
    4141 *  @{
    4242 */
    4343
    4444/** @file
    45  *  DP8390 network interface core implementation.
     45 *
     46 * NE2000 (based on DP8390) network interface core implementation.
     47 * Only the basic NE2000 PIO (ISA) interface is supported, remote
     48 * DMA is completely absent from this code for simplicity.
     49 *
    4650 */
    4751
     
    4953#include <byteorder.h>
    5054#include <errno.h>
    51 #include <netif_local.h>
     55#include <libarch/ddi.h>
     56#include <netif_skel.h>
    5257#include <net/packet.h>
    5358#include <nil_interface.h>
    5459#include <packet_client.h>
    55 #include "dp8390_drv.h"
    56 #include "dp8390_port.h"
    5760#include "dp8390.h"
    58 #include "ne2000.h"
    59 
    60 /** Read a memory block byte by byte.
    61  *
    62  *  @param[in] port The source address.
    63  *  @param[out] buf The destination buffer.
    64  *  @param[in] size The memory block size in bytes.
    65  *
    66  */
    67 static void outsb(port_t port, void * buf, size_t size);
     61
     62/** Page size */
     63#define DP_PAGE  256
     64
     65/** 6 * DP_PAGE >= 1514 bytes */
     66#define SQ_PAGES  6
     67
     68/* NE2000 implementation. */
     69
     70/** NE2000 Data Register */
     71#define NE2K_DATA  0x0010
     72
     73/** NE2000 Reset register */
     74#define NE2K_RESET  0x001f
     75
     76/** NE2000 data start */
     77#define NE2K_START  0x4000
     78
     79/** NE2000 data size */
     80#define NE2K_SIZE  0x4000
     81
     82/** NE2000 retry count */
     83#define NE2K_RETRY  100
     84
     85/** NE2000 error messages rate limiting */
     86#define NE2K_ERL  10
     87
     88/** Minimum Ethernet packet size in bytes */
     89#define ETH_MIN_PACK_SIZE  60
     90
     91/** Maximum Ethernet packet size in bytes */
     92#define ETH_MAX_PACK_SIZE_TAGGED  1518
     93
     94/** Type definition of the receive header
     95 *
     96 */
     97typedef struct {
     98        /** Copy of RSR */
     99        uint8_t status;
     100       
     101        /** Pointer to next packet */
     102        uint8_t next;
     103       
     104        /** Receive Byte Count Low */
     105        uint8_t rbcl;
     106       
     107        /** Receive Byte Count High */
     108        uint8_t rbch;
     109} recv_header_t;
    68110
    69111/** Read a memory block word by word.
    70112 *
    71  *  @param[in] port The source address.
    72  *  @param[out] buf The destination buffer.
    73  *  @param[in] size The memory block size in bytes.
    74  *
    75  */
    76 static void outsw(port_t port, void * buf, size_t size);
    77 
    78 /*
    79  * Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
    80  * on writes to the CR register. Additional CR_STAs do not appear to hurt
    81  * genuine dp8390s.
    82  */
    83 #define CR_EXTRA  CR_STA
    84 
    85 static void dp_init(dpeth_t *dep);
    86 static void dp_reinit(dpeth_t *dep);
    87 static void dp_reset(dpeth_t *dep);
    88 static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep);
    89 static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length);
    90 static void conf_hw(dpeth_t *dep);
    91 static void insb(port_t port, void *buf, size_t size);
    92 static void insw(port_t port, void *buf, size_t size);
    93 
    94 int do_probe(dpeth_t *dep)
    95 {
    96         /* This is the default, try to (re)locate the device. */
    97         conf_hw(dep);
    98         if (!dep->up)
    99                 /* Probe failed, or the device is configured off. */
     113 * @param[in]  port Source address.
     114 * @param[out] buf  Destination buffer.
     115 * @param[in]  size Memory block size in bytes.
     116 *
     117 */
     118static void pio_read_buf_16(void *port, void *buf, size_t size)
     119{
     120        size_t i;
     121       
     122        for (i = 0; (i << 1) < size; i++)
     123                *((uint16_t *) buf + i) = pio_read_16((ioport16_t *) (port));
     124}
     125
     126/** Write a memory block word by word.
     127 *
     128 * @param[in] port Destination address.
     129 * @param[in] buf  Source buffer.
     130 * @param[in] size Memory block size in bytes.
     131 *
     132 */
     133static void pio_write_buf_16(void *port, void *buf, size_t size)
     134{
     135        size_t i;
     136       
     137        for (i = 0; (i << 1) < size; i++)
     138                pio_write_16((ioport16_t *) port, *((uint16_t *) buf + i));
     139}
     140
     141static void ne2k_download(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
     142{
     143        size_t esize = size & ~1;
     144       
     145        pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
     146        pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
     147        pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
     148        pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
     149        pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
     150       
     151        if (esize != 0) {
     152                pio_read_buf_16(ne2k->data_port, buf, esize);
     153                size -= esize;
     154                buf += esize;
     155        }
     156       
     157        if (size) {
     158                assert(size == 1);
     159               
     160                uint16_t word = pio_read_16(ne2k->data_port);
     161                memcpy(buf, &word, 1);
     162        }
     163}
     164
     165static void ne2k_upload(ne2k_t *ne2k, void *buf, size_t addr, size_t size)
     166{
     167        size_t esize = size & ~1;
     168       
     169        pio_write_8(ne2k->port + DP_RBCR0, esize & 0xff);
     170        pio_write_8(ne2k->port + DP_RBCR1, (esize >> 8) & 0xff);
     171        pio_write_8(ne2k->port + DP_RSAR0, addr & 0xff);
     172        pio_write_8(ne2k->port + DP_RSAR1, (addr >> 8) & 0xff);
     173        pio_write_8(ne2k->port + DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
     174       
     175        if (esize != 0) {
     176                pio_write_buf_16(ne2k->data_port, buf, esize);
     177                size -= esize;
     178                buf += esize;
     179        }
     180       
     181        if (size) {
     182                assert(size == 1);
     183               
     184                uint16_t word = 0;
     185               
     186                memcpy(&word, buf, 1);
     187                pio_write_16(ne2k->data_port, word);
     188        }
     189}
     190
     191/** Probe and initialize the network interface.
     192 *
     193 * @param[in,out] ne2k Network interface structure.
     194 * @param[in]     port Device address.
     195 * @param[in]     irq  Device interrupt vector.
     196 *
     197 * @return EOK on success.
     198 * @return EXDEV if the network interface was not recognized.
     199 *
     200 */
     201int ne2k_probe(ne2k_t *ne2k, void *port, int irq)
     202{
     203        unsigned int i;
     204       
     205        /* General initialization */
     206        ne2k->port = port;
     207        ne2k->data_port = ne2k->port + NE2K_DATA;
     208        ne2k->irq = irq;
     209        ne2k->probed = false;
     210        ne2k->up = false;
     211       
     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        }
     224       
     225        /* Check if the DP8390 is really there */
     226        val = pio_read_8(ne2k->port + DP_CR);
     227        if ((val & (CR_STP | CR_DM_ABORT)) != (CR_STP | CR_DM_ABORT))
    100228                return EXDEV;
    101229       
    102         if (dep->up)
    103                 dp_init(dep);
    104        
    105         return EOK;
    106 }
    107 
    108 /** Initialize and/or start the network interface.
    109  *
    110  *  @param[in,out] dep The network interface structure.
    111  *
    112  *  @return EOK on success.
    113  *  @return EXDEV if the network interface is disabled.
    114  *
    115  */
    116 int do_init(dpeth_t *dep)
    117 {
    118         if (!dep->up)
    119                 /* FIXME: Perhaps call do_probe()? */
    120                 return EXDEV;
    121        
    122         assert(dep->up);
    123         assert(dep->enabled);
    124        
    125         dp_reinit(dep);
    126         return EOK;
    127 }
    128 
    129 void do_stop(dpeth_t *dep)
    130 {
    131         if ((dep->up) && (dep->enabled)) {
    132                 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
    133                 ne_stop(dep);
    134                
    135                 dep->enabled = false;
    136                 dep->stopped = false;
    137                 dep->sending = false;
    138                 dep->send_avail = false;
    139         }
    140 }
    141 
    142 static void dp_user2nic(dpeth_t *dep, void *buf, size_t offset, int nic_addr, size_t size)
    143 {
    144         size_t ecount = size & ~1;
    145        
    146         outb_reg0(dep, DP_ISR, ISR_RDC);
    147        
    148         if (dep->de_16bit) {
    149                 outb_reg0(dep, DP_RBCR0, ecount & 0xff);
    150                 outb_reg0(dep, DP_RBCR1, ecount >> 8);
    151         } else {
    152                 outb_reg0(dep, DP_RBCR0, size & 0xff);
    153                 outb_reg0(dep, DP_RBCR1, size >> 8);
    154         }
    155        
    156         outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
    157         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
    158         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
    159        
    160         if (dep->de_16bit) {
    161                 void *ptr = buf + offset;
    162                
    163                 if (ecount != 0) {
    164                         outsw(dep->de_data_port, ptr, ecount);
    165                         size -= ecount;
    166                         offset += ecount;
    167                         ptr += ecount;
    168                 }
    169                
    170                 if (size) {
    171                         assert(size == 1);
    172                        
    173                         uint16_t two_bytes;
    174                        
    175                         memcpy(&(((uint8_t *) &two_bytes)[0]), ptr, 1);
    176                         outw(dep->de_data_port, two_bytes);
    177                 }
    178         } else
    179                 outsb(dep->de_data_port, buf + offset, size);
    180        
    181         unsigned int i;
    182         for (i = 0; i < 100; i++) {
    183                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
    184                         break;
    185         }
    186        
    187         if (i == 100)
    188                 fprintf(stderr, "Remote DMA failed to complete\n");
    189 }
    190 
    191 int do_pwrite(dpeth_t *dep, packet_t *packet, int from_int)
    192 {
    193         int size;
    194         int sendq_head;
    195        
    196         assert(dep->up);
    197         assert(dep->enabled);
    198        
    199         if (dep->send_avail) {
    200                 fprintf(stderr, "Send already in progress\n");
    201                 return EBUSY;
    202         }
    203        
    204         sendq_head = dep->de_sendq_head;
    205         if (dep->de_sendq[sendq_head].sq_filled) {
    206                 if (from_int)
    207                         fprintf(stderr, "dp8390: should not be sending\n");
    208                 dep->send_avail = true;
    209                 dep->sending = false;
    210                
    211                 return EBUSY;
    212         }
    213        
    214         assert(!dep->sending);
    215        
    216         void *buf = packet_get_data(packet);
    217         size = packet_get_data_length(packet);
    218        
    219         if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED) {
    220                 fprintf(stderr, "dp8390: invalid packet size\n");
    221                 return EINVAL;
    222         }
    223        
    224         dp_user2nic(dep, buf, 0, dep->de_sendq[sendq_head].sq_sendpage
    225             * DP_PAGESIZE, size);
    226         dep->de_sendq[sendq_head].sq_filled = true;
    227        
    228         if (dep->de_sendq_tail == sendq_head) {
    229                 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
    230                 outb_reg0(dep, DP_TBCR1, size >> 8);
    231                 outb_reg0(dep, DP_TBCR0, size & 0xff);
    232                 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);  /* there it goes .. */
    233         } else
    234                 dep->de_sendq[sendq_head].sq_size = size;
    235        
    236         if (++sendq_head == dep->de_sendq_nr)
    237                 sendq_head = 0;
    238        
    239         assert(sendq_head < SENDQ_NR);
    240         dep->de_sendq_head = sendq_head;
    241         dep->sending = true;
    242        
    243         if (from_int)
    244                 return EOK;
    245        
    246         dep->sending = false;
    247        
    248         return EOK;
    249 }
    250 
    251 void dp_init(dpeth_t *dep)
    252 {
    253         int dp_rcr_reg;
    254         int i;
    255        
    256         /* General initialization */
    257         dep->enabled = false;
    258         dep->stopped = false;
    259         dep->sending = false;
    260         dep->send_avail = false;
    261         ne_init(dep);
    262        
    263         printf("Ethernet address ");
    264         for (i = 0; i < 6; i++)
    265                 printf("%02x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n');
     230        /* Disable the receiver and init TCR and DCR */
     231        pio_write_8(ne2k->port + DP_RCR, RCR_MON);
     232        pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
     233        pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
     234       
     235        /* Setup a transfer to get the MAC address */
     236        pio_write_8(ne2k->port + DP_RBCR0, ETH_ADDR << 1);
     237        pio_write_8(ne2k->port + DP_RBCR1, 0);
     238        pio_write_8(ne2k->port + DP_RSAR0, 0);
     239        pio_write_8(ne2k->port + DP_RSAR1, 0);
     240        pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
     241       
     242        for (i = 0; i < ETH_ADDR; i++)
     243                ne2k->mac[i] = pio_read_16(ne2k->data_port);
    266244       
    267245        /*
    268          * Initialization of the dp8390 following the mandatory procedure
     246         * Setup send queue. Use the first
     247         * SQ_PAGES of NE2000 memory for the send
     248         * buffer.
     249         */
     250        ne2k->sq.dirty = false;
     251        ne2k->sq.page = NE2K_START / DP_PAGE;
     252        fibril_mutex_initialize(&ne2k->sq_mutex);
     253        fibril_condvar_initialize(&ne2k->sq_cv);
     254       
     255        /*
     256         * Setup receive ring buffer. Use all the rest
     257         * of the NE2000 memory (except the first SQ_PAGES
     258         * reserved for the send buffer) for the receive
     259         * ring buffer.
     260         */
     261        ne2k->start_page = ne2k->sq.page + SQ_PAGES;
     262        ne2k->stop_page = ne2k->sq.page + NE2K_SIZE / DP_PAGE;
     263       
     264        /*
     265         * Initialization of the DP8390 following the mandatory procedure
    269266         * in reference manual ("DP8390D/NS32490D NIC Network Interface
    270267         * Controller", National Semiconductor, July 1995, Page 29).
     
    272269       
    273270        /* Step 1: */
    274         outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
     271        pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
    275272       
    276273        /* Step 2: */
    277         if (dep->de_16bit)
    278                 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
    279         else
    280                 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
     274        pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
    281275       
    282276        /* Step 3: */
    283         outb_reg0(dep, DP_RBCR0, 0);
    284         outb_reg0(dep, DP_RBCR1, 0);
     277        pio_write_8(ne2k->port + DP_RBCR0, 0);
     278        pio_write_8(ne2k->port + DP_RBCR1, 0);
    285279       
    286280        /* Step 4: */
    287         dp_rcr_reg = RCR_AB;  /* Enable broadcasts */
    288        
    289         outb_reg0(dep, DP_RCR, dp_rcr_reg);
     281        pio_write_8(ne2k->port + DP_RCR, RCR_AB);
    290282       
    291283        /* Step 5: */
    292         outb_reg0(dep, DP_TCR, TCR_INTERNAL);
     284        pio_write_8(ne2k->port + DP_TCR, TCR_INTERNAL);
    293285       
    294286        /* Step 6: */
    295         outb_reg0(dep, DP_BNRY, dep->de_startpage);
    296         outb_reg0(dep, DP_PSTART, dep->de_startpage);
    297         outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
     287        pio_write_8(ne2k->port + DP_BNRY, ne2k->start_page);
     288        pio_write_8(ne2k->port + DP_PSTART, ne2k->start_page);
     289        pio_write_8(ne2k->port + DP_PSTOP, ne2k->stop_page);
    298290       
    299291        /* Step 7: */
    300         outb_reg0(dep, DP_ISR, 0xFF);
     292        pio_write_8(ne2k->port + DP_ISR, 0xff);
    301293       
    302294        /* Step 8: */
    303         outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
    304             IMR_OVWE | IMR_CNTE);
     295        pio_write_8(ne2k->port + DP_IMR,
     296            IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
    305297       
    306298        /* Step 9: */
    307         outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
    308        
    309         outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
    310         outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
    311         outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
    312         outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
    313         outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
    314         outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
    315        
    316         outb_reg1(dep, DP_MAR0, 0xff);
    317         outb_reg1(dep, DP_MAR1, 0xff);
    318         outb_reg1(dep, DP_MAR2, 0xff);
    319         outb_reg1(dep, DP_MAR3, 0xff);
    320         outb_reg1(dep, DP_MAR4, 0xff);
    321         outb_reg1(dep, DP_MAR5, 0xff);
    322         outb_reg1(dep, DP_MAR6, 0xff);
    323         outb_reg1(dep, DP_MAR7, 0xff);
    324        
    325         outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
     299        pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
     300       
     301        pio_write_8(ne2k->port + DP_PAR0, ne2k->mac[0]);
     302        pio_write_8(ne2k->port + DP_PAR1, ne2k->mac[1]);
     303        pio_write_8(ne2k->port + DP_PAR2, ne2k->mac[2]);
     304        pio_write_8(ne2k->port + DP_PAR3, ne2k->mac[3]);
     305        pio_write_8(ne2k->port + DP_PAR4, ne2k->mac[4]);
     306        pio_write_8(ne2k->port + DP_PAR5, ne2k->mac[5]);
     307       
     308        pio_write_8(ne2k->port + DP_MAR0, 0xff);
     309        pio_write_8(ne2k->port + DP_MAR1, 0xff);
     310        pio_write_8(ne2k->port + DP_MAR2, 0xff);
     311        pio_write_8(ne2k->port + DP_MAR3, 0xff);
     312        pio_write_8(ne2k->port + DP_MAR4, 0xff);
     313        pio_write_8(ne2k->port + DP_MAR5, 0xff);
     314        pio_write_8(ne2k->port + DP_MAR6, 0xff);
     315        pio_write_8(ne2k->port + DP_MAR7, 0xff);
     316       
     317        pio_write_8(ne2k->port + DP_CURR, ne2k->start_page + 1);
    326318       
    327319        /* Step 10: */
    328         outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
     320        pio_write_8(ne2k->port + DP_CR, CR_DM_ABORT | CR_STA);
    329321       
    330322        /* Step 11: */
    331         outb_reg0(dep, DP_TCR, TCR_NORMAL);
    332        
    333         inb_reg0(dep, DP_CNTR0);  /* Reset counters by reading */
    334         inb_reg0(dep, DP_CNTR1);
    335         inb_reg0(dep, DP_CNTR2);
    336        
    337         /* Finish the initialization. */
    338         dep->enabled = true;
    339         for (i = 0; i < dep->de_sendq_nr; i++)
    340                 dep->de_sendq[i].sq_filled= 0;
    341        
    342         dep->de_sendq_head = 0;
    343         dep->de_sendq_tail = 0;
    344 }
    345 
    346 static void dp_reinit(dpeth_t *dep)
    347 {
    348         int dp_rcr_reg;
    349        
    350         outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
    351        
    352         /* Enable broadcasts */
    353         dp_rcr_reg = RCR_AB;
    354        
    355         outb_reg0(dep, DP_RCR, dp_rcr_reg);
    356 }
    357 
    358 static void dp_reset(dpeth_t *dep)
    359 {
    360         int i;
    361        
    362         /* Stop chip */
    363         outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
    364         outb_reg0(dep, DP_RBCR0, 0);
    365         outb_reg0(dep, DP_RBCR1, 0);
    366        
    367         for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
    368                 ; /* Do nothing */
    369        
    370         outb_reg0(dep, DP_TCR, TCR_1EXTERNAL | TCR_OFST);
    371         outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
    372         outb_reg0(dep, DP_TCR, TCR_NORMAL);
    373        
    374         /* Acknowledge the ISR_RDC (remote DMA) interrupt. */
    375         for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) &ISR_RDC) == 0); i++)
    376                 ; /* Do nothing */
    377        
    378         outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
     323        pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
     324       
     325        /* Reset counters by reading */
     326        pio_read_8(ne2k->port + DP_CNTR0);
     327        pio_read_8(ne2k->port + DP_CNTR1);
     328        pio_read_8(ne2k->port + DP_CNTR2);
     329       
     330        /* 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       
     351        ne2k->up = true;
     352        return EOK;
     353}
     354
     355/** Stop the network interface.
     356 *
     357 * @param[in,out] ne2k Network interface structure.
     358 *
     359 */
     360void ne2k_down(ne2k_t *ne2k)
     361{
     362        if ((ne2k->probed) && (ne2k->up)) {
     363                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               
     370                ne2k->up = false;
     371        }
     372}
     373
     374/** Send a frame.
     375 *
     376 * @param[in,out] ne2k   Network interface structure.
     377 * @param[in]     packet Frame to be sent.
     378 *
     379 */
     380void ne2k_send(ne2k_t *ne2k, packet_t *packet)
     381{
     382        assert(ne2k->probed);
     383        assert(ne2k->up);
     384       
     385        fibril_mutex_lock(&ne2k->sq_mutex);
     386       
     387        while (ne2k->sq.dirty)
     388                fibril_condvar_wait(&ne2k->sq_cv, &ne2k->sq_mutex);
     389       
     390        void *buf = packet_get_data(packet);
     391        size_t size = packet_get_data_length(packet);
     392       
     393        if ((size < ETH_MIN_PACK_SIZE) || (size > ETH_MAX_PACK_SIZE_TAGGED)) {
     394                fprintf(stderr, "%s: Frame dropped (invalid size %zu bytes)\n",
     395                    NAME, size);
     396                return;
     397        }
     398       
     399        /* Upload the frame to the ethernet card */
     400        ne2k_upload(ne2k, buf, ne2k->sq.page * DP_PAGE, size);
     401        ne2k->sq.dirty = true;
     402        ne2k->sq.size = size;
     403       
     404        /* Initialize the transfer */
     405        pio_write_8(ne2k->port + DP_TPSR, ne2k->sq.page);
     406        pio_write_8(ne2k->port + DP_TBCR0, size & 0xff);
     407        pio_write_8(ne2k->port + DP_TBCR1, (size >> 8) & 0xff);
     408        pio_write_8(ne2k->port + DP_CR, CR_TXP | CR_STA);
     409       
     410        fibril_mutex_unlock(&ne2k->sq_mutex);
     411}
     412
     413static void ne2k_reset(ne2k_t *ne2k)
     414{
     415        unsigned int i;
     416       
     417        /* Stop the chip */
     418        pio_write_8(ne2k->port + DP_CR, CR_STP | CR_DM_ABORT);
     419        pio_write_8(ne2k->port + DP_RBCR0, 0);
     420        pio_write_8(ne2k->port + DP_RBCR1, 0);
     421       
     422        for (i = 0; i < 0x1000; i++) {
     423                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RST) != 0)
     424                        break;
     425        }
     426       
     427        pio_write_8(ne2k->port + DP_TCR, TCR_1EXTERNAL | TCR_OFST);
     428        pio_write_8(ne2k->port + DP_CR, CR_STA | CR_DM_ABORT);
     429        pio_write_8(ne2k->port + DP_TCR, TCR_NORMAL);
     430       
     431        /* Acknowledge the ISR_RDC (remote DMA) interrupt */
     432        for (i = 0; i < 0x1000; i++) {
     433                if ((pio_read_8(ne2k->port + DP_ISR) & ISR_RDC) != 0)
     434                        break;
     435        }
     436       
     437        uint8_t val = pio_read_8(ne2k->port + DP_ISR);
     438        pio_write_8(ne2k->port + DP_ISR, val & ~ISR_RDC);
    379439       
    380440        /*
    381          * Reset the transmit ring. If we were transmitting a packet, we
    382          * pretend that the packet is processed. Higher layers will
     441         * Reset the transmit ring. If we were transmitting a frame,
     442         * we pretend that the packet is processed. Higher layers will
    383443         * retransmit if the packet wasn't actually sent.
    384444         */
    385         dep->de_sendq_head = 0;
    386         dep->de_sendq_tail = 0;
    387        
    388         for (i = 0; i < dep->de_sendq_nr; i++)
    389                 dep->de_sendq[i].sq_filled = 0;
    390        
    391         dep->send_avail = false;
    392         dep->stopped = false;
    393 }
    394 
    395 static uint8_t isr_acknowledge(dpeth_t *dep)
    396 {
    397         uint8_t isr = inb_reg0(dep, DP_ISR);
     445        fibril_mutex_lock(&ne2k->sq_mutex);
     446        ne2k->sq.dirty = false;
     447        fibril_mutex_unlock(&ne2k->sq_mutex);
     448}
     449
     450static uint8_t ne2k_isr_ack(ne2k_t *ne2k)
     451{
     452        uint8_t isr = pio_read_8(ne2k->port + DP_ISR);
    398453        if (isr != 0)
    399                 outb_reg0(dep, DP_ISR, isr);
     454                pio_write_8(ne2k->port + DP_ISR, isr);
    400455       
    401456        return isr;
    402457}
    403458
    404 void dp_check_ints(int nil_phone, device_id_t device_id, dpeth_t *dep, uint8_t isr)
    405 {
    406         int tsr;
    407         int size, sendq_tail;
    408        
    409         for (; (isr & 0x7f) != 0; isr = isr_acknowledge(dep)) {
     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);
     467        bzero(buf, length);
     468        uint8_t last = page + length / DP_PAGE;
     469       
     470        if (last >= ne2k->stop_page) {
     471                size_t left = (ne2k->stop_page - page) * DP_PAGE
     472                    - sizeof(recv_header_t);
     473               
     474                ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
     475                    left);
     476                ne2k_download(ne2k, buf + left, ne2k->start_page * DP_PAGE,
     477                    length - left);
     478        } else
     479                ne2k_download(ne2k, buf, page * DP_PAGE + sizeof(recv_header_t),
     480                    length);
     481       
     482        ne2k->stats.receive_packets++;
     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{
     488        while (true) {
     489                uint8_t boundary = pio_read_8(ne2k->port + DP_BNRY) + 1;
     490               
     491                if (boundary == ne2k->stop_page)
     492                        boundary = ne2k->start_page;
     493               
     494                pio_write_8(ne2k->port + DP_CR, CR_PS_P1 | CR_STA);
     495                uint8_t current = pio_read_8(ne2k->port + DP_CURR);
     496                pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STA);
     497               
     498                if (current == boundary)
     499                        /* No more frames to process */
     500                        break;
     501               
     502                recv_header_t header;
     503                size_t size = sizeof(header);
     504                size_t offset = boundary * DP_PAGE;
     505               
     506                /* Get the frame header */
     507                pio_write_8(ne2k->port + DP_RBCR0, size & 0xff);
     508                pio_write_8(ne2k->port + DP_RBCR1, (size >> 8) & 0xff);
     509                pio_write_8(ne2k->port + DP_RSAR0, offset & 0xff);
     510                pio_write_8(ne2k->port + DP_RSAR1, (offset >> 8) & 0xff);
     511                pio_write_8(ne2k->port + DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
     512               
     513                pio_read_buf_16(ne2k->data_port, (void *) &header, size);
     514               
     515                size_t length =
     516                    (((size_t) header.rbcl) | (((size_t) header.rbch) << 8)) - size;
     517                uint8_t next = header.next;
     518               
     519                if ((length < ETH_MIN_PACK_SIZE)
     520                    || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
     521                        fprintf(stderr, "%s: Rant frame (%zu bytes)\n", NAME, length);
     522                        next = current;
     523                } else if ((header.next < ne2k->start_page)
     524                    || (header.next > ne2k->stop_page)) {
     525                        fprintf(stderr, "%s: Malformed next frame %u\n", NAME,
     526                            header.next);
     527                        next = current;
     528                } else if (header.status & RSR_FO) {
     529                        /*
     530                         * This is very serious, so we issue a warning and
     531                         * reset the buffers.
     532                         */
     533                        fprintf(stderr, "%s: FIFO overrun\n", NAME);
     534                        ne2k->overruns++;
     535                        next = current;
     536                } else if ((header.status & RSR_PRX) && (ne2k->up))
     537                        ne2k_receive_frame(ne2k, boundary, length, nil_phone, device_id);
     538               
     539                /*
     540                 * Update the boundary pointer
     541                 * to the value of the page
     542                 * prior to the next packet to
     543                 * be processed.
     544                 */
     545                if (next == ne2k->start_page)
     546                        next = ne2k->stop_page - 1;
     547                else
     548                        next--;
     549               
     550                pio_write_8(ne2k->port + DP_BNRY, next);
     551        }
     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)) {
    410560                if (isr & (ISR_PTX | ISR_TXE)) {
    411561                        if (isr & ISR_TXE)
    412                                 dep->de_stat.ets_sendErr++;
     562                                ne2k->stats.send_errors++;
    413563                        else {
    414                                 tsr = inb_reg0(dep, DP_TSR);
     564                                uint8_t tsr = pio_read_8(ne2k->port + DP_TSR);
    415565                               
    416566                                if (tsr & TSR_PTX)
    417                                         dep->de_stat.ets_packetT++;
     567                                        ne2k->stats.send_packets++;
    418568                               
    419569                                if (tsr & TSR_COL)
    420                                         dep->de_stat.ets_collision++;
     570                                        ne2k->stats.collisions++;
    421571                               
    422572                                if (tsr & TSR_ABT)
    423                                         dep->de_stat.ets_transAb++;
     573                                        ne2k->stats.send_aborted_errors++;
    424574                               
    425575                                if (tsr & TSR_CRS)
    426                                         dep->de_stat.ets_carrSense++;
     576                                        ne2k->stats.send_carrier_errors++;
    427577                               
    428                                 if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10))
    429                                         printf("FIFO underrun\n");
     578                                if (tsr & TSR_FU) {
     579                                        ne2k->underruns++;
     580                                        if (ne2k->underruns < NE2K_ERL)
     581                                                fprintf(stderr, "%s: FIFO underrun\n", NAME);
     582                                }
    430583                               
    431                                 if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10))
    432                                         printf("CD heart beat failure\n");
     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                                }
    433589                               
    434590                                if (tsr & TSR_OWC)
    435                                         dep->de_stat.ets_OWC++;
     591                                        ne2k->stats.send_window_errors++;
    436592                        }
    437593                       
    438                         sendq_tail = dep->de_sendq_tail;
     594                        fibril_mutex_lock(&ne2k->sq_mutex);
    439595                       
    440                         if (!(dep->de_sendq[sendq_tail].sq_filled)) {
    441                                 printf("PTX interrupt, but no frame to send\n");
    442                                 continue;
     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);
    443605                        }
    444606                       
    445                         dep->de_sendq[sendq_tail].sq_filled = false;
    446                        
    447                         if (++sendq_tail == dep->de_sendq_nr)
    448                                 sendq_tail = 0;
    449                        
    450                         dep->de_sendq_tail = sendq_tail;
    451                        
    452                         if (dep->de_sendq[sendq_tail].sq_filled) {
    453                                 size = dep->de_sendq[sendq_tail].sq_size;
    454                                 outb_reg0(dep, DP_TPSR,
    455                                     dep->de_sendq[sendq_tail].sq_sendpage);
    456                                 outb_reg0(dep, DP_TBCR1, size >> 8);
    457                                 outb_reg0(dep, DP_TBCR0, size & 0xff);
    458                                 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
    459                         }
    460                        
    461                         dep->send_avail = false;
     607                        fibril_mutex_unlock(&ne2k->sq_mutex);
    462608                }
    463609               
    464610                if (isr & ISR_PRX)
    465                         dp_recv(nil_phone, device_id, dep);
     611                        ne2k_receive(ne2k, nil_phone, device_id);
    466612               
    467613                if (isr & ISR_RXE)
    468                         dep->de_stat.ets_recvErr++;
     614                        ne2k->stats.receive_errors++;
    469615               
    470616                if (isr & ISR_CNT) {
    471                         dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
    472                         dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
    473                         dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
    474                 }
    475                
    476                 if (isr & ISR_OVW)
    477                         dep->de_stat.ets_OVW++;
    478                
    479                 if (isr & ISR_RDC) {
    480                         /* Nothing to do */
     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);
    481623                }
    482624               
     
    486628                         * chip is shutdown. We set the flag 'stopped'
    487629                         * and continue processing arrived packets. When the
    488                          * receive buffer is empty, we reset the dp8390.
     630                         * receive buffer is empty, we reset the DP8390.
    489631                         */
    490                         dep->stopped = true;
    491                         break;
     632                        stopped = true;
    492633                }
    493634        }
    494635       
    495         if (dep->stopped) {
     636        if (stopped) {
    496637                /*
    497638                 * The chip is stopped, and all arrived
    498639                 * frames are delivered.
    499640                 */
    500                 dp_reset(dep);
    501         }
    502        
    503         dep->sending = false;
    504 }
    505 
    506 static void dp_getblock(dpeth_t *dep, int page, size_t offset, size_t size, void *dst)
    507 {
    508         offset = page * DP_PAGESIZE + offset;
    509        
    510         outb_reg0(dep, DP_RBCR0, size & 0xff);
    511         outb_reg0(dep, DP_RBCR1, size >> 8);
    512         outb_reg0(dep, DP_RSAR0, offset & 0xff);
    513         outb_reg0(dep, DP_RSAR1, offset >> 8);
    514         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
    515        
    516         if (dep->de_16bit) {
    517                 assert((size % 2) == 0);
    518                 insw(dep->de_data_port, dst, size);
    519         } else
    520                 insb(dep->de_data_port, dst, size);
    521 }
    522 
    523 static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep)
    524 {
    525         dp_rcvhdr_t header;
    526         int pageno, curr, next;
    527         size_t length;
    528         int packet_processed, r;
    529         uint16_t eth_type;
    530        
    531         packet_processed = false;
    532         pageno = inb_reg0(dep, DP_BNRY) + 1;
    533         if (pageno == dep->de_stoppage)
    534                 pageno = dep->de_startpage;
    535        
    536         do {
    537                 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
    538                 curr = inb_reg1(dep, DP_CURR);
    539                 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
    540                
    541                 if (curr == pageno)
    542                         break;
    543                
    544                 dp_getblock(dep, pageno, (size_t) 0, sizeof(header), &header);
    545                 dp_getblock(dep, pageno, sizeof(header) +
    546                     2 * sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
    547                
    548                 length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
    549                 next = header.dr_next;
    550                 if ((length < ETH_MIN_PACK_SIZE) || (length > ETH_MAX_PACK_SIZE_TAGGED)) {
    551                         printf("Packet with strange length arrived: %zu\n", length);
    552                         next = curr;
    553                 } else if ((next < dep->de_startpage) || (next >= dep->de_stoppage)) {
    554                         printf("Strange next page\n");
    555                         next = curr;
    556                 } else if (header.dr_status & RSR_FO) {
    557                         /*
    558                          * This is very serious, so we issue a warning and
    559                          * reset the buffers
    560                          */
    561                         printf("FIFO overrun, resetting receive buffer\n");
    562                         dep->de_stat.ets_fifoOver++;
    563                         next = curr;
    564                 } else if ((header.dr_status & RSR_PRX) && (dep->enabled)) {
    565                         r = dp_pkt2user(nil_phone, device_id, dep, pageno, length);
    566                         if (r != EOK)
    567                                 return;
    568                        
    569                         packet_processed = true;
    570                         dep->de_stat.ets_packetR++;
    571                 }
    572                
    573                 if (next == dep->de_startpage)
    574                         outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
    575                 else
    576                         outb_reg0(dep, DP_BNRY, next - 1);
    577                
    578                 pageno = next;
    579         } while (!packet_processed);
    580 }
    581 
    582 static void dp_nic2user(dpeth_t *dep, int nic_addr, void *buf, size_t offset, size_t size)
    583 {
    584         size_t ecount = size & ~1;
    585        
    586         if (dep->de_16bit) {
    587                 outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
    588                 outb_reg0(dep, DP_RBCR1, ecount >> 8);
    589         } else {
    590                 outb_reg0(dep, DP_RBCR0, size & 0xff);
    591                 outb_reg0(dep, DP_RBCR1, size >> 8);
    592         }
    593        
    594         outb_reg0(dep, DP_RSAR0, nic_addr & 0xff);
    595         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
    596         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
    597        
    598         if (dep->de_16bit) {
    599                 void *ptr = buf + offset;
    600                
    601                 if (ecount != 0) {
    602                         insw(dep->de_data_port, ptr, ecount);
    603                         size -= ecount;
    604                         offset += ecount;
    605                         ptr += ecount;
    606                 }
    607                
    608                 if (size) {
    609                         assert(size == 1);
    610                        
    611                         uint16_t two_bytes = inw(dep->de_data_port);
    612                         memcpy(ptr, &(((uint8_t *) &two_bytes)[0]), 1);
    613                 }
    614         } else
    615                 insb(dep->de_data_port, buf + offset, size);
    616 }
    617 
    618 static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length)
    619 {
    620         int last, count;
    621         packet_t *packet;
    622        
    623         packet = netif_packet_get_1(length);
    624         if (!packet)
    625                 return ENOMEM;
    626        
    627         void *buf = packet_suffix(packet, length);
    628        
    629         last = page + (length - 1) / DP_PAGESIZE;
    630         if (last >= dep->de_stoppage) {
    631                 count = (dep->de_stoppage - page) * DP_PAGESIZE - sizeof(dp_rcvhdr_t);
    632                
    633                 dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
    634                     buf, 0, count);
    635                 dp_nic2user(dep, dep->de_startpage * DP_PAGESIZE,
    636                     buf, count, length - count);
    637         } else {
    638                 dp_nic2user(dep, page * DP_PAGESIZE + sizeof(dp_rcvhdr_t),
    639                     buf, 0, length);
    640         }
    641        
    642         nil_received_msg(nil_phone, device_id, packet, SERVICE_NONE);
    643        
    644         return EOK;
    645 }
    646 
    647 static void conf_hw(dpeth_t *dep)
    648 {
    649         if (!ne_probe(dep)) {
    650                 printf("No ethernet card found at %#lx\n", dep->de_base_port);
    651                 dep->up = false;
    652                 return;
    653         }
    654        
    655         dep->up = true;
    656         dep->enabled = false;
    657         dep->stopped = false;
    658         dep->sending = false;
    659         dep->send_avail = false;
    660 }
    661 
    662 static void insb(port_t port, void *buf, size_t size)
    663 {
    664         size_t i;
    665        
    666         for (i = 0; i < size; i++)
    667                 *((uint8_t *) buf + i) = inb(port);
    668 }
    669 
    670 static void insw(port_t port, void *buf, size_t size)
    671 {
    672         size_t i;
    673        
    674         for (i = 0; i * 2 < size; i++)
    675                 *((uint16_t *) buf + i) = inw(port);
    676 }
    677 
    678 static void outsb(port_t port, void *buf, size_t size)
    679 {
    680         size_t i;
    681        
    682         for (i = 0; i < size; i++)
    683                 outb(port, *((uint8_t *) buf + i));
    684 }
    685 
    686 static void outsw(port_t port, void *buf, size_t size)
    687 {
    688         size_t i;
    689        
    690         for (i = 0; i * 2 < size; i++)
    691                 outw(port, *((uint16_t *) buf + i));
     641                ne2k_reset(ne2k);
     642        }
     643       
     644        /* Signal a next frame to be sent */
     645        if (signal)
     646                fibril_condvar_broadcast(&ne2k->sq_cv);
    692647}
    693648
Note: See TracChangeset for help on using the changeset viewer.