Subversion Repositories HelenOS

Rev

Rev 4307 | Rev 4332 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4163 mejdrech 1
/*
2
 * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
3
 *
4
 * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
5
 * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
6
 * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
7
 * * Any deviations from these conditions require written permission from the copyright holder in advance
8
 *
9
 *
10
 * Disclaimer
11
 *
12
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
13
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
14
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
18
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
19
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
 *
23
 * Changes:
4192 mejdrech 24
 *  2009 Lukas Mejdrech ported to HelenOS
4163 mejdrech 25
 */
26
 
27
/** @addtogroup dp8390
28
 *  @{
29
 */
30
 
31
#include <assert.h>
32
#include <errno.h>
33
 
34
#include "../../include/byteorder.h"
35
 
4192 mejdrech 36
#include "../../structures/packet/packet.h"
37
#include "../../structures/packet/packet_client.h"
38
 
39
#include "../netif.h"
40
 
4163 mejdrech 41
#include "dp8390_drv.h"
42
#include "dp8390_port.h"
43
 
44
/*
45
 * dp8390.c
46
 *
47
 * Created: before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
48
 *
49
 * Modified Mar 10 1994 by Philip Homburg
50
 *  Become a generic dp8390 driver.
51
 *
52
 * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
53
 *  Added support for 3c503 boards.
54
 */
55
 
56
#include "local.h"
57
#include "dp8390.h"
58
 
4192 mejdrech 59
int queue_packet( dpeth_t * dep, packet_t packet );
60
static void outsb( port_t port, void * buf, size_t size );
61
static void outsw( port_t port, void * buf, size_t size );
62
 
4163 mejdrech 63
//static u16_t eth_ign_proto;
64
//static char *progname;
65
 
66
/* Configuration */
67
/*typedef struct dp_conf
68
{
69
    port_t dpc_port;
70
    int dpc_irq;
71
    phys_bytes dpc_mem;
72
    char *dpc_envvar;
73
} dp_conf_t;
74
*/
75
//dp_conf_t dp_conf[]=  /* Card addresses */
76
//{
77
    /* I/O port, IRQ,  Buffer address,  Env. var. */
78
/*  {  0x280,     3,    0xD0000,        "DPETH0"    },
79
    {  0x300,     5,    0xC8000,        "DPETH1"    },
80
    {  0x380,    10,    0xD8000,        "DPETH2"    },
81
};
82
*/
83
/* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see
84
 * the error: "array size is negative".
85
 */
86
//extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
87
 
88
/* Card inits configured out? */
89
#if !ENABLE_WDETH
90
#define wdeth_probe(dep)    (0)
91
#endif
92
#if !ENABLE_NE2000
93
#define ne_probe(dep)       (0)
94
#endif
95
#if !ENABLE_3C503
96
#define el2_probe(dep)      (0)
97
#endif
98
 
99
/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
100
 * on writes to the CR register. Additional CR_STAs do not appear to hurt
101
 * genuine dp8390s
102
 */
103
#define CR_EXTRA    CR_STA
104
 
105
//#if ENABLE_PCI
106
//_PROTOTYPE( static void pci_conf, (void)              );
107
//#endif
108
//_PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
109
//                          int vectored)   );
110
//_PROTOTYPE( static void do_vwrite_s, (message *mp, int from_int)  );
111
//_PROTOTYPE( static void do_vread, (message *mp, int vectored)     );
112
//_PROTOTYPE( static void do_vread_s, (message *mp)         );
113
//_PROTOTYPE( static void do_init, (message *mp)                );
114
//_PROTOTYPE( static void do_int, (dpeth_t *dep)                );
115
//_PROTOTYPE( static void do_getstat, (message *mp)         );
116
//_PROTOTYPE( static void do_getstat_s, (message *mp)           );
117
//_PROTOTYPE( static void do_getname, (message *mp)         );
118
//_PROTOTYPE( static void do_stop, (message *mp)                );
119
_PROTOTYPE( static void dp_init, (dpeth_t *dep)             );
120
//_PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)           );
121
_PROTOTYPE( static void dp_reinit, (dpeth_t *dep)           );
122
_PROTOTYPE( static void dp_reset, (dpeth_t *dep)            );
123
//_PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)         );
124
_PROTOTYPE( static void dp_recv, (dpeth_t *dep)             );
125
_PROTOTYPE( static void dp_send, (dpeth_t *dep)             );
126
//_PROTOTYPE( static void dp8390_stop, (void)               );
127
_PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
128
                size_t offset, size_t size, void *dst)  );
4192 mejdrech 129
_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
130
                size_t offset, size_t size, void *dst)  );
131
_PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
132
                size_t offset, size_t size, void *dst)  );
4163 mejdrech 133
_PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
134
                            int length) );
135
//_PROTOTYPE( static int dp_pkt2user_s, (dpeth_t *dep, int page,
136
//                          int length) );
4192 mejdrech 137
_PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
138
        vir_bytes offset, int nic_addr, vir_bytes count)    );
4163 mejdrech 139
//_PROTOTYPE( static void dp_user2nic_s, (dpeth_t *dep, iovec_dat_s_t *iovp, 
140
//      vir_bytes offset, int nic_addr, vir_bytes count)    );
4192 mejdrech 141
_PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
142
                iovec_dat_t *iovp, vir_bytes offset,
143
                int nic_addr, vir_bytes count)      );
4163 mejdrech 144
//_PROTOTYPE( static void dp_pio8_user2nic_s, (dpeth_t *dep,
145
//              iovec_dat_s_t *iovp, vir_bytes offset,
146
//              int nic_addr, vir_bytes count)      );
4192 mejdrech 147
_PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
148
                iovec_dat_t *iovp, vir_bytes offset,
149
                int nic_addr, vir_bytes count)      );
4163 mejdrech 150
//_PROTOTYPE( static void dp_pio16_user2nic_s, (dpeth_t *dep,
151
//              iovec_dat_s_t *iovp, vir_bytes offset,
152
//              int nic_addr, vir_bytes count)      );
153
_PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr,
154
        iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
155
//_PROTOTYPE( static void dp_nic2user_s, (dpeth_t *dep, int nic_addr, 
156
//      iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
4192 mejdrech 157
_PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
158
        iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
4163 mejdrech 159
//_PROTOTYPE( static void dp_pio8_nic2user_s, (dpeth_t *dep, int nic_addr, 
160
//      iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
4192 mejdrech 161
_PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
162
        iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
