Changeset 3c106e88 in mainline


Ignore:
Timestamp:
2011-01-09T23:09:02Z (13 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

Location:
uspace/srv/hw/netif/dp8390
Files:
4 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/hw/netif/dp8390/Makefile

    r7ea7db31 r3c106e88  
    4343SOURCES = \
    4444        dp8390.c \
    45         dp8390_module.c \
    4645        ne2000.c
    4746
  • 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
  • uspace/srv/hw/netif/dp8390/dp8390.h

    r7ea7db31 r3c106e88  
    3838 */
    3939
    40 /** @addtogroup dp8390
     40/** @addtogroup ne2000
    4141 *  @{
    4242 */
     
    4949#define __NET_NETIF_DP8390_H__
    5050
     51#include <fibril_synch.h>
    5152#include <net/packet.h>
    52 #include "dp8390_port.h"
     53
     54/** Module name */
     55#define NAME  "ne2000"
    5356
    5457/** Input/output size */
    55 #define DP8390_IO_SIZE  0x0020
     58#define NE2K_IO_SIZE  0x0020
     59
     60/** Ethernet address length */
     61#define ETH_ADDR  6
    5662
    5763/* National Semiconductor DP8390 Network Interface Controller. */
     
    105111#define DP_MAR7  0x0f  /**< Multicast Address Register 7 */
    106112
    107 /* Bits in dp_cr */
    108 #define CR_STP          0x01    /* Stop: software reset              */
    109 #define CR_STA          0x02    /* Start: activate NIC               */
    110 #define CR_TXP          0x04    /* Transmit Packet                   */
    111 #define CR_DMA          0x38    /* Mask for DMA control              */
    112 #define CR_DM_NOP       0x00    /* DMA: No Operation                 */
    113 #define CR_DM_RR        0x08    /* DMA: Remote Read                  */
    114 #define CR_DM_RW        0x10    /* DMA: Remote Write                 */
    115 #define CR_DM_SP        0x18    /* DMA: Send Packet                  */
    116 #define CR_DM_ABORT     0x20    /* DMA: Abort Remote DMA Operation   */
    117 #define CR_PS           0xC0    /* Mask for Page Select              */
    118 #define CR_PS_P0        0x00    /* Register Page 0                   */
    119 #define CR_PS_P1        0x40    /* Register Page 1                   */
    120 #define CR_PS_P2        0x80    /* Register Page 2                   */
    121 #define CR_PS_T1        0xC0    /* Test Mode Register Map            */
    122 
    123 /* Bits in dp_isr */
    124 #define ISR_PRX         0x01    /* Packet Received with no errors    */
    125 #define ISR_PTX         0x02    /* Packet Transmitted with no errors */
    126 #define ISR_RXE         0x04    /* Receive Error                     */
    127 #define ISR_TXE         0x08    /* Transmit Error                    */
    128 #define ISR_OVW         0x10    /* Overwrite Warning                 */
    129 #define ISR_CNT         0x20    /* Counter Overflow                  */
    130 #define ISR_RDC         0x40    /* Remote DMA Complete               */
    131 #define ISR_RST         0x80    /* Reset Status                      */
    132 
    133 /* Bits in dp_imr */
    134 #define IMR_PRXE        0x01    /* Packet Received iEnable           */
    135 #define IMR_PTXE        0x02    /* Packet Transmitted iEnable        */
    136 #define IMR_RXEE        0x04    /* Receive Error iEnable             */
    137 #define IMR_TXEE        0x08    /* Transmit Error iEnable            */
    138 #define IMR_OVWE        0x10    /* Overwrite Warning iEnable         */
    139 #define IMR_CNTE        0x20    /* Counter Overflow iEnable          */
    140 #define IMR_RDCE        0x40    /* DMA Complete iEnable              */
    141 
    142 /* Bits in dp_dcr */
    143 #define DCR_WTS         0x01    /* Word Transfer Select              */
    144 #define DCR_BYTEWIDE    0x00    /* WTS: byte wide transfers          */
    145 #define DCR_WORDWIDE    0x01    /* WTS: word wide transfers          */
    146 #define DCR_BOS         0x02    /* Byte Order Select                 */
    147 #define DCR_LTLENDIAN   0x00    /* BOS: Little Endian                */
    148 #define DCR_BIGENDIAN   0x02    /* BOS: Big Endian                   */
    149 #define DCR_LAS         0x04    /* Long Address Select               */
    150 #define DCR_BMS         0x08    /* Burst Mode Select
    151                                  * Called Loopback Select (LS) in
    152                                  * later manuals. Should be set.     */
    153 #define DCR_AR          0x10    /* Autoinitialize Remote             */
    154 #define DCR_FTS         0x60    /* Fifo Threshold Select             */
    155 #define DCR_2BYTES      0x00    /* 2 bytes                           */
    156 #define DCR_4BYTES      0x40    /* 4 bytes                           */
    157 #define DCR_8BYTES      0x20    /* 8 bytes                           */
    158 #define DCR_12BYTES     0x60    /* 12 bytes                          */
    159 
    160 /* Bits in dp_tcr */
    161 #define TCR_CRC         0x01    /* Inhibit CRC                       */
    162 #define TCR_ELC         0x06    /* Encoded Loopback Control          */
    163 #define TCR_NORMAL      0x00    /* ELC: Normal Operation             */
    164 #define TCR_INTERNAL    0x02    /* ELC: Internal Loopback            */
    165 #define TCR_0EXTERNAL   0x04    /* ELC: External Loopback LPBK=0     */
    166 #define TCR_1EXTERNAL   0x06    /* ELC: External Loopback LPBK=1     */
    167 #define TCR_ATD         0x08    /* Auto Transmit Disable             */
    168 #define TCR_OFST        0x10    /* Collision Offset Enable (be nice) */
    169 
    170 /* Bits in dp_tsr */
    171 #define TSR_PTX         0x01    /* Packet Transmitted (without error)*/
    172 #define TSR_DFR         0x02    /* Transmit Deferred, reserved in
    173                                  * later manuals.                    */
    174 #define TSR_COL         0x04    /* Transmit Collided                 */
    175 #define TSR_ABT         0x08    /* Transmit Aborted                  */
    176 #define TSR_CRS         0x10    /* Carrier Sense Lost                */
    177 #define TSR_FU          0x20    /* FIFO Underrun                     */
    178 #define TSR_CDH         0x40    /* CD Heartbeat                      */
    179 #define TSR_OWC         0x80    /* Out of Window Collision           */
    180 
    181 /* Bits in tp_rcr */
    182 #define RCR_SEP         0x01    /* Save Errored Packets              */
    183 #define RCR_AR          0x02    /* Accept Runt Packets               */
    184 #define RCR_AB          0x04    /* Accept Broadcast                  */
    185 #define RCR_AM          0x08    /* Accept Multicast                  */
    186 #define RCR_PRO         0x10    /* Physical Promiscuous              */
    187 #define RCR_MON         0x20    /* Monitor Mode                      */
    188 
    189 /* Bits in dp_rsr */
    190 #define RSR_PRX         0x01    /* Packet Received Intact            */
    191 #define RSR_CRC         0x02    /* CRC Error                         */
    192 #define RSR_FAE         0x04    /* Frame Alignment Error             */
    193 #define RSR_FO          0x08    /* FIFO Overrun                      */
    194 #define RSR_MPA         0x10    /* Missed Packet                     */
    195 #define RSR_PHY         0x20    /* Multicast Address Match           */
    196 #define RSR_DIS         0x40    /* Receiver Disabled                 */
    197 #define RSR_DFR         0x80    /* In later manuals: Deferring       */
    198 
    199 /** Type definition of the receive header
    200  *
    201  */
    202 typedef struct dp_rcvhdr {
    203         /** Copy of rsr */
    204         uint8_t dr_status;
    205        
    206         /** Pointer to next packet */
    207         uint8_t dr_next;
    208        
    209         /** Receive Byte Count Low */
    210         uint8_t dr_rbcl;
    211        
    212         /** Receive Byte Count High */
    213         uint8_t dr_rbch;
    214 } dp_rcvhdr_t;
    215 
    216 /** Page size */
    217 #define DP_PAGESIZE  256
    218 
    219 /** Read 1 byte from the zero page register.
    220  *  @param[in] dep The network interface structure.
    221  *  @param[in] reg The register offset.
    222  *  @returns The read value.
    223  */
    224 #define inb_reg0(dep, reg)  (inb(dep->de_dp8390_port + reg))
    225 
    226 /** Write 1 byte zero page register.
    227  *  @param[in] dep The network interface structure.
    228  *  @param[in] reg The register offset.
    229  *  @param[in] data The value to be written.
    230  */
    231 #define outb_reg0(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
    232 
    233 /** Read 1 byte from the first page register.
    234  *  @param[in] dep The network interface structure.
    235  *  @param[in] reg The register offset.
    236  *  @returns The read value.
    237  */
    238 #define inb_reg1(dep, reg)  (inb(dep->de_dp8390_port + reg))
    239 
    240 /** Write 1 byte first page register.
    241  *  @param[in] dep The network interface structure.
    242  *  @param[in] reg The register offset.
    243  *  @param[in] data The value to be written.
    244  */
    245 #define outb_reg1(dep, reg, data)  (outb(dep->de_dp8390_port + reg, data))
    246 
    247 #define SENDQ_NR     1  /* Maximum size of the send queue */
    248 #define SENDQ_PAGES  6  /* 6 * DP_PAGESIZE >= 1514 bytes */
    249 
    250 typedef struct dpeth {
    251         /*
    252          * The de_base_port field is the starting point of the probe.
    253          * The conf routine also fills de_irq. If the probe
    254          * routine knows the irq and/or memory address because they are
    255          * hardwired in the board, the probe should modify these fields.
    256          */
    257         port_t de_base_port;
    258         int de_irq;
    259        
    260         ether_addr_t de_address;
    261         port_t de_dp8390_port;
    262         port_t de_data_port;
    263         int de_16bit;
    264         long de_ramsize;
    265         int de_offset_page;
    266         int de_startpage;
    267         int de_stoppage;
    268        
    269         /* Do it yourself send queue */
    270         struct sendq {
    271                 int sq_filled;    /* this buffer contains a packet */
    272                 int sq_size;      /* with this size */
    273                 int sq_sendpage;  /* starting page of the buffer */
    274         } de_sendq[SENDQ_NR];
    275        
    276         int de_sendq_nr;
    277         int de_sendq_head;  /* Enqueue at the head */
    278         int de_sendq_tail;  /* Dequeue at the tail */
    279        
    280         /* Fields for internal use by the dp8390 driver. */
    281         eth_stat_t de_stat;
    282        
    283         /* Driver flags */
     113/* Bits in Command Register */
     114#define CR_STP       0x01  /**< Stop (software reset) */
     115#define CR_STA       0x02  /**< Start (activate NIC) */
     116#define CR_TXP       0x04  /**< Transmit Packet */
     117#define CR_DMA       0x38  /**< Mask for DMA control */
     118#define CR_DM_NOP    0x00  /**< DMA: No Operation */
     119#define CR_DM_RR     0x08  /**< DMA: Remote Read */
     120#define CR_DM_RW     0x10  /**< DMA: Remote Write */
     121#define CR_DM_SP     0x18  /**< DMA: Send Packet */
     122#define CR_DM_ABORT  0x20  /**< DMA: Abort Remote DMA Operation */
     123#define CR_PS        0xc0  /**< Mask for Page Select */
     124#define CR_PS_P0     0x00  /**< Register Page 0 */
     125#define CR_PS_P1     0x40  /**< Register Page 1 */
     126#define CR_PS_P2     0x80  /**< Register Page 2 */
     127#define CR_PS_T1     0xc0  /**< Test Mode Register Map */
     128
     129/* Bits in Interrupt State Register */
     130#define ISR_PRX  0x01  /**< Packet Received with no errors */
     131#define ISR_PTX  0x02  /**< Packet Transmitted with no errors */
     132#define ISR_RXE  0x04  /**< Receive Error */
     133#define ISR_TXE  0x08  /**< Transmit Error */
     134#define ISR_OVW  0x10  /**< Overwrite Warning */
     135#define ISR_CNT  0x20  /**< Counter Overflow */
     136#define ISR_RDC  0x40  /**< Remote DMA Complete */
     137#define ISR_RST  0x80  /**< Reset Status */
     138
     139/* Bits in Interrupt Mask Register */
     140#define IMR_PRXE  0x01  /**< Packet Received Interrupt Enable */
     141#define IMR_PTXE  0x02  /**< Packet Transmitted Interrupt Enable */
     142#define IMR_RXEE  0x04  /**< Receive Error Interrupt Enable */
     143#define IMR_TXEE  0x08  /**< Transmit Error Interrupt Enable */
     144#define IMR_OVWE  0x10  /**< Overwrite Warning Interrupt Enable */
     145#define IMR_CNTE  0x20  /**< Counter Overflow Interrupt Enable */
     146#define IMR_RDCE  0x40  /**< DMA Complete Interrupt Enable */
     147
     148/* Bits in Data Configuration Register */
     149#define DCR_WTS        0x01  /**< Word Transfer Select */
     150#define DCR_BYTEWIDE   0x00  /**< WTS: byte wide transfers */
     151#define DCR_WORDWIDE   0x01  /**< WTS: word wide transfers */
     152#define DCR_BOS        0x02  /**< Byte Order Select */
     153#define DCR_LTLENDIAN  0x00  /**< BOS: Little Endian */
     154#define DCR_BIGENDIAN  0x02  /**< BOS: Big Endian */
     155#define DCR_LAS        0x04  /**< Long Address Select */
     156#define DCR_BMS        0x08  /**< Burst Mode Select */
     157#define DCR_AR         0x10  /**< Autoinitialize Remote */
     158#define DCR_FTS        0x60  /**< Fifo Threshold Select */
     159#define DCR_2BYTES     0x00  /**< 2 bytes */
     160#define DCR_4BYTES     0x40  /**< 4 bytes */
     161#define DCR_8BYTES     0x20  /**< 8 bytes */
     162#define DCR_12BYTES    0x60  /**< 12 bytes */
     163
     164/* Bits in Transmit Configuration Register */
     165#define TCR_CRC        0x01  /**< Inhibit CRC */
     166#define TCR_ELC        0x06  /**< Encoded Loopback Control */
     167#define TCR_NORMAL     0x00  /**< ELC: Normal Operation */
     168#define TCR_INTERNAL   0x02  /**< ELC: Internal Loopback */
     169#define TCR_0EXTERNAL  0x04  /**< ELC: External Loopback LPBK=0 */
     170#define TCR_1EXTERNAL  0x06  /**< ELC: External Loopback LPBK=1 */
     171#define TCR_ATD        0x08  /**< Auto Transmit Disable */
     172#define TCR_OFST       0x10  /**< Collision Offset Enable (be nice) */
     173
     174/* Bits in Interrupt Status Register */
     175#define TSR_PTX  0x01  /**< Packet Transmitted (without error) */
     176#define TSR_DFR  0x02  /**< Transmit Deferred (reserved) */
     177#define TSR_COL  0x04  /**< Transmit Collided */
     178#define TSR_ABT  0x08  /**< Transmit Aborted */
     179#define TSR_CRS  0x10  /**< Carrier Sense Lost */
     180#define TSR_FU   0x20  /**< FIFO Underrun */
     181#define TSR_CDH  0x40  /**< CD Heartbeat */
     182#define TSR_OWC  0x80  /**< Out of Window Collision */
     183
     184/* Bits in Receive Configuration Register */
     185#define RCR_SEP  0x01  /**< Save Errored Packets */
     186#define RCR_AR   0x02  /**< Accept Runt Packets */
     187#define RCR_AB   0x04  /**< Accept Broadcast */
     188#define RCR_AM   0x08  /**< Accept Multicast */
     189#define RCR_PRO  0x10  /**< Physical Promiscuous */
     190#define RCR_MON  0x20  /**< Monitor Mode */
     191
     192/* Bits in Receive Status Register */
     193#define RSR_PRX  0x01  /**< Packet Received Intact */
     194#define RSR_CRC  0x02  /**< CRC Error */
     195#define RSR_FAE  0x04  /**< Frame Alignment Error */
     196#define RSR_FO   0x08  /**< FIFO Overrun */
     197#define RSR_MPA  0x10  /**< Missed Packet */
     198#define RSR_PHY  0x20  /**< Multicast Address Match */
     199#define RSR_DIS  0x40  /**< Receiver Disabled */
     200#define RSR_DFR  0x80  /**< In later manuals: Deferring */
     201
     202typedef struct {
     203        /* Device configuration */
     204        void *port;
     205        void *data_port;
     206        int irq;
     207        uint8_t mac[ETH_ADDR];
     208       
     209        uint8_t start_page;  /**< Ring buffer start page */
     210        uint8_t stop_page;   /**< Ring buffer stop page */
     211       
     212        /* Send queue */
     213        struct {
     214                bool dirty;    /**< Buffer contains a packet */
     215                size_t size;   /**< Packet size */
     216                uint8_t page;  /**< Starting page of the buffer */
     217        } sq;
     218        fibril_mutex_t sq_mutex;
     219        fibril_condvar_t sq_cv;
     220       
     221        /* Driver run-time variables */
     222        bool probed;
    284223        bool up;
    285         bool enabled;
    286         bool stopped;
    287         bool sending;
    288         bool send_avail;
    289 } dpeth_t;
     224       
     225        /* Device statistics */
     226        device_stats_t stats;
     227        uint64_t misses;     /**< Receive frame misses */
     228        uint64_t underruns;  /**< FIFO underruns */
     229        uint64_t overruns;   /**< FIFO overruns */
     230} ne2k_t;
     231
     232extern int ne2k_probe(ne2k_t *, void *, int);
     233extern int ne2k_up(ne2k_t *);
     234extern void ne2k_down(ne2k_t *);
     235extern void ne2k_send(ne2k_t *, packet_t *);
     236extern void ne2k_interrupt(ne2k_t *, uint8_t isr, int, device_id_t);
    290237
    291238#endif
  • uspace/srv/hw/netif/dp8390/ne2000.c

    r7ea7db31 r3c106e88  
    2828 */
    2929
    30 /*
    31  * This code is based upon the NE2000 driver for MINIX,
    32  * distributed according to a BSD-style license.
    33  *
    34  * Copyright (c) 1987, 1997, 2006 Vrije Universiteit
    35  * Copyright (c) 1992, 1994 Philip Homburg
    36  * Copyright (c) 1996 G. Falzoni
    37  *
    38  */
    39 
    40 /** @addtogroup ne2k
     30/** @addtogroup ne2000
    4131 *  @{
    4232 */
    4333
    4434/** @file
    45  *  NE1000 and NE2000 network interface initialization and probe functions implementation.
    46  */
    47 
    48 #include <stdio.h>
    49 #include <unistd.h>
    50 #include "dp8390_port.h"
     35 *  NE2000 network interface implementation.
     36 */
     37
     38#include <assert.h>
     39#include <async.h>
     40#include <ddi.h>
     41#include <errno.h>
     42#include <err.h>
     43#include <malloc.h>
     44#include <sysinfo.h>
     45#include <ipc/ipc.h>
     46#include <ipc/services.h>
     47#include <ipc/irc.h>
     48#include <net/modules.h>
     49#include <packet_client.h>
     50#include <adt/measured_strings.h>
     51#include <net/device.h>
     52#include <netif_skel.h>
     53#include <nil_interface.h>
    5154#include "dp8390.h"
    52 #include "ne2000.h"
    53 
    54 /** Number of bytes to transfer */
    55 #define N  100
    56 
    57 typedef int (*testf_t)(dpeth_t *dep, int pos, uint8_t *pat);
    58 
    59 /** Data patterns */
    60 uint8_t pat0[] = {0x00, 0x00, 0x00, 0x00};
    61 uint8_t pat1[] = {0xFF, 0xFF, 0xFF, 0xFF};
    62 uint8_t pat2[] = {0xA5, 0x5A, 0x69, 0x96};
    63 uint8_t pat3[] = {0x96, 0x69, 0x5A, 0xA5};
    64 
    65 /** Tests 8 bit NE2000 network interface.
    66  *  @param[in,out] dep The network interface structure.
    67  *  @param[in] pos The starting position.
    68  *  @param[in] pat The data pattern to be written.
    69  *  @returns True on success.
    70  *  @returns false otherwise.
    71  */
    72 static int test_8(dpeth_t *dep, int pos, uint8_t *pat);
    73 
    74 /** Tests 16 bit NE2000 network interface.
    75  *  @param[in,out] dep The network interface structure.
    76  *  @param[in] pos The starting position.
    77  *  @param[in] pat The data pattern to be written.
    78  *  @returns True on success.
    79  *  @returns false otherwise.
    80  */
    81 static int test_16(dpeth_t *dep, int pos, uint8_t *pat);
    82 
    83 int ne_probe(dpeth_t *dep)
    84 {
    85         int byte;
    86         int i;
    87         int loc1, loc2;
    88         testf_t f;
    89        
    90         dep->de_dp8390_port = dep->de_base_port + NE_DP8390;
     55
     56/** Return the device from the interrupt call.
     57 *
     58 *  @param[in] call The interrupt call.
     59 *
     60 */
     61#define IRQ_GET_DEVICE(call)  ((device_id_t) IPC_GET_IMETHOD(call))
     62
     63/** Return the ISR from the interrupt call.
     64 *
     65 * @param[in] call The interrupt call.
     66 *
     67 */
     68#define IRQ_GET_ISR(call)  ((int) IPC_GET_ARG2(call))
     69
     70static int irc_service = 0;
     71static int irc_phone = -1;
     72
     73/** DP8390 kernel interrupt command sequence.
     74 *
     75 */
     76static irq_cmd_t ne2k_cmds[] = {
     77        {
     78                .cmd = CMD_PIO_READ_8,
     79                .addr = NULL,
     80                .dstarg = 2
     81        },
     82        {
     83                .cmd = CMD_BTEST,
     84                .value = 0x7f,
     85                .srcarg = 2,
     86                .dstarg = 3,
     87        },
     88        {
     89                .cmd = CMD_PREDICATE,
     90                .value = 2,
     91                .srcarg = 3
     92        },
     93        {
     94                .cmd = CMD_PIO_WRITE_A_8,
     95                .addr = NULL,
     96                .srcarg = 3
     97        },
     98        {
     99                .cmd = CMD_ACCEPT
     100        }
     101};
     102
     103/** DP8390 kernel interrupt code.
     104 *
     105 */
     106static irq_code_t ne2k_code = {
     107        sizeof(ne2k_cmds) / sizeof(irq_cmd_t),
     108        ne2k_cmds
     109};
     110
     111/** Handle the interrupt notification.
     112 *
     113 * This is the interrupt notification function.
     114 *
     115 * @param[in] iid  Interrupt notification identifier.
     116 * @param[in] call Interrupt notification.
     117 *
     118 */
     119static void irq_handler(ipc_callid_t iid, ipc_call_t *call)
     120{
     121        device_id_t device_id = IRQ_GET_DEVICE(*call);
     122        netif_device_t *device;
     123        int nil_phone;
     124        ne2k_t *ne2k;
     125       
     126        fibril_rwlock_read_lock(&netif_globals.lock);
     127       
     128        if (find_device(device_id, &device) == EOK) {
     129                nil_phone = device->nil_phone;
     130                ne2k = (ne2k_t *) device->specific;
     131        } else
     132                ne2k = NULL;
     133       
     134        fibril_rwlock_read_unlock(&netif_globals.lock);
     135       
     136        if (ne2k != NULL)
     137                ne2k_interrupt(ne2k, IRQ_GET_ISR(*call), nil_phone, device_id);
     138}
     139
     140/** Change the network interface state.
     141 *
     142 * @param[in,out] device Network interface.
     143 * @param[in]     state  New state.
     144 *
     145 */
     146static void change_state(netif_device_t *device, device_state_t state)
     147{
     148        if (device->state != state) {
     149                device->state = state;
     150               
     151                const char *desc;
     152                switch (state) {
     153                case NETIF_ACTIVE:
     154                        desc = "active";
     155                        break;
     156                case NETIF_STOPPED:
     157                        desc = "stopped";
     158                        break;
     159                default:
     160                        desc = "unknown";
     161                }
     162               
     163                printf("%s: State changed to %s\n", NAME, desc);
     164        }
     165}
     166
     167int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
     168    ipc_call_t *answer, size_t *count)
     169{
     170        return ENOTSUP;
     171}
     172
     173int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
     174{
     175        if (!stats)
     176                return EBADMEM;
     177       
     178        netif_device_t *device;
     179        int rc = find_device(device_id, &device);
     180        if (rc != EOK)
     181                return rc;
     182       
     183        ne2k_t *ne2k = (ne2k_t *) device->specific;
     184       
     185        memcpy(stats, &ne2k->stats, sizeof(device_stats_t));
     186        return EOK;
     187}
     188
     189int netif_get_addr_message(device_id_t device_id, measured_string_t *address)
     190{
     191        if (!address)
     192                return EBADMEM;
     193       
     194        netif_device_t *device;
     195        int rc = find_device(device_id, &device);
     196        if (rc != EOK)
     197                return rc;
     198       
     199        ne2k_t *ne2k = (ne2k_t *) device->specific;
     200       
     201        address->value = ne2k->mac;
     202        address->length = ETH_ADDR;
     203        return EOK;
     204}
     205
     206int netif_probe_message(device_id_t device_id, int irq, void *io)
     207{
     208        netif_device_t *device =
     209            (netif_device_t *) malloc(sizeof(netif_device_t));
     210        if (!device)
     211                return ENOMEM;
     212       
     213        ne2k_t *ne2k = (ne2k_t *) malloc(sizeof(ne2k_t));
     214        if (!ne2k) {
     215                free(device);
     216                return ENOMEM;
     217        }
     218       
     219        void *port;
     220        int rc = pio_enable((void *) io, NE2K_IO_SIZE, &port);
     221        if (rc != EOK) {
     222                free(ne2k);
     223                free(device);
     224                return rc;
     225        }
     226       
     227        bzero(device, sizeof(netif_device_t));
     228        bzero(ne2k, sizeof(ne2k_t));
     229       
     230        device->device_id = device_id;
     231        device->nil_phone = -1;
     232        device->specific = (void *) ne2k;
     233        device->state = NETIF_STOPPED;
     234       
     235        rc = ne2k_probe(ne2k, port, irq);
     236        if (rc != EOK) {
     237                printf("%s: No ethernet card found at I/O address %p\n",
     238                    NAME, port);
     239                free(ne2k);
     240                free(device);
     241                return rc;
     242        }
     243       
     244        rc = netif_device_map_add(&netif_globals.device_map, device->device_id, device);
     245        if (rc != EOK) {
     246                free(ne2k);
     247                free(device);
     248                return rc;
     249        }
     250       
     251        printf("%s: Ethernet card at I/O address %p, IRQ %d, MAC ",
     252            NAME, port, irq);
     253       
     254        unsigned int i;
     255        for (i = 0; i < ETH_ADDR; i++)
     256                printf("%02x%c", ne2k->mac[i], i < 5 ? ':' : '\n');
     257       
     258        return EOK;
     259}
     260
     261int netif_start_message(netif_device_t *device)
     262{
     263        if (device->state != NETIF_ACTIVE) {
     264                ne2k_t *ne2k = (ne2k_t *) device->specific;
     265               
     266                ne2k_cmds[0].addr = ne2k->port + DP_ISR;
     267                ne2k_cmds[3].addr = ne2k_cmds[0].addr;
     268               
     269                int rc = ipc_register_irq(ne2k->irq, device->device_id,
     270                    device->device_id, &ne2k_code);
     271                if (rc != EOK)
     272                        return rc;
     273               
     274                rc = ne2k_up(ne2k);
     275                if (rc != EOK) {
     276                        ipc_unregister_irq(ne2k->irq, device->device_id);
     277                        return rc;
     278                }
     279               
     280                if (irc_service)
     281                        async_msg_1(irc_phone, IRC_ENABLE_INTERRUPT, ne2k->irq);
     282               
     283                change_state(device, NETIF_ACTIVE);
     284        }
     285       
     286        return device->state;
     287}
     288
     289int netif_stop_message(netif_device_t *device)
     290{
     291        if (device->state != NETIF_STOPPED) {
     292                ne2k_t *ne2k = (ne2k_t *) device->specific;
     293               
     294                ne2k_down(ne2k);
     295                ipc_unregister_irq(ne2k->irq, device->device_id);
     296                change_state(device, NETIF_STOPPED);
     297        }
     298       
     299        return EOK;
     300}
     301
     302int netif_send_message(device_id_t device_id, packet_t *packet,
     303    services_t sender)
     304{
     305        netif_device_t *device;
     306        int rc = find_device(device_id, &device);
     307        if (rc != EOK)
     308                return rc;
     309       
     310        if (device->state != NETIF_ACTIVE) {
     311                netif_pq_release(packet_get_id(packet));
     312                return EFORWARD;
     313        }
     314       
     315        ne2k_t *ne2k = (ne2k_t *) device->specific;
    91316       
    92317        /*
    93          * We probe for an ne1000 or an ne2000 by testing whether the
    94          * on board is reachable through the dp8390. Note that the
    95          * ne1000 is an 8bit card and has a memory region distict from
    96          * the 16bit ne2000
     318         * Process the packet queue
    97319         */
    98320       
    99         for (dep->de_16bit = 0; dep->de_16bit < 2; dep->de_16bit++) {
    100                 /* Reset the ethernet card */
    101                 byte= inb_ne(dep, NE_RESET);
    102                 usleep(2000);
    103                 outb_ne(dep, NE_RESET, byte);
    104                 usleep(2000);
    105                
    106                 /* Reset the dp8390 */
    107                 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
    108                 for (i = 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
    109                         ; /* Do nothing */
    110                
    111                 /* Check if the dp8390 is really there */
    112                 if ((inb_reg0(dep, DP_CR) & (CR_STP | CR_DM_ABORT)) !=
    113                     (CR_STP | CR_DM_ABORT))
    114                         return 0;
    115                
    116                 /* Disable the receiver and init TCR and DCR. */
    117                 outb_reg0(dep, DP_RCR, RCR_MON);
    118                 outb_reg0(dep, DP_TCR, TCR_NORMAL);
    119                 if (dep->de_16bit) {
    120                         outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
    121                             DCR_BMS);
    122                 } else {
    123                         outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
    124                             DCR_BMS);
     321        do {
     322                packet_t *next = pq_detach(packet);
     323                ne2k_send(ne2k, packet);
     324                netif_pq_release(packet_get_id(packet));
     325                packet = next;
     326        } while (packet);
     327       
     328        return EOK;
     329}
     330
     331int netif_initialize(void)
     332{
     333        sysarg_t apic;
     334        sysarg_t i8259;
     335       
     336        if ((sysinfo_get_value("apic", &apic) == EOK) && (apic))
     337                irc_service = SERVICE_APIC;
     338        else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259))
     339                irc_service = SERVICE_I8259;
     340       
     341        if (irc_service) {
     342                while (irc_phone < 0) {
     343                        irc_phone = ipc_connect_me_to_blocking(PHONE_NS, irc_service,
     344                            0, 0);
    125345                }
    126                
    127                 if (dep->de_16bit) {
    128                         loc1 = NE2000_START;
    129                         loc2 = NE2000_START + NE2000_SIZE - 4;
    130                         f = test_16;
    131                 } else {
    132                         loc1 = NE1000_START;
    133                         loc2 = NE1000_START + NE1000_SIZE - 4;
    134                         f = test_8;
    135                 }
    136                
    137                 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
    138                     f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
    139                     f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
    140                     f(dep, loc2, pat2) && f(dep, loc2, pat3)) {
    141                         return 1;
    142                 }
    143         }
    144        
    145         return 0;
    146 }
    147 
    148 /** Initializes the NE2000 network interface.
    149  *
    150  *  @param[in,out] dep The network interface structure.
    151  *
    152  */
    153 void ne_init(dpeth_t *dep)
    154 {
    155         int i;
    156         int word, sendq_nr;
    157        
    158         /* Setup a transfer to get the ethernet address. */
    159         if (dep->de_16bit)
    160                 outb_reg0(dep, DP_RBCR0, 6*2);
    161         else
    162                 outb_reg0(dep, DP_RBCR0, 6);
    163        
    164         outb_reg0(dep, DP_RBCR1, 0);
    165         outb_reg0(dep, DP_RSAR0, 0);
    166         outb_reg0(dep, DP_RSAR1, 0);
    167         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
    168        
    169         for (i = 0; i < 6; i++) {
    170                 if (dep->de_16bit) {
    171                         word = inw_ne(dep, NE_DATA);
    172                         dep->de_address.ea_addr[i] = word;
    173                 } else
    174                         dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
    175         }
    176        
    177         dep->de_data_port= dep->de_base_port + NE_DATA;
    178         if (dep->de_16bit) {
    179                 dep->de_ramsize = NE2000_SIZE;
    180                 dep->de_offset_page = NE2000_START / DP_PAGESIZE;
    181         } else {
    182                 dep->de_ramsize = NE1000_SIZE;
    183                 dep->de_offset_page = NE1000_START / DP_PAGESIZE;
    184         }
    185        
    186         /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
    187         sendq_nr = dep->de_ramsize / 0x2000;
    188        
    189         if (sendq_nr < 1)
    190                 sendq_nr = 1;
    191         else if (sendq_nr > SENDQ_NR)
    192                 sendq_nr = SENDQ_NR;
    193        
    194         dep->de_sendq_nr = sendq_nr;
    195         for (i = 0; i < sendq_nr; i++)
    196                 dep->de_sendq[i].sq_sendpage = dep->de_offset_page + i * SENDQ_PAGES;
    197        
    198         dep->de_startpage = dep->de_offset_page + i * SENDQ_PAGES;
    199         dep->de_stoppage = dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
    200        
    201         printf("Novell NE%d000 ethernet card at I/O address "
    202             "%#lx, memory size %#lx, irq %d\n",
    203             dep->de_16bit ? 2 : 1, dep->de_base_port, dep->de_ramsize,
    204             dep->de_irq);
    205 }
    206 
    207 static int test_8(dpeth_t *dep, int pos, uint8_t *pat)
    208 {
    209         uint8_t buf[4];
    210         int i;
    211        
    212         outb_reg0(dep, DP_ISR, 0xff);
    213        
    214         /* Setup a transfer to put the pattern. */
    215         outb_reg0(dep, DP_RBCR0, 4);
    216         outb_reg0(dep, DP_RBCR1, 0);
    217         outb_reg0(dep, DP_RSAR0, pos & 0xff);
    218         outb_reg0(dep, DP_RSAR1, pos >> 8);
    219         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
    220        
    221         for (i = 0; i < 4; i++)
    222                 outb_ne(dep, NE_DATA, pat[i]);
    223        
    224         for (i = 0; i < N; i++) {
    225                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
    226                         break;
    227         }
    228        
    229         if (i == N) {
    230                 printf("NE1000 remote DMA test failed\n");
    231                 return 0;
    232         }
    233        
    234         outb_reg0(dep, DP_RBCR0, 4);
    235         outb_reg0(dep, DP_RBCR1, 0);
    236         outb_reg0(dep, DP_RSAR0, pos & 0xff);
    237         outb_reg0(dep, DP_RSAR1, pos >> 8);
    238         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
    239        
    240         for (i = 0; i < 4; i++)
    241                 buf[i] = inb_ne(dep, NE_DATA);
    242        
    243         return (bcmp(buf, pat, 4) == 0);
    244 }
    245 
    246 static int test_16(dpeth_t *dep, int pos, uint8_t *pat)
    247 {
    248         uint8_t buf[4];
    249         int i;
    250        
    251         outb_reg0(dep, DP_ISR, 0xff);
    252        
    253         /* Setup a transfer to put the pattern. */
    254         outb_reg0(dep, DP_RBCR0, 4);
    255         outb_reg0(dep, DP_RBCR1, 0);
    256         outb_reg0(dep, DP_RSAR0, pos & 0xff);
    257         outb_reg0(dep, DP_RSAR1, pos >> 8);
    258         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
    259        
    260         for (i = 0; i < 4; i += 2)
    261                 outw_ne(dep, NE_DATA, *(uint16_t *)(pat + i));
    262        
    263         for (i = 0; i < N; i++) {
    264                 if (inb_reg0(dep, DP_ISR) &ISR_RDC)
    265                         break;
    266         }
    267        
    268         if (i == N) {
    269                 printf("NE2000 remote DMA test failed\n");
    270                 return 0;
    271         }
    272        
    273         outb_reg0(dep, DP_RBCR0, 4);
    274         outb_reg0(dep, DP_RBCR1, 0);
    275         outb_reg0(dep, DP_RSAR0, pos & 0xff);
    276         outb_reg0(dep, DP_RSAR1, pos >> 8);
    277         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
    278        
    279         for (i = 0; i < 4; i += 2)
    280                 *(uint16_t *)(buf + i) = inw_ne(dep, NE_DATA);
    281        
    282         return (bcmp(buf, pat, 4) == 0);
    283 }
    284 
    285 /** Stop the NE2000 network interface.
    286  *
    287  *  @param[in,out] dep The network interface structure.
    288  *
    289  */
    290 void ne_stop(dpeth_t *dep)
    291 {
    292         /* Reset the ethernet card */
    293         int byte = inb_ne(dep, NE_RESET);
    294         usleep(2000);
    295         outb_ne(dep, NE_RESET, byte);
     346        }
     347       
     348        async_set_interrupt_received(irq_handler);
     349       
     350        sysarg_t phonehash;
     351        return ipc_connect_to_me(PHONE_NS, SERVICE_DP8390, 0, 0, &phonehash);
     352}
     353
     354int main(int argc, char *argv[])
     355{
     356        /* Start the module */
     357        return netif_module_start();
    296358}
    297359
Note: See TracChangeset for help on using the changeset viewer.