Ignore:
File:
1 edited

Legend:

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

    r3c106e88 r7922dea  
    3838 */
    3939
    40 /** @addtogroup ne2000
     40/** @addtogroup dp8390
    4141 *  @{
    4242 */
    4343
    4444/** @file
    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  *
     45 *  DP8390 network interface core implementation.
    5046 */
    5147
     
    5349#include <byteorder.h>
    5450#include <errno.h>
    55 #include <libarch/ddi.h>
    56 #include <netif_skel.h>
     51#include <netif_local.h>
    5752#include <net/packet.h>
    5853#include <nil_interface.h>
    5954#include <packet_client.h>
     55#include "dp8390_drv.h"
     56#include "dp8390_port.h"
    6057#include "dp8390.h"
    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  */
    97 typedef 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;
     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 */
     67static void outsb(port_t port, void * buf, size_t size);
    11068
    11169/** Read a memory block word by word.
    11270 *
    113  * @param[in]  port Source address.
    114  * @param[out] buf  Destination buffer.
    115  * @param[in]  size Memory block size in bytes.
    116  *
    117  */
    118 static 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  */
    133 static 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 
    141 static 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 
    165 static 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  */
    201 int ne2k_probe(ne2k_t *ne2k, void *port, int irq)
    202 {
     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 */
     76static 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
     85static void dp_init(dpeth_t *dep);
     86static void dp_reinit(dpeth_t *dep);
     87static void dp_reset(dpeth_t *dep);
     88static void dp_recv(int nil_phone, device_id_t device_id, dpeth_t *dep);
     89static int dp_pkt2user(int nil_phone, device_id_t device_id, dpeth_t *dep, int page, int length);
     90static void conf_hw(dpeth_t *dep);
     91static void insb(port_t port, void *buf, size_t size);
     92static void insw(port_t port, void *buf, size_t size);
     93
     94int 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. */
     100                return EXDEV;
     101       
     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 */
     116int 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
     129void 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
     142static 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       
    203181        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
     191int 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
     251void dp_init(dpeth_t *dep)
     252{
     253        int dp_rcr_reg;
     254        int i;
    204255       
    205256        /* 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))
    228                 return EXDEV;
    229        
    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);
     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("%x%c", dep->de_address.ea_addr[i], i < 5 ? ':' : '\n');
    244266       
    245267        /*
    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
     268         * Initialization of the dp8390 following the mandatory procedure
    266269         * in reference manual ("DP8390D/NS32490D NIC Network Interface
    267270         * Controller", National Semiconductor, July 1995, Page 29).
     
    269272       
    270273        /* Step 1: */
    271         pio_write_8(ne2k->port + DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
     274        outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
    272275       
    273276        /* Step 2: */
    274         pio_write_8(ne2k->port + DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
     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);
    275281       
    276282        /* Step 3: */
    277         pio_write_8(ne2k->port + DP_RBCR0, 0);
    278         pio_write_8(ne2k->port + DP_RBCR1, 0);
     283        outb_reg0(dep, DP_RBCR0, 0);
     284        outb_reg0(dep, DP_RBCR1, 0);
    279285       
    280286        /* Step 4: */
    281         pio_write_8(ne2k->port + DP_RCR, RCR_AB);
     287        dp_rcr_reg = RCR_AB;  /* Enable broadcasts */
     288       
     289        outb_reg0(dep, DP_RCR, dp_rcr_reg);
    282290       
    283291        /* Step 5: */
    284         pio_write_8(ne2k->port + DP_TCR, TCR_INTERNAL);
     292        outb_reg0(dep, DP_TCR, TCR_INTERNAL);
    285293       
    286294        /* Step 6: */
    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);
     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);
    290298       
    291299        /* Step 7: */
    292         pio_write_8(ne2k->port + DP_ISR, 0xff);
     300        outb_reg0(dep, DP_ISR, 0xFF);
    293301       
    294302        /* Step 8: */
    295         pio_write_8(ne2k->port + DP_IMR,
    296             IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE | IMR_CNTE);
     303        outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
     304            IMR_OVWE | IMR_CNTE);
    297305       
    298306        /* Step 9: */
    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);
     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);
    318326       
    319327        /* Step 10: */
    320         pio_write_8(ne2k->port + DP_CR, CR_DM_ABORT | CR_STA);
     328        outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
    321329       
    322330        /* Step 11: */
    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  */
    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        
    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  */
    360 void 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  */
    380 void 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 
    413 static 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);
     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
     346static 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
     358static 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);
    439379       
    440380        /*
    441          * Reset the transmit ring. If we were transmitting a frame,
    442          * we pretend that the packet is processed. Higher layers will
     381         * Reset the transmit ring. If we were transmitting a packet, we
     382         * pretend that the packet is processed. Higher layers will
    443383         * retransmit if the packet wasn't actually sent.
    444384         */
    445         fibril_mutex_lock(&ne2k->sq_mutex);
    446         ne2k->sq.dirty = false;
    447         fibril_mutex_unlock(&ne2k->sq_mutex);
    448 }
    449 
    450 static uint8_t ne2k_isr_ack(ne2k_t *ne2k)
    451 {
    452         uint8_t isr = pio_read_8(ne2k->port + DP_ISR);
     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
     395static uint8_t isr_acknowledge(dpeth_t *dep)
     396{
     397        uint8_t isr = inb_reg0(dep, DP_ISR);
    453398        if (isr != 0)
    454                 pio_write_8(ne2k->port + DP_ISR, isr);
     399                outb_reg0(dep, DP_ISR, isr);
    455400       
    456401        return isr;
    457402}
    458403
    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);
    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 
    486 static 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 
    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)) {
     404void 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)) {
    560410                if (isr & (ISR_PTX | ISR_TXE)) {
    561411                        if (isr & ISR_TXE)
    562                                 ne2k->stats.send_errors++;
     412                                dep->de_stat.ets_sendErr++;
    563413                        else {
    564                                 uint8_t tsr = pio_read_8(ne2k->port + DP_TSR);
     414                                tsr = inb_reg0(dep, DP_TSR);
    565415                               
    566416                                if (tsr & TSR_PTX)
    567                                         ne2k->stats.send_packets++;
     417                                        dep->de_stat.ets_packetT++;
    568418                               
    569419                                if (tsr & TSR_COL)
    570                                         ne2k->stats.collisions++;
     420                                        dep->de_stat.ets_collision++;
    571421                               
    572422                                if (tsr & TSR_ABT)
    573                                         ne2k->stats.send_aborted_errors++;
     423                                        dep->de_stat.ets_transAb++;
    574424                               
    575425                                if (tsr & TSR_CRS)
    576                                         ne2k->stats.send_carrier_errors++;
     426                                        dep->de_stat.ets_carrSense++;
    577427                               
    578                                 if (tsr & TSR_FU) {
    579                                         ne2k->underruns++;
    580                                         if (ne2k->underruns < NE2K_ERL)
    581                                                 fprintf(stderr, "%s: FIFO underrun\n", NAME);
    582                                 }
     428                                if ((tsr & TSR_FU) && (++dep->de_stat.ets_fifoUnder <= 10))
     429                                        printf("FIFO underrun\n");
    583430                               
    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                                 }
     431                                if ((tsr & TSR_CDH) && (++dep->de_stat.ets_CDheartbeat <= 10))
     432                                        printf("CD heart beat failure\n");
    589433                               
    590434                                if (tsr & TSR_OWC)
    591                                         ne2k->stats.send_window_errors++;
     435                                        dep->de_stat.ets_OWC++;
    592436                        }
    593437                       
    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);
     438                        sendq_tail = dep->de_sendq_tail;
     439                       
     440                        if (!(dep->de_sendq[sendq_tail].sq_filled)) {
     441                                printf("PTX interrupt, but no frame to send\n");
     442                                continue;
    605443                        }
    606444                       
    607                         fibril_mutex_unlock(&ne2k->sq_mutex);
     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;
    608462                }
    609463               
    610464                if (isr & ISR_PRX)
    611                         ne2k_receive(ne2k, nil_phone, device_id);
     465                        dp_recv(nil_phone, device_id, dep);
    612466               
    613467                if (isr & ISR_RXE)
    614                         ne2k->stats.receive_errors++;
     468                        dep->de_stat.ets_recvErr++;
    615469               
    616470                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);
     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 */
    623481                }
    624482               
     
    628486                         * chip is shutdown. We set the flag 'stopped'
    629487                         * and continue processing arrived packets. When the
    630                          * receive buffer is empty, we reset the DP8390.
     488                         * receive buffer is empty, we reset the dp8390.
    631489                         */
    632                         stopped = true;
    633                 }
    634         }
    635        
    636         if (stopped) {
     490                        dep->stopped = true;
     491                        break;
     492                }
     493        }
     494       
     495        if (dep->stopped) {
    637496                /*
    638497                 * The chip is stopped, and all arrived
    639498                 * frames are delivered.
    640499                 */
    641                 ne2k_reset(ne2k);
    642         }
    643        
    644         /* Signal a next frame to be sent */
    645         if (signal)
    646                 fibril_condvar_broadcast(&ne2k->sq_cv);
     500                dp_reset(dep);
     501        }
     502       
     503        dep->sending = false;
     504}
     505
     506static 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
     523static 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
     582static 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
     618static 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
     647static 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
     662static 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
     670static 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
     678static 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
     686static 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));
    647692}
    648693
Note: See TracChangeset for help on using the changeset viewer.