4163 mejdrech 163
//_PROTOTYPE( static void dp_pio16_nic2user_s, (dpeth_t *dep, int nic_addr, 
164
//      iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
4192 mejdrech 165
_PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)      );
4163 mejdrech 166
//_PROTOTYPE( static void dp_next_iovec_s, (iovec_dat_s_t *iovp)        );
167
_PROTOTYPE( static void conf_hw, (dpeth_t *dep)             );
168
//_PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)   );
169
_PROTOTYPE( static void map_hw_buffer, (dpeth_t *dep)           );
170
//_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)       );
171
//_PROTOTYPE( static int calc_iovec_size_s, (iovec_dat_s_t *iovp)       );
172
_PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)   );
173
//_PROTOTYPE( static void mess_reply, (message *req, message *reply)    );
4192 mejdrech 174
_PROTOTYPE( static void get_userdata, (int user_proc,
175
        vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
4163 mejdrech 176
//_PROTOTYPE( static void get_userdata_s, (int user_proc,
177
//      cp_grant_id_t grant, vir_bytes offset, vir_bytes count,
178
//      void *loc_addr) );
179
//_PROTOTYPE( static void put_userdata, (int user_proc,
180
//      vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
181
//_PROTOTYPE( static void put_userdata_s, (int user_proc,
182
//      cp_grant_id_t grant, size_t count, void *loc_addr)  );
4192 mejdrech 183
_PROTOTYPE( static void insb, (port_t port, void *buf, size_t size)             );
184
_PROTOTYPE( static void insw, (port_t port, void *buf, size_t size)             );
4163 mejdrech 185
//_PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
186
//                  vir_bytes buf, size_t size) );
187
//_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
188
//                  vir_bytes buf, size_t size) );
189
//_PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
190
//                  vir_bytes buf, size_t size) );
191
//_PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
192
//                  vir_bytes buf, size_t size) );
193
 
194
int do_probe( dpeth_t * dep ){
195
    /* This is the default, try to (re)locate the device. */
196
    conf_hw(dep);
197
    if (dep->de_mode == DEM_DISABLED)
198
    {
199
        /* Probe failed, or the device is configured off. */
200
        return EXDEV;//ENXIO;
201
    }
202
    if (dep->de_mode == DEM_ENABLED)
203
        dp_init(dep);
204
    return EOK;
205
}
206
 
207
/*===========================================================================*
4327 mejdrech 208
 *              dp8390_dump                  *
209
 *===========================================================================*/
210
void dp8390_dump( dpeth_t * dep )
211
{
212
//  dpeth_t *dep;
213
    int /*i,*/ isr;
214
 
215
//  printf("\n");
216
//  for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
217
//  {
218
#if XXX
219
        if (dep->de_mode == DEM_DISABLED)
220
            printf("dp8390 port %d is disabled\n", i);
221
        else if (dep->de_mode == DEM_SINK)
222
            printf("dp8390 port %d is in sink mode\n", i);
223
#endif
224
 
225
        if (dep->de_mode != DEM_ENABLED)
226
//          continue;
227
            return;
228
 
229
//      printf("dp8390 statistics of port %d:\n", i);
230
 
231
        printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);
232
        printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);
233
        printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);
234
 
235
        printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);
236
        printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);
237
        printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);
238
 
239
        printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);
240
        printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);
241
        printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);
242
 
243
        printf("collision  :%8ld\t", dep->de_stat.ets_collision);
244
        printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);
245
        printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);
246
 
247
        printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);
248
        printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);
249
        printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
250
 
251
        printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);
252
 
253
        isr= inb_reg0(dep, DP_ISR);
254
        printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
255
                    inb_reg0(dep, DP_ISR), dep->de_flags);
256
//  }
257
}
258
 
259
/*===========================================================================*
4163 mejdrech 260
 *              do_init                      *
261
 *===========================================================================*/
262
int do_init( dpeth_t * dep, int mode ){
263
    if (dep->de_mode == DEM_DISABLED)
264
    {
265
        // might call do_probe()
266
        return EXDEV;
267
    }
268
 
269
    if (dep->de_mode == DEM_SINK)
270
    {
271
//      strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
272
//      dep->de_address.ea_addr[5] = port;
273
//      dp_confaddr(dep);
274
        //TODO ether address?
275
//      reply_mess.m_type = DL_CONF_REPLY;
276
//      reply_mess.m3_i1 = mp->DL_PORT;
277
//      reply_mess.m3_i2 = DE_PORT_NR;
278
//      *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
279
//      mess_reply(mp, &reply_mess);
280
//      return;
281
        return EOK;
282
    }
283
    //TODO assert?
284
    assert(dep->de_mode == DEM_ENABLED);
285
    assert(dep->de_flags & DEF_ENABLED);
286
 
287
    dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
288
 
289
    if (mode & DL_PROMISC_REQ)
290
        dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
291
    if (mode & DL_MULTI_REQ)
292
        dep->de_flags |= DEF_MULTI;
293
    if (mode & DL_BROAD_REQ)
294
        dep->de_flags |= DEF_BROAD;
295
 
296
//  dep->de_client = mp->m_source;
297
    dp_reinit(dep);
298
 
299
    //TODO ether address?
300
//  reply_mess.m_type = DL_CONF_REPLY;
301
//  reply_mess.m3_i1 = mp->DL_PORT;
302
//  reply_mess.m3_i2 = DE_PORT_NR;
303
//  *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
304
 
305
//  mess_reply(mp, &reply_mess);
306
    return EOK;
307
}
308
 
309
/*===========================================================================*
310
 *              do_stop                      *
311
 *===========================================================================*/
312
void do_stop( dpeth_t * dep ){
313
    if(( dep->de_mode != DEM_SINK ) && ( dep->de_mode == DEM_ENABLED ) && ( dep->de_flags & DEF_ENABLED )){
314
        outb_reg0( dep, DP_CR, CR_STP | CR_DM_ABORT );
315
        ( dep->de_stopf )( dep );
316
 
317
        dep->de_flags = DEF_EMPTY;
318
    }
319
}
320
 
4192 mejdrech 321
int queue_packet( dpeth_t * dep, packet_t packet ){
322
    packet_t    tmp;
323
 
324
    if( dep->packet_count > 1 ){
325
        if( ! pq_add( pq_previous( dep->packet_queue ), packet, 0, 0 )){
326
            return EINVAL;
327
        }
328
    }else{
329
        tmp = pq_add( dep->packet_queue, packet, 0, 0 );
330
        if( ! tmp ) return EINVAL;
331
        dep->packet_queue = tmp;
332
    }
333
    ++ dep->packet_count;
334
    return EBUSY;
335
}
336
 
4163 mejdrech 337
/*===========================================================================*
4192 mejdrech 338
 *          based on    do_vwrite                    *
339
 *===========================================================================*/
340
int do_pwrite( dpeth_t * dep, packet_t packet, int from_int )
341
{
342
//  int port, count, size;
343
    int size;
344
    int sendq_head;
345
/*  dpeth_t *dep;
346
 
347
    port = mp->DL_PORT;
348
    count = mp->DL_COUNT;
349
    if (port < 0 || port >= DE_PORT_NR)
350
        panic("", "dp8390: illegal port", port);
351
    dep= &de_table[port];
352
    dep->de_client= mp->DL_PROC;
353
*/
354
    if (dep->de_mode == DEM_SINK)
355
    {
356
        assert(!from_int);
357
        dep->de_flags |= DEF_PACK_SEND;
358
        reply(dep, OK, FALSE);
359
//      return;
360
        return EOK;
361
    }
362
    assert(dep->de_mode == DEM_ENABLED);
363
    assert(dep->de_flags & DEF_ENABLED);
364
    if (dep->de_flags & DEF_SEND_AVAIL){
365
//      panic("", "dp8390: send already in progress", NO_NUM);
366
        return queue_packet( dep, packet );
367
    }
368
 
369
    sendq_head= dep->de_sendq_head;
370
    if (dep->de_sendq[sendq_head].sq_filled)
371
    {
372
        if (from_int)
373
            panic("", "dp8390: should not be sending\n", NO_NUM);
374
//      dep->de_sendmsg= *mp;
375
        dep->de_flags |= DEF_SEND_AVAIL;
376
        reply(dep, OK, FALSE);
377
//      return;
378
        return queue_packet( dep, packet );
379
    }
380
    assert(!(dep->de_flags & DEF_PACK_SEND));
381
 
382
/*  if (vectored)
383
    {
384
        get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
385
            (count > IOVEC_NR ? IOVEC_NR : count) *
386
            sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
387
        dep->de_write_iovec.iod_iovec_s = count;
388
        dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
389
        dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
390
 
391
        dep->de_tmp_iovec = dep->de_write_iovec;
392
        size = calc_iovec_size(&dep->de_tmp_iovec);
393
    }
394
    else
395
    {  
396
        dep->de_write_iovec.iod_iovec[0].iov_addr =
397
            (vir_bytes) mp->DL_ADDR;
398
        dep->de_write_iovec.iod_iovec[0].iov_size =
399
            mp->DL_COUNT;
400
        dep->de_write_iovec.iod_iovec_s = 1;
401
        dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
402
        dep->de_write_iovec.iod_iovec_addr = 0;
403
        size= mp->DL_COUNT;
404
    }
405
*/
406
    size = packet_get_data_length( packet );
407
    dep->de_write_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_get_data( packet );
408
    dep->de_write_iovec.iod_iovec[0].iov_size = size;
409
    dep->de_write_iovec.iod_iovec_s = 1;
410
    dep->de_write_iovec.iod_iovec_addr = NULL;
411
 
412
    if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
413
    {
414
        panic("", "dp8390: invalid packet size", size);
415
        return EINVAL;
416
    }
417
    (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
418
        dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
419
        size);
420
    dep->de_sendq[sendq_head].sq_filled= TRUE;
421
    if (dep->de_sendq_tail == sendq_head)
422
    {
423
        outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
424
        outb_reg0(dep, DP_TBCR1, size >> 8);
425
        outb_reg0(dep, DP_TBCR0, size & 0xff);
426
        outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
427
    }
428
    else
429
        dep->de_sendq[sendq_head].sq_size= size;
430
 
431
    if (++sendq_head == dep->de_sendq_nr)
432
        sendq_head= 0;
433
    assert(sendq_head < SENDQ_NR);
434
    dep->de_sendq_head= sendq_head;
435
 
436
    dep->de_flags |= DEF_PACK_SEND;
437
 
438
    /* If the interrupt handler called, don't send a reply. The reply
439
     * will be sent after all interrupts are handled.
440
     */
441
    if (from_int)
442
        return EOK;
443
    reply(dep, OK, FALSE);
444
 
445
    assert(dep->de_mode == DEM_ENABLED);
446
    assert(dep->de_flags & DEF_ENABLED);
447
    return EOK;
448
}
449
 
450
/*===========================================================================*
4163 mejdrech 451
 *              dp_init                      *
452
 *===========================================================================*/
453
void dp_init(dep)
454
dpeth_t *dep;
455
{
456
    int dp_rcr_reg;
457
    int i;//, r;
458
 
459
    /* General initialization */
460
    dep->de_flags = DEF_EMPTY;
461
    (*dep->de_initf)(dep);
462
 
463
//  dp_confaddr(dep);
464
 
465
    if (debug)
466
    {
467
        printf("%s: Ethernet address ", dep->de_name);
468
        for (i= 0; i < 6; i++)
469
            printf("%x%c", dep->de_address.ea_addr[i],
470
                            i < 5 ? ':' : '\n');
471
    }
472
 
473
    /* Map buffer */
474
    map_hw_buffer(dep);
475
 
476
    /* Initialization of the dp8390 following the mandatory procedure
477
     * in reference manual ("DP8390D/NS32490D NIC Network Interface
478
     * Controller", National Semiconductor, July 1995, Page 29).
479
     */
480
    /* Step 1: */
481
    outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
482
    /* Step 2: */
483
    if (dep->de_16bit)
484
        outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
485
    else
486
        outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
487
    /* Step 3: */
488
    outb_reg0(dep, DP_RBCR0, 0);
489
    outb_reg0(dep, DP_RBCR1, 0);
490
    /* Step 4: */
491
    dp_rcr_reg = 0;
492
    if (dep->de_flags & DEF_PROMISC)
493
        dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
494
    if (dep->de_flags & DEF_BROAD)
495
        dp_rcr_reg |= RCR_AB;
496
    if (dep->de_flags & DEF_MULTI)
497
        dp_rcr_reg |= RCR_AM;
498
    outb_reg0(dep, DP_RCR, dp_rcr_reg);
499
    /* Step 5: */
500
    outb_reg0(dep, DP_TCR, TCR_INTERNAL);
501
    /* Step 6: */
502
    outb_reg0(dep, DP_BNRY, dep->de_startpage);
503
    outb_reg0(dep, DP_PSTART, dep->de_startpage);
504
    outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
505
    /* Step 7: */
506
    outb_reg0(dep, DP_ISR, 0xFF);
507
    /* Step 8: */
508
    outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
509
        IMR_OVWE | IMR_CNTE);
510
    /* Step 9: */
511
    outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
512
 
513
    outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
514
    outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
515
    outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
516
    outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
517
    outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
518
    outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
519
 
520
    outb_reg1(dep, DP_MAR0, 0xff);
521
    outb_reg1(dep, DP_MAR1, 0xff);
522
    outb_reg1(dep, DP_MAR2, 0xff);
523
    outb_reg1(dep, DP_MAR3, 0xff);
524
    outb_reg1(dep, DP_MAR4, 0xff);
525
    outb_reg1(dep, DP_MAR5, 0xff);
526
    outb_reg1(dep, DP_MAR6, 0xff);
527
    outb_reg1(dep, DP_MAR7, 0xff);
528
 
529
    outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
530
    /* Step 10: */
531
    outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
532
    /* Step 11: */
533
    outb_reg0(dep, DP_TCR, TCR_NORMAL);
534
 
535
    inb_reg0(dep, DP_CNTR0);        /* reset counters by reading */
536
    inb_reg0(dep, DP_CNTR1);
537
    inb_reg0(dep, DP_CNTR2);
538
 
539
    /* Finish the initialization. */
540
    dep->de_flags |= DEF_ENABLED;
541
    for (i= 0; i<dep->de_sendq_nr; i++)
542
        dep->de_sendq[i].sq_filled= 0;
543
    dep->de_sendq_head= 0;
544
    dep->de_sendq_tail= 0;
4192 mejdrech 545
    if (!dep->de_prog_IO)
546
    {
547
        dep->de_user2nicf= dp_user2nic;
4163 mejdrech 548
//      dep->de_user2nicf_s= dp_user2nic_s;
549
        dep->de_nic2userf= dp_nic2user;
550
//      dep->de_nic2userf_s= dp_nic2user_s;
551
        dep->de_getblockf= dp_getblock;
4192 mejdrech 552
    }
553
    else if (dep->de_16bit)
554
    {
555
        dep->de_user2nicf= dp_pio16_user2nic;
4163 mejdrech 556
//      dep->de_user2nicf_s= dp_pio16_user2nic_s;
4192 mejdrech 557
        dep->de_nic2userf= dp_pio16_nic2user;
4163 mejdrech 558
//      dep->de_nic2userf_s= dp_pio16_nic2user_s;
4192 mejdrech 559
        dep->de_getblockf= dp_pio16_getblock;
560
    }
561
    else
562
    {
563
        dep->de_user2nicf= dp_pio8_user2nic;
4163 mejdrech 564
//      dep->de_user2nicf_s= dp_pio8_user2nic_s;
4192 mejdrech 565
        dep->de_nic2userf= dp_pio8_nic2user;
4163 mejdrech 566
//      dep->de_nic2userf_s= dp_pio8_nic2user_s;
4192 mejdrech 567
        dep->de_getblockf= dp_pio8_getblock;
568
    }
4163 mejdrech 569
 
570
    /* Set the interrupt handler and policy. Do not automatically
571
     * reenable interrupts. Return the IRQ line number on interrupts.
572
     */
573
/*  dep->de_hook = dep->de_irq;
574
    r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
575
    if (r != OK)
576
        panic("DP8390", "sys_irqsetpolicy failed", r);
577
 
578
    r= sys_irqenable(&dep->de_hook);
579
    if (r != OK)
580
    {
581
        panic("DP8390", "unable enable interrupts", r);
582
    }
583
*/
584
}
585
 
586
/*===========================================================================*
587
 *              dp_reinit                    *
588
 *===========================================================================*/
589
static void dp_reinit(dep)
590
dpeth_t *dep;
591
{
592
    int dp_rcr_reg;
593
 
594
    outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
595
 
596
    dp_rcr_reg = 0;
597
    if (dep->de_flags & DEF_PROMISC)
598
        dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
599
    if (dep->de_flags & DEF_BROAD)
600
        dp_rcr_reg |= RCR_AB;
601
    if (dep->de_flags & DEF_MULTI)
602
        dp_rcr_reg |= RCR_AM;
603
    outb_reg0(dep, DP_RCR, dp_rcr_reg);
604
}
605
 
606
/*===========================================================================*
607
 *              dp_reset                     *
608
 *===========================================================================*/
609
static void dp_reset(dep)
610
dpeth_t *dep;
611
{
612
    int i;
613
 
614
    /* Stop chip */
615
    outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
616
    outb_reg0(dep, DP_RBCR0, 0);
617
    outb_reg0(dep, DP_RBCR1, 0);
618
    for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
619
        ; /* Do nothing */
620
    outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
621
    outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
622
    outb_reg0(dep, DP_TCR, TCR_NORMAL);
623
 
624
    /* Acknowledge the ISR_RDC (remote dma) interrupt. */
625
    for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
626
        ; /* Do nothing */
627
    outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
628
 
629
    /* Reset the transmit ring. If we were transmitting a packet, we
630
     * pretend that the packet is processed. Higher layers will
631
     * retransmit if the packet wasn't actually sent.
632
     */
633
    dep->de_sendq_head= dep->de_sendq_tail= 0;
634
    for (i= 0; i<dep->de_sendq_nr; i++)
635
        dep->de_sendq[i].sq_filled= 0;
636
    dp_send(dep);
637
    dep->de_flags &= ~DEF_STOPPED;
638
}
639
 
640
/*===========================================================================*
641
 *              dp_check_ints                    *
642
 *===========================================================================*/
4327 mejdrech 643
void dp_check_ints(dep, isr)
4163 mejdrech 644
dpeth_t *dep;
4327 mejdrech 645
int isr;
4163 mejdrech 646
{
4327 mejdrech 647
    int /*isr,*/ tsr;
4163 mejdrech 648
    int size, sendq_tail;
649
 
650
    if (!(dep->de_flags & DEF_ENABLED))
651
        panic("", "dp8390: got premature interrupt", NO_NUM);
652
 
653
    for(;;)
654
    {
4327 mejdrech 655
//      isr = inb_reg0(dep, DP_ISR);
4163 mejdrech 656
        if (!isr)
657
            break;
658
        outb_reg0(dep, DP_ISR, isr);
659
        if (isr & (ISR_PTX|ISR_TXE))
660
        {
661
            if (isr & ISR_TXE)
662
            {
663
#if DEBUG
664
 { printf("%s: got send Error\n", dep->de_name); }
665
#endif
666
                dep->de_stat.ets_sendErr++;
667
            }
668
            else
669
            {
670
                tsr = inb_reg0(dep, DP_TSR);
671
 
672
                if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
673
#if 0   /* Reserved in later manuals, should be ignored */
674
                if (!(tsr & TSR_DFR))
675
                {
676
                    /* In most (all?) implementations of
677
                     * the dp8390, this bit is set
678
                     * when the packet is not deferred
679
                     */
680
                    dep->de_stat.ets_transDef++;
681
                }
682
#endif
683
                if (tsr & TSR_COL) dep->de_stat.ets_collision++;
684
                if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
685
                if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
686
                if (tsr & TSR_FU
687
                    && ++dep->de_stat.ets_fifoUnder <= 10)
688
                {
689
                    printf("%s: fifo underrun\n",
690
                        dep->de_name);
691
                }
692
                if (tsr & TSR_CDH
693
                    && ++dep->de_stat.ets_CDheartbeat <= 10)
694
                {
695
                    printf("%s: CD heart beat failure\n",
696
                        dep->de_name);
697
                }
698
                if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
699
            }
700
            sendq_tail= dep->de_sendq_tail;
701
 
702
            if (!(dep->de_sendq[sendq_tail].sq_filled))
703
            {
704
                /* Software bug? */
705
                assert(!debug);
706
 
707
                /* Or hardware bug? */
708
                printf(
709
                "%s: transmit interrupt, but not sending\n",
710
                    dep->de_name);
711
                continue;
712
            }
713
            dep->de_sendq[sendq_tail].sq_filled= 0;
714
            if (++sendq_tail == dep->de_sendq_nr)
715
                sendq_tail= 0;
716
            dep->de_sendq_tail= sendq_tail;
717
            if (dep->de_sendq[sendq_tail].sq_filled)
718
            {
719
                size= dep->de_sendq[sendq_tail].sq_size;
720
                outb_reg0(dep, DP_TPSR,
721
                    dep->de_sendq[sendq_tail].sq_sendpage);
722
                outb_reg0(dep, DP_TBCR1, size >> 8);
723
                outb_reg0(dep, DP_TBCR0, size & 0xff);
724
                outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
725
            }
726
            if (dep->de_flags & DEF_SEND_AVAIL)
727
                dp_send(dep);
728
        }
729
 
730
        if (isr & ISR_PRX)
731
        {
732
            /* Only call dp_recv if there is a read request */
733
            if (dep->de_flags & DEF_READING)
734
                dp_recv(dep);
735
        }
736
 
737
        if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
738
        if (isr & ISR_CNT)
739
        {
740
            dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
741
            dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
742
            dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
743
        }
744
        if (isr & ISR_OVW)
745
        {
746
            dep->de_stat.ets_OVW++;
747
#if 0
748
            { printW(); printf(
749
                "%s: got overwrite warning\n", dep->de_name); }
750
#endif
751
            if (dep->de_flags & DEF_READING)
752
            {
753
                printf(
754
"dp_check_ints: strange: overwrite warning and pending read request\n");
755
                dp_recv(dep);
756
            }
757
        }
758
        if (isr & ISR_RDC)
759
        {
760
            /* Nothing to do */
761
        }
762
        if (isr & ISR_RST)
763
        {
764
            /* this means we got an interrupt but the ethernet
765
             * chip is shutdown. We set the flag DEF_STOPPED,
766
             * and continue processing arrived packets. When the
767
             * receive buffer is empty, we reset the dp8390.
768
             */
769
#if 0
770
             { printW(); printf(
771
                "%s: NIC stopped\n", dep->de_name); }
772
#endif
773
            dep->de_flags |= DEF_STOPPED;
774
            break;
775
        }
4327 mejdrech 776
        isr = inb_reg0(dep, DP_ISR);
4163 mejdrech 777
    }
778
    if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
779
                        (DEF_READING|DEF_STOPPED))
780
    {
781
        /* The chip is stopped, and all arrived packets are
782
         * delivered.
783
         */
784
        dp_reset(dep);
785
    }
786
}
787
 
788
/*===========================================================================*
789
 *              dp_recv                      *
790
 *===========================================================================*/
791
static void dp_recv(dep)
792
dpeth_t *dep;
793
{
794
    dp_rcvhdr_t header;
795
    unsigned pageno, curr, next;
796
    vir_bytes length;
797
    int packet_processed, r;
798
    u16_t eth_type;
799
 
800
    packet_processed = FALSE;
801
    pageno = inb_reg0(dep, DP_BNRY) + 1;
802
    if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
803
 
804
    do
805
    {
806
        outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
807
        curr = inb_reg1(dep, DP_CURR);
808
        outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
809
 
810
        if (curr == pageno) break;
811
 
812
        (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
813
            &header);
814
        (dep->de_getblockf)(dep, pageno, sizeof(header) +
815
            2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
816
 
817
        length = (header.dr_rbcl | (header.dr_rbch << 8)) -
818
            sizeof(dp_rcvhdr_t);
819
        next = header.dr_next;
820
        if (length < ETH_MIN_PACK_SIZE ||
821
            length > ETH_MAX_PACK_SIZE_TAGGED)
822
        {
823
            printf("%s: packet with strange length arrived: %d\n",
824
                dep->de_name, (int) length);
825
            next= curr;
826
        }
827
        else if (next < dep->de_startpage || next >= dep->de_stoppage)
828
        {
829
            printf("%s: strange next page\n", dep->de_name);
830
            next= curr;
831
        }
832
/*      else if (eth_type == eth_ign_proto)
833
        {
834
*/          /* Hack: ignore packets of a given protocol, useful
835
             * if you share a net with 80 computers sending
836
             * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
837
             */
838
/*          static int first= 1;
839
            if (first)
840
            {
841
                first= 0;
842
                printf("%s: dropping proto 0x%04x packets\n",
843
                    dep->de_name,
844
                    ntohs(eth_ign_proto));
845
            }
846
            dep->de_stat.ets_packetR++;
847
        }
848
*/      else if (header.dr_status & RSR_FO)
849
        {
850
            /* This is very serious, so we issue a warning and
851
             * reset the buffers */
852
            printf("%s: fifo overrun, resetting receive buffer\n",
853
                dep->de_name);
854
            dep->de_stat.ets_fifoOver++;
855
            next = curr;
856
        }
857
        else if ((header.dr_status & RSR_PRX) &&
858
                       (dep->de_flags & DEF_ENABLED))
859
        {
860
//          if (dep->de_safecopy_read)
861
//              r = dp_pkt2user_s(dep, pageno, length);
862
//          else
863
                r = dp_pkt2user(dep, pageno, length);
864
            if (r != OK)
865
                return;
866
 
867
            packet_processed = TRUE;
868
            dep->de_stat.ets_packetR++;
869
        }
870
        if (next == dep->de_startpage)
871
            outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
872
        else
873
            outb_reg0(dep, DP_BNRY, next - 1);
874
 
875
        pageno = next;
876
    }
877
    while (!packet_processed);
878
}
879
 
880
/*===========================================================================*
881
 *              dp_send                      *
882
 *===========================================================================*/
883
static void dp_send(dep)
884
dpeth_t *dep;
885
{
4192 mejdrech 886
    packet_t packet;
887
 
888
    if (!(dep->de_flags & DEF_SEND_AVAIL))
4163 mejdrech 889
        return;
890
 
891
    dep->de_flags &= ~DEF_SEND_AVAIL;
4192 mejdrech 892
    while( dep->packet_queue ){
893
        packet = dep->packet_queue;
894
        dep->packet_queue = pq_detach( packet );
895
        do_pwrite( dep, packet, TRUE );
896
        netif_pq_release( packet_get_id( packet ));
897
        -- dep->packet_count;
898
    }
899
/*  switch(dep->de_sendmsg.m_type)
4163 mejdrech 900
    {
901
    case DL_WRITE:  do_vwrite(&dep->de_sendmsg, TRUE, FALSE);   break;
902
    case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE);    break;
903
    case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, TRUE);  break;
904
    default:
905
        panic("", "dp8390: wrong type", dep->de_sendmsg.m_type);
906
        break;
907
    }
908
*/
909
}
910
 
911
/*===========================================================================*
912
 *              dp_getblock                  *
913
 *===========================================================================*/
914
static void dp_getblock(dep, page, offset, size, dst)
915
dpeth_t *dep;
916
int page;
917
size_t offset;
918
size_t size;
919
void *dst;
920
{
921
//  int r;
922
 
923
    offset = page * DP_PAGESIZE + offset;
924
 
925
    memcpy(dst, dep->de_locmem + offset, size);
926
}
927
 
928
/*===========================================================================*
4192 mejdrech 929
 *              dp_pio8_getblock                 *
930
 *===========================================================================*/
931
static void dp_pio8_getblock(dep, page, offset, size, dst)
932
dpeth_t *dep;
933
int page;
934
size_t offset;
935
size_t size;
936
void *dst;
937
{
938
    offset = page * DP_PAGESIZE + offset;
939
    outb_reg0(dep, DP_RBCR0, size & 0xFF);
940
    outb_reg0(dep, DP_RBCR1, size >> 8);
941
    outb_reg0(dep, DP_RSAR0, offset & 0xFF);
942
    outb_reg0(dep, DP_RSAR1, offset >> 8);
943
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
944
 
945
    insb(dep->de_data_port, dst, size);
946
}
947
 
948
/*===========================================================================*
949
 *              dp_pio16_getblock                *
950
 *===========================================================================*/
951
static void dp_pio16_getblock(dep, page, offset, size, dst)
952
dpeth_t *dep;
953
int page;
954
size_t offset;
955
size_t size;
956
void *dst;
957
{
958
    offset = page * DP_PAGESIZE + offset;
959
    outb_reg0(dep, DP_RBCR0, size & 0xFF);
960
    outb_reg0(dep, DP_RBCR1, size >> 8);
961
    outb_reg0(dep, DP_RSAR0, offset & 0xFF);
962
    outb_reg0(dep, DP_RSAR1, offset >> 8);
963
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
964
 
965
    assert (!(size & 1));
966
    insw(dep->de_data_port, dst, size);
967
}
968
 
969
/*===========================================================================*
4163 mejdrech 970
 *              dp_pkt2user                  *
971
 *===========================================================================*/
972
static int dp_pkt2user(dep, page, length)
973
dpeth_t *dep;
974
int page, length;
975
{
976
    int last, count;
4192 mejdrech 977
    packet_t    packet;
4261 mejdrech 978
    packet_t    queue;
4163 mejdrech 979
 
980
    if (!(dep->de_flags & DEF_READING))
981
        return EGENERIC;
982
 
4192 mejdrech 983
    packet = netif_packet_get_1( length );
984
    if( ! packet ) return ENOMEM;
985
    dep->de_read_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_suffix( packet, length );
986
    dep->de_read_iovec.iod_iovec[0].iov_size = length;
987
    dep->de_read_iovec.iod_iovec_s = 1;
988
    dep->de_read_iovec.iod_iovec_addr = NULL;
989
 
4163 mejdrech 990
    last = page + (length - 1) / DP_PAGESIZE;
991
    if (last >= dep->de_stoppage)
992
    {
993
        count = (dep->de_stoppage - page) * DP_PAGESIZE -
994
            sizeof(dp_rcvhdr_t);
995
 
996
        /* Save read_iovec since we need it twice. */
997
        dep->de_tmp_iovec = dep->de_read_iovec;
998
        (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
999
            sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
1000
        (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
1001
                &dep->de_read_iovec, count, length - count);
1002
    }
1003
    else
1004
    {
1005
        (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
1006
            sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
1007
    }
1008
 
1009
    dep->de_read_s = length;
1010
    dep->de_flags |= DEF_PACK_RECV;
1011
    dep->de_flags &= ~DEF_READING;
1012
 
4261 mejdrech 1013
    queue = pq_add( dep->received_queue, packet, 0, 0 );
1014
    if( queue ){
1015
        dep->received_queue = queue;
1016
    }else{
4192 mejdrech 1017
        netif_pq_release( packet_get_id( packet ));
1018
    }
4163 mejdrech 1019
    return OK;
1020
}
1021
 
1022
/*===========================================================================*
4192 mejdrech 1023
 *              dp_user2nic                  *
1024
 *===========================================================================*/
1025
static void dp_user2nic(dep, iovp, offset, nic_addr, count)
1026
dpeth_t *dep;
1027
iovec_dat_t *iovp;
1028
vir_bytes offset;
1029
int nic_addr;
1030
vir_bytes count;
1031
{
1032
    vir_bytes vir_hw;//, vir_user;
1033
    int bytes, i, r;
1034
 
1035
    vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
1036
 
1037
    i= 0;
1038
    while (count > 0)
1039
    {
1040
        if (i >= IOVEC_NR)
1041
        {
1042
            dp_next_iovec(iovp);
1043
            i= 0;
1044
            continue;
1045
        }
1046
        assert(i < iovp->iod_iovec_s);
1047
        if (offset >= iovp->iod_iovec[i].iov_size)
1048
        {
1049
            offset -= iovp->iod_iovec[i].iov_size;
1050
            i++;
1051
            continue;
1052
        }
1053
        bytes = iovp->iod_iovec[i].iov_size - offset;
1054
        if (bytes > count)
1055
            bytes = count;
1056
 
1057
        r= sys_vircopy(iovp->iod_proc_nr, D,
1058
            iovp->iod_iovec[i].iov_addr + offset,
1059
            SELF, D, vir_hw, bytes);
1060
        if (r != OK)
1061
            panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
1062
 
1063
        count -= bytes;
1064
        vir_hw += bytes;
1065
        offset += bytes;
1066
    }
1067
    assert(count == 0);
1068
}
1069
 
1070
/*===========================================================================*
1071
 *              dp_pio8_user2nic                 *
1072
 *===========================================================================*/
1073
static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
1074
dpeth_t *dep;
1075
iovec_dat_t *iovp;
1076
vir_bytes offset;
1077
int nic_addr;
1078
vir_bytes count;
1079
{
1080
//  phys_bytes phys_user;
1081
    int bytes, i;
1082
 
1083
    outb_reg0(dep, DP_ISR, ISR_RDC);
1084
 
1085
    outb_reg0(dep, DP_RBCR0, count & 0xFF);
1086
    outb_reg0(dep, DP_RBCR1, count >> 8);
1087
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1088
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1089
    outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1090
 
1091
    i= 0;
1092
    while (count > 0)
1093
    {
1094
        if (i >= IOVEC_NR)
1095
        {
1096
            dp_next_iovec(iovp);
1097
            i= 0;
1098
            continue;
1099
        }
1100
        assert(i < iovp->iod_iovec_s);
1101
        if (offset >= iovp->iod_iovec[i].iov_size)
1102
        {
1103
            offset -= iovp->iod_iovec[i].iov_size;
1104
            i++;
1105
            continue;
1106
        }
1107
        bytes = iovp->iod_iovec[i].iov_size - offset;
1108
        if (bytes > count)
1109
            bytes = count;
1110
 
1111
        do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
1112
            iovp->iod_iovec[i].iov_addr + offset, bytes);
1113
        count -= bytes;
1114
        offset += bytes;
1115
    }
1116
    assert(count == 0);
1117
 
1118
    for (i= 0; i<100; i++)
1119
    {
1120
        if (inb_reg0(dep, DP_ISR) & ISR_RDC)
1121
            break;
1122
    }
1123
    if (i == 100)
1124
    {
1125
        panic("", "dp8390: remote dma failed to complete", NO_NUM);
1126
    }
1127
}
1128
 
1129
/*===========================================================================*
1130
 *              dp_pio16_user2nic                *
1131
 *===========================================================================*/
1132
static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
1133
dpeth_t *dep;
1134
iovec_dat_t *iovp;
1135
vir_bytes offset;
1136
int nic_addr;
1137
vir_bytes count;
1138
{
1139
    vir_bytes vir_user;
1140
    vir_bytes ecount;
1141
    int i, r, bytes, user_proc;
1142
    u8_t two_bytes[2];
1143
    int odd_byte;
1144
 
1145
    ecount= (count+1) & ~1;
1146
    odd_byte= 0;
1147
 
1148
    outb_reg0(dep, DP_ISR, ISR_RDC);
1149
    outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
1150
    outb_reg0(dep, DP_RBCR1, ecount >> 8);
1151
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1152
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1153
    outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1154
 
1155
    i= 0;
1156
    while (count > 0)
1157
    {
1158
        if (i >= IOVEC_NR)
1159
        {
1160
            dp_next_iovec(iovp);
1161
            i= 0;
1162
            continue;
1163
        }
1164
        assert(i < iovp->iod_iovec_s);
1165
        if (offset >= iovp->iod_iovec[i].iov_size)
1166
        {
1167
            offset -= iovp->iod_iovec[i].iov_size;
1168
            i++;
1169
            continue;
1170
        }
1171
        bytes = iovp->iod_iovec[i].iov_size - offset;
1172
        if (bytes > count)
1173
            bytes = count;
1174
 
1175
        user_proc= iovp->iod_proc_nr;
1176
        vir_user= iovp->iod_iovec[i].iov_addr + offset;
1177
        if (odd_byte)
1178
        {
1179
            r= sys_vircopy(user_proc, D, vir_user,
1180
                SELF, D, (vir_bytes)&two_bytes[1], 1);
1181
            if (r != OK)
1182
            {
1183
                panic("DP8390",
1184
                    "dp_pio16_user2nic: sys_vircopy failed",
1185
                    r);
1186
            }
1187
            outw(dep->de_data_port, *(u16_t *)two_bytes);
1188
            count--;
1189
            offset++;
1190
            bytes--;
1191
            vir_user++;
1192
            odd_byte= 0;
1193
            if (!bytes)
1194
                continue;
1195
        }
1196
        ecount= bytes & ~1;
1197
        if (ecount != 0)
1198
        {
1199
            do_vir_outsw(dep->de_data_port, user_proc, vir_user,
1200
                ecount);
1201
            count -= ecount;
1202
            offset += ecount;
1203
            bytes -= ecount;
1204
            vir_user += ecount;
1205
        }
1206
        if (bytes)
1207
        {
1208
            assert(bytes == 1);
1209
            r= sys_vircopy(user_proc, D, vir_user,
1210
                SELF, D, (vir_bytes)&two_bytes[0], 1);
1211
            if (r != OK)
1212
            {
1213
                panic("DP8390",
1214
                    "dp_pio16_user2nic: sys_vircopy failed",
1215
                    r);
1216
            }
1217
            count--;
1218
            offset++;
1219
            bytes--;
1220
            vir_user++;
1221
            odd_byte= 1;
1222
        }
1223
    }
1224
    assert(count == 0);
1225
 
1226
    if (odd_byte)
1227
        outw(dep->de_data_port, *(u16_t *)two_bytes);
1228
 
1229
    for (i= 0; i<100; i++)
1230
    {
1231
        if (inb_reg0(dep, DP_ISR) & ISR_RDC)
1232
            break;
1233
    }
1234
    if (i == 100)
1235
    {
1236
        panic("", "dp8390: remote dma failed to complete", NO_NUM);
1237
    }
1238
}
1239
 
1240
/*===========================================================================*
4163 mejdrech 1241
 *              dp_nic2user                  *
1242
 *===========================================================================*/
1243
static void dp_nic2user(dep, nic_addr, iovp, offset, count)
1244
dpeth_t *dep;
1245
int nic_addr;
1246
iovec_dat_t *iovp;
1247
vir_bytes offset;
1248
vir_bytes count;
1249
{
4192 mejdrech 1250
    vir_bytes vir_hw;//, vir_user;
4163 mejdrech 1251
    int bytes, i, r;
1252
 
1253
    vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
1254
 
1255
    i= 0;
1256
    while (count > 0)
1257
    {
1258
        if (i >= IOVEC_NR)
1259
        {
1260
            dp_next_iovec(iovp);
1261
            i= 0;
1262
            continue;
1263
        }
1264
        assert(i < iovp->iod_iovec_s);
1265
        if (offset >= iovp->iod_iovec[i].iov_size)
1266
        {
1267
            offset -= iovp->iod_iovec[i].iov_size;
1268
            i++;
1269
            continue;
1270
        }
1271
        bytes = iovp->iod_iovec[i].iov_size - offset;
1272
        if (bytes > count)
1273
            bytes = count;
1274
 
1275
        r= sys_vircopy(SELF, D, vir_hw,
1276
            iovp->iod_proc_nr, D,
1277
            iovp->iod_iovec[i].iov_addr + offset, bytes);
1278
        if (r != OK)
1279
            panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
1280
 
1281
        count -= bytes;
1282
        vir_hw += bytes;
1283
        offset += bytes;
1284
    }
1285
    assert(count == 0);
1286
}
1287
 
1288
/*===========================================================================*
4192 mejdrech 1289
 *              dp_pio8_nic2user                 *
1290
 *===========================================================================*/
1291
static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
1292
dpeth_t *dep;
1293
int nic_addr;
1294
iovec_dat_t *iovp;
1295
vir_bytes offset;
1296
vir_bytes count;
1297
{
1298
//  phys_bytes phys_user;
1299
    int bytes, i;
1300
 
1301
    outb_reg0(dep, DP_RBCR0, count & 0xFF);
1302
    outb_reg0(dep, DP_RBCR1, count >> 8);
1303
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1304
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1305
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1306
 
1307
    i= 0;
1308
    while (count > 0)
1309
    {
1310
        if (i >= IOVEC_NR)
1311
        {
1312
            dp_next_iovec(iovp);
1313
            i= 0;
1314
            continue;
1315
        }
1316
        assert(i < iovp->iod_iovec_s);
1317
        if (offset >= iovp->iod_iovec[i].iov_size)
1318
        {
1319
            offset -= iovp->iod_iovec[i].iov_size;
1320
            i++;
1321
            continue;
1322
        }
1323
        bytes = iovp->iod_iovec[i].iov_size - offset;
1324
        if (bytes > count)
1325
            bytes = count;
1326
 
1327
        do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
1328
            iovp->iod_iovec[i].iov_addr + offset, bytes);
1329
        count -= bytes;
1330
        offset += bytes;
1331
    }
1332
    assert(count == 0);
1333
}
1334
 
1335
/*===========================================================================*
1336
 *              dp_pio16_nic2user                *
1337
 *===========================================================================*/
1338
static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
1339
dpeth_t *dep;
1340
int nic_addr;
1341
iovec_dat_t *iovp;
1342
vir_bytes offset;
1343
vir_bytes count;
1344
{
1345
    vir_bytes vir_user;
1346
    vir_bytes ecount;
1347
    int i, r, bytes, user_proc;
1348
    u8_t two_bytes[2];
1349
    int odd_byte;
1350
 
1351
    ecount= (count+1) & ~1;
1352
    odd_byte= 0;
1353
 
1354
    outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
1355
    outb_reg0(dep, DP_RBCR1, ecount >> 8);
1356
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1357
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1358
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1359
 
1360
    i= 0;
1361
    while (count > 0)
1362
    {
1363
        if (i >= IOVEC_NR)
1364
        {
1365
            dp_next_iovec(iovp);
1366
            i= 0;
1367
            continue;
1368
        }
1369
        assert(i < iovp->iod_iovec_s);
1370
        if (offset >= iovp->iod_iovec[i].iov_size)
1371
        {
1372
            offset -= iovp->iod_iovec[i].iov_size;
1373
            i++;
1374
            continue;
1375
        }
1376
        bytes = iovp->iod_iovec[i].iov_size - offset;
1377
        if (bytes > count)
1378
            bytes = count;
1379
 
1380
        user_proc= iovp->iod_proc_nr;
1381
        vir_user= iovp->iod_iovec[i].iov_addr + offset;
1382
        if (odd_byte)
1383
        {
1384
            r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
1385
                user_proc, D, vir_user,  1);
1386
            if (r != OK)
1387
            {
1388
                panic("DP8390",
1389
                    "dp_pio16_nic2user: sys_vircopy failed",
1390
                    r);
1391
            }
1392
            count--;
1393
            offset++;
1394
            bytes--;
1395
            vir_user++;
1396
            odd_byte= 0;
1397
            if (!bytes)
1398
                continue;
1399
        }
1400
        ecount= bytes & ~1;
1401
        if (ecount != 0)
1402
        {
1403
            do_vir_insw(dep->de_data_port, user_proc, vir_user,
1404
                ecount);
1405
            count -= ecount;
1406
            offset += ecount;
1407
            bytes -= ecount;
1408
            vir_user += ecount;
1409
        }
1410
        if (bytes)
1411
        {
1412
            assert(bytes == 1);
1413
            *(u16_t *)two_bytes= inw(dep->de_data_port);
1414
            r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
1415
                user_proc, D, vir_user,  1);
1416
            if (r != OK)
1417
            {
1418
                panic("DP8390",
1419
                    "dp_pio16_nic2user: sys_vircopy failed",
1420
                    r);
1421
            }
1422
            count--;
1423
            offset++;
1424
            bytes--;
1425
            vir_user++;
1426
            odd_byte= 1;
1427
        }
1428
    }
1429
    assert(count == 0);
1430
}
1431
 
1432
/*===========================================================================*
1433
 *              dp_next_iovec                    *
1434
 *===========================================================================*/
1435
static void dp_next_iovec(iovp)
1436
iovec_dat_t *iovp;
1437
{
1438
    assert(iovp->iod_iovec_s > IOVEC_NR);
1439
 
1440
    iovp->iod_iovec_s -= IOVEC_NR;
1441
 
1442
    iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
1443
 
1444
    get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
1445
        (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
1446
        sizeof(iovec_t), iovp->iod_iovec);
1447
}
1448
 
1449
/*===========================================================================*
4163 mejdrech 1450
 *              conf_hw                      *
1451
 *===========================================================================*/
1452
static void conf_hw(dep)
1453
dpeth_t *dep;
1454
{
1455
//  static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0    /* ,... */ };
1456
 
1457
//  int ifnr;
1458
//  dp_conf_t *dcp;
1459
 
1460
//  dep->de_mode= DEM_DISABLED; /* Superfluous */
1461
//  ifnr= dep-de_table;
1462
 
1463
//  dcp= &dp_conf[ifnr];
1464
//  update_conf(dep, dcp);
1465
//  if (dep->de_mode != DEM_ENABLED)
1466
//      return;
1467
    if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
1468
    {
1469
        printf("%s: No ethernet card found at 0x%x\n",
1470
            dep->de_name, dep->de_base_port);
1471
        dep->de_mode= DEM_DISABLED;
1472
        return;
1473
    }
1474
 
1475
/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
1476
 
1477
    dep->de_mode = DEM_ENABLED;
1478
 
1479
    dep->de_flags = DEF_EMPTY;
1480
//  dep->de_stat = empty_stat;
1481
}
1482
 
1483
/*===========================================================================*
1484
 *              map_hw_buffer                    *
1485
 *===========================================================================*/
1486
static void map_hw_buffer(dep)
1487
dpeth_t *dep;
1488
{
1489
//  int r;
1490
//  size_t o, size;
1491
//  char *buf, *abuf;
1492
 
1493
    if (dep->de_prog_IO)
1494
    {
4192 mejdrech 1495
#if 0
4163 mejdrech 1496
        if(debug){
1497
            printf(
1498
            "map_hw_buffer: programmed I/O, no need to map buffer\n");
1499
        }
4192 mejdrech 1500
#endif
4163 mejdrech 1501
        dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */
1502
        return;
4192 mejdrech 1503
    }else{
4307 mejdrech 1504
        printf( "map_hw_buffer: no buffer!\n" );
4163 mejdrech 1505
    }
1506
 
1507
//  size = dep->de_ramsize + PAGE_SIZE; /* Add PAGE_SIZE for
1508
//                       * alignment
1509
//                       */
1510
//  buf= malloc(size);
1511
//  if (buf == NULL)
1512
//      panic(__FILE__, "map_hw_buffer: cannot malloc size", size);
1513
//  o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
1514
//  abuf= buf + o;
1515
//  printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf);
1516
 
1517
//  r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf,
1518
//          dep->de_ramsize, (phys_bytes)dep->de_linmem);
1519
//  if (r != OK)
1520
//      panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r);
1521
//  dep->de_locmem = abuf;
1522
}
1523
 
1524
/*===========================================================================*
1525
 *              reply                        *
1526
 *===========================================================================*/
1527
static void reply(dep, err, may_block)
1528
dpeth_t *dep;
1529
int err;
1530
int may_block;
1531
{
1532
/*  message reply;
1533
    int status;
1534
    int r;
1535
 
1536
    status = 0;
1537
    if (dep->de_flags & DEF_PACK_SEND)
1538
        status |= DL_PACK_SEND;
1539
    if (dep->de_flags & DEF_PACK_RECV)
1540
        status |= DL_PACK_RECV;
1541
 
1542
    reply.m_type = DL_TASK_REPLY;
1543
    reply.DL_PORT = dep - de_table;
1544
    reply.DL_PROC = dep->de_client;
1545
    reply.DL_STAT = status | ((u32_t) err << 16);
1546
    reply.DL_COUNT = dep->de_read_s;
1547
    reply.DL_CLCK = 0;  *//* Don't know */
1548
/*  r= send(dep->de_client, &reply);
1549
 
1550
    if (r == ELOCKED && may_block)
1551
    {
1552
#if 0
1553
        printf("send locked\n");
1554
#endif
1555
        return;
1556
    }
1557
 
1558
    if (r < 0)
1559
        panic("", "dp8390: send failed:", r);
1560
 
4327 mejdrech 1561
*/  dep->de_read_s = 0;
1562
    dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
4163 mejdrech 1563
}
1564
 
4192 mejdrech 1565
/*===========================================================================*
1566
 *              get_userdata                     *
1567
 *===========================================================================*/
1568
static void get_userdata(user_proc, user_addr, count, loc_addr)
1569
int user_proc;
1570
vir_bytes user_addr;
1571
vir_bytes count;
1572
void *loc_addr;
1573
{
1574
    int r;
1575
 
1576
    r= sys_vircopy(user_proc, D, user_addr,
1577
        SELF, D, (vir_bytes)loc_addr, count);
1578
    if (r != OK)
1579
        panic("DP8390", "get_userdata: sys_vircopy failed", r);
1580
}
1581
 
1582
static void insb(port_t port, void *buf, size_t size)
1583
{
4243 mejdrech 1584
    size_t i;
4192 mejdrech 1585
 
1586
    for( i = 0; i < size; ++ i ){
1587
        *(( uint8_t * )( buf + i )) = inb( port );
1588
    }
1589
}
1590
 
1591
static void insw(port_t port, void *buf, size_t size)
1592
{
4243 mejdrech 1593
    size_t i;
4192 mejdrech 1594
 
1595
    for( i = 0; i < size; i += 2 ){
1596
        *(( uint16_t * )( buf + i )) = inw( port );
1597
    }
1598
}
1599
 
1600
static void outsb(port_t port, void *buf, size_t size)
1601
{
4243 mejdrech 1602
    size_t i;
4192 mejdrech 1603
 
1604
    for( i = 0; i < size; ++ i ){
1605
        outb( port, *(( uint8_t * )( buf + i )));
1606
    }
1607
}
1608
 
1609
static void outsw(port_t port, void *buf, size_t size)
1610
{
4243 mejdrech 1611
    size_t i;
4192 mejdrech 1612
 
1613
    for( i = 0; i < size; i += 2 ){
1614
        outw( port, *(( uint16_t * )( buf + i )));
1615
    }
1616
}
1617
 
4163 mejdrech 1618
/*
1619
 * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
1620
 */
1621
 
1622
/** @}
1623
 */