Subversion Repositories HelenOS

Rev

Rev 4351 | Rev 4723 | 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
//      reply_mess.m_type = DL_CONF_REPLY;
275
//      reply_mess.m3_i1 = mp->DL_PORT;
276
//      reply_mess.m3_i2 = DE_PORT_NR;
277
//      *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
278
//      mess_reply(mp, &reply_mess);
279
//      return;
280
        return EOK;
281
    }
282
    assert(dep->de_mode == DEM_ENABLED);
283
    assert(dep->de_flags & DEF_ENABLED);
284
 
285
    dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
286
 
287
    if (mode & DL_PROMISC_REQ)
288
        dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
289
    if (mode & DL_MULTI_REQ)
290
        dep->de_flags |= DEF_MULTI;
291
    if (mode & DL_BROAD_REQ)
292
        dep->de_flags |= DEF_BROAD;
293
 
294
//  dep->de_client = mp->m_source;
295
    dp_reinit(dep);
296
 
297
//  reply_mess.m_type = DL_CONF_REPLY;
298
//  reply_mess.m3_i1 = mp->DL_PORT;
299
//  reply_mess.m3_i2 = DE_PORT_NR;
300
//  *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
301
 
302
//  mess_reply(mp, &reply_mess);
303
    return EOK;
304
}
305
 
306
/*===========================================================================*
307
 *              do_stop                      *
308
 *===========================================================================*/
309
void do_stop( dpeth_t * dep ){
310
    if(( dep->de_mode != DEM_SINK ) && ( dep->de_mode == DEM_ENABLED ) && ( dep->de_flags & DEF_ENABLED )){
311
        outb_reg0( dep, DP_CR, CR_STP | CR_DM_ABORT );
312
        ( dep->de_stopf )( dep );
313
 
314
        dep->de_flags = DEF_EMPTY;
315
    }
316
}
317
 
4192 mejdrech 318
int queue_packet( dpeth_t * dep, packet_t packet ){
319
    packet_t    tmp;
320
 
321
    if( dep->packet_count > 1 ){
322
        if( ! pq_add( pq_previous( dep->packet_queue ), packet, 0, 0 )){
323
            return EINVAL;
324
        }
325
    }else{
326
        tmp = pq_add( dep->packet_queue, packet, 0, 0 );
327
        if( ! tmp ) return EINVAL;
328
        dep->packet_queue = tmp;
329
    }
330
    ++ dep->packet_count;
331
    return EBUSY;
332
}
333
 
4163 mejdrech 334
/*===========================================================================*
4192 mejdrech 335
 *          based on    do_vwrite                    *
336
 *===========================================================================*/
337
int do_pwrite( dpeth_t * dep, packet_t packet, int from_int )
338
{
339
//  int port, count, size;
340
    int size;
341
    int sendq_head;
342
/*  dpeth_t *dep;
343
 
344
    port = mp->DL_PORT;
345
    count = mp->DL_COUNT;
346
    if (port < 0 || port >= DE_PORT_NR)
347
        panic("", "dp8390: illegal port", port);
348
    dep= &de_table[port];
349
    dep->de_client= mp->DL_PROC;
350
*/
351
    if (dep->de_mode == DEM_SINK)
352
    {
353
        assert(!from_int);
4498 mejdrech 354
//      dep->de_flags |= DEF_PACK_SEND;
4192 mejdrech 355
        reply(dep, OK, FALSE);
356
//      return;
357
        return EOK;
358
    }
359
    assert(dep->de_mode == DEM_ENABLED);
360
    assert(dep->de_flags & DEF_ENABLED);
4498 mejdrech 361
    if( dep->packet_queue && ( ! from_int )){
362
//  if (dep->de_flags & DEF_SEND_AVAIL){
4192 mejdrech 363
//      panic("", "dp8390: send already in progress", NO_NUM);
364
        return queue_packet( dep, packet );
365
    }
366
 
367
    sendq_head= dep->de_sendq_head;
4498 mejdrech 368
//  if (dep->de_sendq[sendq_head].sq_filled)
369
//  {
370
//      if (from_int)
371
//          panic("", "dp8390: should not be sending\n", NO_NUM);
4192 mejdrech 372
//      dep->de_sendmsg= *mp;
4498 mejdrech 373
//      dep->de_flags |= DEF_SEND_AVAIL;
374
//      reply(dep, OK, FALSE);
4192 mejdrech 375
//      return;
4498 mejdrech 376
//      return queue_packet( dep, packet );
377
//  }
378
//  assert(!(dep->de_flags & DEF_PACK_SEND));
4192 mejdrech 379
 
380
/*  if (vectored)
381
    {
382
        get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
383
            (count > IOVEC_NR ? IOVEC_NR : count) *
384
            sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
385
        dep->de_write_iovec.iod_iovec_s = count;
386
        dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
387
        dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
388
 
389
        dep->de_tmp_iovec = dep->de_write_iovec;
390
        size = calc_iovec_size(&dep->de_tmp_iovec);
391
    }
392
    else
393
    {  
394
        dep->de_write_iovec.iod_iovec[0].iov_addr =
395
            (vir_bytes) mp->DL_ADDR;
396
        dep->de_write_iovec.iod_iovec[0].iov_size =
397
            mp->DL_COUNT;
398
        dep->de_write_iovec.iod_iovec_s = 1;
399
        dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
400
        dep->de_write_iovec.iod_iovec_addr = 0;
401
        size= mp->DL_COUNT;
402
    }
403
*/
404
    size = packet_get_data_length( packet );
405
    dep->de_write_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_get_data( packet );
406
    dep->de_write_iovec.iod_iovec[0].iov_size = size;
407
    dep->de_write_iovec.iod_iovec_s = 1;
408
    dep->de_write_iovec.iod_iovec_addr = NULL;
409
 
410
    if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
411
    {
412
        panic("", "dp8390: invalid packet size", size);
413
        return EINVAL;
414
    }
415
    (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
416
        dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
417
        size);
418
    dep->de_sendq[sendq_head].sq_filled= TRUE;
419
    if (dep->de_sendq_tail == sendq_head)
420
    {
421
        outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
422
        outb_reg0(dep, DP_TBCR1, size >> 8);
423
        outb_reg0(dep, DP_TBCR0, size & 0xff);
424
        outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
425
    }
426
    else
427
        dep->de_sendq[sendq_head].sq_size= size;
428
 
429
    if (++sendq_head == dep->de_sendq_nr)
430
        sendq_head= 0;
431
    assert(sendq_head < SENDQ_NR);
432
    dep->de_sendq_head= sendq_head;
433
 
4498 mejdrech 434
//  dep->de_flags |= DEF_PACK_SEND;
4192 mejdrech 435
 
436
    /* If the interrupt handler called, don't send a reply. The reply
437
     * will be sent after all interrupts are handled.
438
     */
439
    if (from_int)
440
        return EOK;
441
    reply(dep, OK, FALSE);
442
 
443
    assert(dep->de_mode == DEM_ENABLED);
444
    assert(dep->de_flags & DEF_ENABLED);
445
    return EOK;
446
}
447
 
448
/*===========================================================================*
4163 mejdrech 449
 *              dp_init                      *
450
 *===========================================================================*/
451
void dp_init(dep)
452
dpeth_t *dep;
453
{
454
    int dp_rcr_reg;
455
    int i;//, r;
456
 
457
    /* General initialization */
458
    dep->de_flags = DEF_EMPTY;
459
    (*dep->de_initf)(dep);
460
 
461
//  dp_confaddr(dep);
462
 
463
    if (debug)
464
    {
465
        printf("%s: Ethernet address ", dep->de_name);
466
        for (i= 0; i < 6; i++)
467
            printf("%x%c", dep->de_address.ea_addr[i],
468
                            i < 5 ? ':' : '\n');
469
    }
470
 
471
    /* Map buffer */
472
    map_hw_buffer(dep);
473
 
474
    /* Initialization of the dp8390 following the mandatory procedure
475
     * in reference manual ("DP8390D/NS32490D NIC Network Interface
476
     * Controller", National Semiconductor, July 1995, Page 29).
477
     */
478
    /* Step 1: */
479
    outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
480
    /* Step 2: */
481
    if (dep->de_16bit)
482
        outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
483
    else
484
        outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
485
    /* Step 3: */
486
    outb_reg0(dep, DP_RBCR0, 0);
487
    outb_reg0(dep, DP_RBCR1, 0);
488
    /* Step 4: */
489
    dp_rcr_reg = 0;
490
    if (dep->de_flags & DEF_PROMISC)
491
        dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
492
    if (dep->de_flags & DEF_BROAD)
493
        dp_rcr_reg |= RCR_AB;
494
    if (dep->de_flags & DEF_MULTI)
495
        dp_rcr_reg |= RCR_AM;
496
    outb_reg0(dep, DP_RCR, dp_rcr_reg);
497
    /* Step 5: */
498
    outb_reg0(dep, DP_TCR, TCR_INTERNAL);
499
    /* Step 6: */
500
    outb_reg0(dep, DP_BNRY, dep->de_startpage);
501
    outb_reg0(dep, DP_PSTART, dep->de_startpage);
502
    outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
503
    /* Step 7: */
504
    outb_reg0(dep, DP_ISR, 0xFF);
505
    /* Step 8: */
506
    outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
507
        IMR_OVWE | IMR_CNTE);
508
    /* Step 9: */
509
    outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
510
 
511
    outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
512
    outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
513
    outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
514
    outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
515
    outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
516
    outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
517
 
518
    outb_reg1(dep, DP_MAR0, 0xff);
519
    outb_reg1(dep, DP_MAR1, 0xff);
520
    outb_reg1(dep, DP_MAR2, 0xff);
521
    outb_reg1(dep, DP_MAR3, 0xff);
522
    outb_reg1(dep, DP_MAR4, 0xff);
523
    outb_reg1(dep, DP_MAR5, 0xff);
524
    outb_reg1(dep, DP_MAR6, 0xff);
525
    outb_reg1(dep, DP_MAR7, 0xff);
526
 
527
    outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
528
    /* Step 10: */
529
    outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
530
    /* Step 11: */
531
    outb_reg0(dep, DP_TCR, TCR_NORMAL);
532
 
533
    inb_reg0(dep, DP_CNTR0);        /* reset counters by reading */
534
    inb_reg0(dep, DP_CNTR1);
535
    inb_reg0(dep, DP_CNTR2);
536
 
537
    /* Finish the initialization. */
538
    dep->de_flags |= DEF_ENABLED;
539
    for (i= 0; i<dep->de_sendq_nr; i++)
540
        dep->de_sendq[i].sq_filled= 0;
541
    dep->de_sendq_head= 0;
542
    dep->de_sendq_tail= 0;
4192 mejdrech 543
    if (!dep->de_prog_IO)
544
    {
545
        dep->de_user2nicf= dp_user2nic;
4163 mejdrech 546
//      dep->de_user2nicf_s= dp_user2nic_s;
547
        dep->de_nic2userf= dp_nic2user;
548
//      dep->de_nic2userf_s= dp_nic2user_s;
549
        dep->de_getblockf= dp_getblock;
4192 mejdrech 550
    }
551
    else if (dep->de_16bit)
552
    {
553
        dep->de_user2nicf= dp_pio16_user2nic;
4163 mejdrech 554
//      dep->de_user2nicf_s= dp_pio16_user2nic_s;
4192 mejdrech 555
        dep->de_nic2userf= dp_pio16_nic2user;
4163 mejdrech 556
//      dep->de_nic2userf_s= dp_pio16_nic2user_s;
4192 mejdrech 557
        dep->de_getblockf= dp_pio16_getblock;
558
    }
559
    else
560
    {
561
        dep->de_user2nicf= dp_pio8_user2nic;
4163 mejdrech 562
//      dep->de_user2nicf_s= dp_pio8_user2nic_s;
4192 mejdrech 563
        dep->de_nic2userf= dp_pio8_nic2user;
4163 mejdrech 564
//      dep->de_nic2userf_s= dp_pio8_nic2user_s;
4192 mejdrech 565
        dep->de_getblockf= dp_pio8_getblock;
566
    }
4163 mejdrech 567
 
568
    /* Set the interrupt handler and policy. Do not automatically
569
     * reenable interrupts. Return the IRQ line number on interrupts.
570
     */
571
/*  dep->de_hook = dep->de_irq;
572
    r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
573
    if (r != OK)
574
        panic("DP8390", "sys_irqsetpolicy failed", r);
575
 
576
    r= sys_irqenable(&dep->de_hook);
577
    if (r != OK)
578
    {
579
        panic("DP8390", "unable enable interrupts", r);
580
    }
581
*/
582
}
583
 
584
/*===========================================================================*
585
 *              dp_reinit                    *
586
 *===========================================================================*/
587
static void dp_reinit(dep)
588
dpeth_t *dep;
589
{
590
    int dp_rcr_reg;
591
 
592
    outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
593
 
594
    dp_rcr_reg = 0;
595
    if (dep->de_flags & DEF_PROMISC)
596
        dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
597
    if (dep->de_flags & DEF_BROAD)
598
        dp_rcr_reg |= RCR_AB;
599
    if (dep->de_flags & DEF_MULTI)
600
        dp_rcr_reg |= RCR_AM;
601
    outb_reg0(dep, DP_RCR, dp_rcr_reg);
602
}
603
 
604
/*===========================================================================*
605
 *              dp_reset                     *
606
 *===========================================================================*/
607
static void dp_reset(dep)
608
dpeth_t *dep;
609
{
610
    int i;
611
 
612
    /* Stop chip */
613
    outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
614
    outb_reg0(dep, DP_RBCR0, 0);
615
    outb_reg0(dep, DP_RBCR1, 0);
616
    for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
617
        ; /* Do nothing */
618
    outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
619
    outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
620
    outb_reg0(dep, DP_TCR, TCR_NORMAL);
621
 
622
    /* Acknowledge the ISR_RDC (remote dma) interrupt. */
623
    for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
624
        ; /* Do nothing */
625
    outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
626
 
627
    /* Reset the transmit ring. If we were transmitting a packet, we
628
     * pretend that the packet is processed. Higher layers will
629
     * retransmit if the packet wasn't actually sent.
630
     */
631
    dep->de_sendq_head= dep->de_sendq_tail= 0;
632
    for (i= 0; i<dep->de_sendq_nr; i++)
633
        dep->de_sendq[i].sq_filled= 0;
634
    dp_send(dep);
635
    dep->de_flags &= ~DEF_STOPPED;
636
}
637
 
638
/*===========================================================================*
639
 *              dp_check_ints                    *
640
 *===========================================================================*/
4327 mejdrech 641
void dp_check_ints(dep, isr)
4163 mejdrech 642
dpeth_t *dep;
4327 mejdrech 643
int isr;
4163 mejdrech 644
{
4327 mejdrech 645
    int /*isr,*/ tsr;
4163 mejdrech 646
    int size, sendq_tail;
647
 
648
    if (!(dep->de_flags & DEF_ENABLED))
649
        panic("", "dp8390: got premature interrupt", NO_NUM);
650
 
651
    for(;;)
652
    {
4327 mejdrech 653
//      isr = inb_reg0(dep, DP_ISR);
4163 mejdrech 654
        if (!isr)
655
            break;
656
        outb_reg0(dep, DP_ISR, isr);
657
        if (isr & (ISR_PTX|ISR_TXE))
658
        {
659
            if (isr & ISR_TXE)
660
            {
661
#if DEBUG
662
 { printf("%s: got send Error\n", dep->de_name); }
663
#endif
664
                dep->de_stat.ets_sendErr++;
665
            }
666
            else
667
            {
668
                tsr = inb_reg0(dep, DP_TSR);
669
 
670
                if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
671
#if 0   /* Reserved in later manuals, should be ignored */
672
                if (!(tsr & TSR_DFR))
673
                {
674
                    /* In most (all?) implementations of
675
                     * the dp8390, this bit is set
676
                     * when the packet is not deferred
677
                     */
678
                    dep->de_stat.ets_transDef++;
679
                }
680
#endif
681
                if (tsr & TSR_COL) dep->de_stat.ets_collision++;
682
                if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
683
                if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
684
                if (tsr & TSR_FU
685
                    && ++dep->de_stat.ets_fifoUnder <= 10)
686
                {
687
                    printf("%s: fifo underrun\n",
688
                        dep->de_name);
689
                }
690
                if (tsr & TSR_CDH
691
                    && ++dep->de_stat.ets_CDheartbeat <= 10)
692
                {
693
                    printf("%s: CD heart beat failure\n",
694
                        dep->de_name);
695
                }
696
                if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
697
            }
698
            sendq_tail= dep->de_sendq_tail;
699
 
700
            if (!(dep->de_sendq[sendq_tail].sq_filled))
701
            {
702
                /* Software bug? */
703
                assert(!debug);
704
 
705
                /* Or hardware bug? */
706
                printf(
707
                "%s: transmit interrupt, but not sending\n",
708
                    dep->de_name);
709
                continue;
710
            }
711
            dep->de_sendq[sendq_tail].sq_filled= 0;
712
            if (++sendq_tail == dep->de_sendq_nr)
713
                sendq_tail= 0;
714
            dep->de_sendq_tail= sendq_tail;
715
            if (dep->de_sendq[sendq_tail].sq_filled)
716
            {
717
                size= dep->de_sendq[sendq_tail].sq_size;
718
                outb_reg0(dep, DP_TPSR,
719
                    dep->de_sendq[sendq_tail].sq_sendpage);
720
                outb_reg0(dep, DP_TBCR1, size >> 8);
721
                outb_reg0(dep, DP_TBCR0, size & 0xff);
722
                outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
723
            }
4498 mejdrech 724
//          if (dep->de_flags & DEF_SEND_AVAIL)
4163 mejdrech 725
                dp_send(dep);
726
        }
727
 
728
        if (isr & ISR_PRX)
729
        {
730
            /* Only call dp_recv if there is a read request */
4332 mejdrech 731
//          if (dep->de_flags) & DEF_READING)
4163 mejdrech 732
                dp_recv(dep);
733
        }
734
 
735
        if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
736
        if (isr & ISR_CNT)
737
        {
738
            dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
739
            dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
740
            dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
741
        }
742
        if (isr & ISR_OVW)
743
        {
744
            dep->de_stat.ets_OVW++;
745
#if 0
746
            { printW(); printf(
747
                "%s: got overwrite warning\n", dep->de_name); }
748
#endif
4332 mejdrech 749
/*          if (dep->de_flags & DEF_READING)
4163 mejdrech 750
            {
751
                printf(
752
"dp_check_ints: strange: overwrite warning and pending read request\n");
753
                dp_recv(dep);
754
            }
4332 mejdrech 755
*/      }
4163 mejdrech 756
        if (isr & ISR_RDC)
757
        {
758
            /* Nothing to do */
759
        }
760
        if (isr & ISR_RST)
761
        {
762
            /* this means we got an interrupt but the ethernet
763
             * chip is shutdown. We set the flag DEF_STOPPED,
764
             * and continue processing arrived packets. When the
765
             * receive buffer is empty, we reset the dp8390.
766
             */
767
#if 0
768
             { printW(); printf(
769
                "%s: NIC stopped\n", dep->de_name); }
770
#endif
771
            dep->de_flags |= DEF_STOPPED;
772
            break;
773
        }
4327 mejdrech 774
        isr = inb_reg0(dep, DP_ISR);
4163 mejdrech 775
    }
4332 mejdrech 776
//  if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) == 
777
//                      (DEF_READING|DEF_STOPPED))
778
    if ((dep->de_flags & DEF_STOPPED) == DEF_STOPPED )
4163 mejdrech 779
    {
780
        /* The chip is stopped, and all arrived packets are
781
         * delivered.
782
         */
783
        dp_reset(dep);
784
    }
785
}
786
 
787
/*===========================================================================*
788
 *              dp_recv                      *
789
 *===========================================================================*/
790
static void dp_recv(dep)
791
dpeth_t *dep;
792
{
793
    dp_rcvhdr_t header;
794
    unsigned pageno, curr, next;
795
    vir_bytes length;
796
    int packet_processed, r;
797
    u16_t eth_type;
798
 
799
    packet_processed = FALSE;
800
    pageno = inb_reg0(dep, DP_BNRY) + 1;
801
    if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
802
 
803
    do
804
    {
805
        outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
806
        curr = inb_reg1(dep, DP_CURR);
807
        outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
808
 
809
        if (curr == pageno) break;
810
 
811
        (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
812
            &header);
813
        (dep->de_getblockf)(dep, pageno, sizeof(header) +
814
            2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
815
 
816
        length = (header.dr_rbcl | (header.dr_rbch << 8)) -
817
            sizeof(dp_rcvhdr_t);
818
        next = header.dr_next;
819
        if (length < ETH_MIN_PACK_SIZE ||
820
            length > ETH_MAX_PACK_SIZE_TAGGED)
821
        {
822
            printf("%s: packet with strange length arrived: %d\n",
823
                dep->de_name, (int) length);
824
            next= curr;
825
        }
826
        else if (next < dep->de_startpage || next >= dep->de_stoppage)
827
        {
828
            printf("%s: strange next page\n", dep->de_name);
829
            next= curr;
830
        }
831
/*      else if (eth_type == eth_ign_proto)
832
        {
833
*/          /* Hack: ignore packets of a given protocol, useful
834
             * if you share a net with 80 computers sending
835
             * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
836
             */
837
/*          static int first= 1;
838
            if (first)
839
            {
840
                first= 0;
841
                printf("%s: dropping proto 0x%04x packets\n",
842
                    dep->de_name,
843
                    ntohs(eth_ign_proto));
844
            }
845
            dep->de_stat.ets_packetR++;
846
        }
847
*/      else if (header.dr_status & RSR_FO)
848
        {
849
            /* This is very serious, so we issue a warning and
850
             * reset the buffers */
851
            printf("%s: fifo overrun, resetting receive buffer\n",
852
                dep->de_name);
853
            dep->de_stat.ets_fifoOver++;
854
            next = curr;
855
        }
856
        else if ((header.dr_status & RSR_PRX) &&
857
                       (dep->de_flags & DEF_ENABLED))
858
        {
859
//          if (dep->de_safecopy_read)
860
//              r = dp_pkt2user_s(dep, pageno, length);
861
//          else
862
                r = dp_pkt2user(dep, pageno, length);
863
            if (r != OK)
864
                return;
865
 
866
            packet_processed = TRUE;
867
            dep->de_stat.ets_packetR++;
868
        }
869
        if (next == dep->de_startpage)
870
            outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
871
        else
872
            outb_reg0(dep, DP_BNRY, next - 1);
873
 
874
        pageno = next;
875
    }
876
    while (!packet_processed);
877
}
878
 
879
/*===========================================================================*
880
 *              dp_send                      *
881
 *===========================================================================*/
882
static void dp_send(dep)
883
dpeth_t *dep;
884
{
4192 mejdrech 885
    packet_t packet;
886
 
4498 mejdrech 887
//  if (!(dep->de_flags & DEF_SEND_AVAIL))
888
//      return;
4163 mejdrech 889
 
4498 mejdrech 890
    if( dep->packet_queue ){
4192 mejdrech 891
        packet = dep->packet_queue;
892
        dep->packet_queue = pq_detach( packet );
893
        do_pwrite( dep, packet, TRUE );
894
        netif_pq_release( packet_get_id( packet ));
895
        -- dep->packet_count;
896
    }
4498 mejdrech 897
//  if( ! dep->packet_queue ){
898
//      dep->de_flags &= ~DEF_SEND_AVAIL;
899
//  }
4192 mejdrech 900
/*  switch(dep->de_sendmsg.m_type)
4163 mejdrech 901
    {
902
    case DL_WRITE:  do_vwrite(&dep->de_sendmsg, TRUE, FALSE);   break;
903
    case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE);    break;
904
    case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, TRUE);  break;
905
    default:
906
        panic("", "dp8390: wrong type", dep->de_sendmsg.m_type);
907
        break;
908
    }
909
*/
910
}
911
 
912
/*===========================================================================*
913
 *              dp_getblock                  *
914
 *===========================================================================*/
915
static void dp_getblock(dep, page, offset, size, dst)
916
dpeth_t *dep;
917
int page;
918
size_t offset;
919
size_t size;
920
void *dst;
921
{
922
//  int r;
923
 
924
    offset = page * DP_PAGESIZE + offset;
925
 
926
    memcpy(dst, dep->de_locmem + offset, size);
927
}
928
 
929
/*===========================================================================*
4192 mejdrech 930
 *              dp_pio8_getblock                 *
931
 *===========================================================================*/
932
static void dp_pio8_getblock(dep, page, offset, size, dst)
933
dpeth_t *dep;
934
int page;
935
size_t offset;
936
size_t size;
937
void *dst;
938
{
939
    offset = page * DP_PAGESIZE + offset;
940
    outb_reg0(dep, DP_RBCR0, size & 0xFF);
941
    outb_reg0(dep, DP_RBCR1, size >> 8);
942
    outb_reg0(dep, DP_RSAR0, offset & 0xFF);
943
    outb_reg0(dep, DP_RSAR1, offset >> 8);
944
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
945
 
946
    insb(dep->de_data_port, dst, size);
947
}
948
 
949
/*===========================================================================*
950
 *              dp_pio16_getblock                *
951
 *===========================================================================*/
952
static void dp_pio16_getblock(dep, page, offset, size, dst)
953
dpeth_t *dep;
954
int page;
955
size_t offset;
956
size_t size;
957
void *dst;
958
{
959
    offset = page * DP_PAGESIZE + offset;
960
    outb_reg0(dep, DP_RBCR0, size & 0xFF);
961
    outb_reg0(dep, DP_RBCR1, size >> 8);
962
    outb_reg0(dep, DP_RSAR0, offset & 0xFF);
963
    outb_reg0(dep, DP_RSAR1, offset >> 8);
964
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
965
 
966
    assert (!(size & 1));
967
    insw(dep->de_data_port, dst, size);
968
}
969
 
970
/*===========================================================================*
4163 mejdrech 971
 *              dp_pkt2user                  *
972
 *===========================================================================*/
973
static int dp_pkt2user(dep, page, length)
974
dpeth_t *dep;
975
int page, length;
976
{
977
    int last, count;
4192 mejdrech 978
    packet_t    packet;
4261 mejdrech 979
    packet_t    queue;
4163 mejdrech 980
 
4332 mejdrech 981
//  if (!(dep->de_flags & DEF_READING))
982
//      return EGENERIC;
4163 mejdrech 983
 
4192 mejdrech 984
    packet = netif_packet_get_1( length );
985
    if( ! packet ) return ENOMEM;
986
    dep->de_read_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_suffix( packet, length );
987
    dep->de_read_iovec.iod_iovec[0].iov_size = length;
988
    dep->de_read_iovec.iod_iovec_s = 1;
989
    dep->de_read_iovec.iod_iovec_addr = NULL;
990
 
4163 mejdrech 991
    last = page + (length - 1) / DP_PAGESIZE;
992
    if (last >= dep->de_stoppage)
993
    {
994
        count = (dep->de_stoppage - page) * DP_PAGESIZE -
995
            sizeof(dp_rcvhdr_t);
996
 
997
        /* Save read_iovec since we need it twice. */
998
        dep->de_tmp_iovec = dep->de_read_iovec;
999
        (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
1000
            sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
1001
        (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
1002
                &dep->de_read_iovec, count, length - count);
1003
    }
1004
    else
1005
    {
1006
        (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
1007
            sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
1008
    }
1009
 
1010
    dep->de_read_s = length;
1011
    dep->de_flags |= DEF_PACK_RECV;
4332 mejdrech 1012
//  dep->de_flags &= ~DEF_READING;
4163 mejdrech 1013
 
4261 mejdrech 1014
    queue = pq_add( dep->received_queue, packet, 0, 0 );
1015
    if( queue ){
1016
        dep->received_queue = queue;
1017
    }else{
4192 mejdrech 1018
        netif_pq_release( packet_get_id( packet ));
1019
    }
4163 mejdrech 1020
    return OK;
1021
}
1022
 
1023
/*===========================================================================*
4192 mejdrech 1024
 *              dp_user2nic                  *
1025
 *===========================================================================*/
1026
static void dp_user2nic(dep, iovp, offset, nic_addr, count)
1027
dpeth_t *dep;
1028
iovec_dat_t *iovp;
1029
vir_bytes offset;
1030
int nic_addr;
1031
vir_bytes count;
1032
{
1033
    vir_bytes vir_hw;//, vir_user;
1034
    int bytes, i, r;
1035
 
1036
    vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
1037
 
1038
    i= 0;
1039
    while (count > 0)
1040
    {
1041
        if (i >= IOVEC_NR)
1042
        {
1043
            dp_next_iovec(iovp);
1044
            i= 0;
1045
            continue;
1046
        }
1047
        assert(i < iovp->iod_iovec_s);
1048
        if (offset >= iovp->iod_iovec[i].iov_size)
1049
        {
1050
            offset -= iovp->iod_iovec[i].iov_size;
1051
            i++;
1052
            continue;
1053
        }
1054
        bytes = iovp->iod_iovec[i].iov_size - offset;
1055
        if (bytes > count)
1056
            bytes = count;
1057
 
1058
        r= sys_vircopy(iovp->iod_proc_nr, D,
1059
            iovp->iod_iovec[i].iov_addr + offset,
1060
            SELF, D, vir_hw, bytes);
1061
        if (r != OK)
1062
            panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
1063
 
1064
        count -= bytes;
1065
        vir_hw += bytes;
1066
        offset += bytes;
1067
    }
1068
    assert(count == 0);
1069
}
1070
 
1071
/*===========================================================================*
1072
 *              dp_pio8_user2nic                 *
1073
 *===========================================================================*/
1074
static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
1075
dpeth_t *dep;
1076
iovec_dat_t *iovp;
1077
vir_bytes offset;
1078
int nic_addr;
1079
vir_bytes count;
1080
{
1081
//  phys_bytes phys_user;
1082
    int bytes, i;
1083
 
1084
    outb_reg0(dep, DP_ISR, ISR_RDC);
1085
 
1086
    outb_reg0(dep, DP_RBCR0, count & 0xFF);
1087
    outb_reg0(dep, DP_RBCR1, count >> 8);
1088
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1089
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1090
    outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1091
 
1092
    i= 0;
1093
    while (count > 0)
1094
    {
1095
        if (i >= IOVEC_NR)
1096
        {
1097
            dp_next_iovec(iovp);
1098
            i= 0;
1099
            continue;
1100
        }
1101
        assert(i < iovp->iod_iovec_s);
1102
        if (offset >= iovp->iod_iovec[i].iov_size)
1103
        {
1104
            offset -= iovp->iod_iovec[i].iov_size;
1105
            i++;
1106
            continue;
1107
        }
1108
        bytes = iovp->iod_iovec[i].iov_size - offset;
1109
        if (bytes > count)
1110
            bytes = count;
1111
 
1112
        do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
1113
            iovp->iod_iovec[i].iov_addr + offset, bytes);
1114
        count -= bytes;
1115
        offset += bytes;
1116
    }
1117
    assert(count == 0);
1118
 
1119
    for (i= 0; i<100; i++)
1120
    {
1121
        if (inb_reg0(dep, DP_ISR) & ISR_RDC)
1122
            break;
1123
    }
1124
    if (i == 100)
1125
    {
1126
        panic("", "dp8390: remote dma failed to complete", NO_NUM);
1127
    }
1128
}
1129
 
1130
/*===========================================================================*
1131
 *              dp_pio16_user2nic                *
1132
 *===========================================================================*/
1133
static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
1134
dpeth_t *dep;
1135
iovec_dat_t *iovp;
1136
vir_bytes offset;
1137
int nic_addr;
1138
vir_bytes count;
1139
{
1140
    vir_bytes vir_user;
1141
    vir_bytes ecount;
1142
    int i, r, bytes, user_proc;
1143
    u8_t two_bytes[2];
1144
    int odd_byte;
1145
 
1146
    ecount= (count+1) & ~1;
1147
    odd_byte= 0;
1148
 
1149
    outb_reg0(dep, DP_ISR, ISR_RDC);
1150
    outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
1151
    outb_reg0(dep, DP_RBCR1, ecount >> 8);
1152
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1153
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1154
    outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
1155
 
1156
    i= 0;
1157
    while (count > 0)
1158
    {
1159
        if (i >= IOVEC_NR)
1160
        {
1161
            dp_next_iovec(iovp);
1162
            i= 0;
1163
            continue;
1164
        }
1165
        assert(i < iovp->iod_iovec_s);
1166
        if (offset >= iovp->iod_iovec[i].iov_size)
1167
        {
1168
            offset -= iovp->iod_iovec[i].iov_size;
1169
            i++;
1170
            continue;
1171
        }
1172
        bytes = iovp->iod_iovec[i].iov_size - offset;
1173
        if (bytes > count)
1174
            bytes = count;
1175
 
1176
        user_proc= iovp->iod_proc_nr;
1177
        vir_user= iovp->iod_iovec[i].iov_addr + offset;
1178
        if (odd_byte)
1179
        {
1180
            r= sys_vircopy(user_proc, D, vir_user,
1181
                SELF, D, (vir_bytes)&two_bytes[1], 1);
1182
            if (r != OK)
1183
            {
1184
                panic("DP8390",
1185
                    "dp_pio16_user2nic: sys_vircopy failed",
1186
                    r);
1187
            }
1188
            outw(dep->de_data_port, *(u16_t *)two_bytes);
1189
            count--;
1190
            offset++;
1191
            bytes--;
1192
            vir_user++;
1193
            odd_byte= 0;
1194
            if (!bytes)
1195
                continue;
1196
        }
1197
        ecount= bytes & ~1;
1198
        if (ecount != 0)
1199
        {
1200
            do_vir_outsw(dep->de_data_port, user_proc, vir_user,
1201
                ecount);
1202
            count -= ecount;
1203
            offset += ecount;
1204
            bytes -= ecount;
1205
            vir_user += ecount;
1206
        }
1207
        if (bytes)
1208
        {
1209
            assert(bytes == 1);
1210
            r= sys_vircopy(user_proc, D, vir_user,
1211
                SELF, D, (vir_bytes)&two_bytes[0], 1);
1212
            if (r != OK)
1213
            {
1214
                panic("DP8390",
1215
                    "dp_pio16_user2nic: sys_vircopy failed",
1216
                    r);
1217
            }
1218
            count--;
1219
            offset++;
1220
            bytes--;
1221
            vir_user++;
1222
            odd_byte= 1;
1223
        }
1224
    }
1225
    assert(count == 0);
1226
 
1227
    if (odd_byte)
1228
        outw(dep->de_data_port, *(u16_t *)two_bytes);
1229
 
1230
    for (i= 0; i<100; i++)
1231
    {
1232
        if (inb_reg0(dep, DP_ISR) & ISR_RDC)
1233
            break;
1234
    }
1235
    if (i == 100)
1236
    {
1237
        panic("", "dp8390: remote dma failed to complete", NO_NUM);
1238
    }
1239
}
1240
 
1241
/*===========================================================================*
4163 mejdrech 1242
 *              dp_nic2user                  *
1243
 *===========================================================================*/
1244
static void dp_nic2user(dep, nic_addr, iovp, offset, count)
1245
dpeth_t *dep;
1246
int nic_addr;
1247
iovec_dat_t *iovp;
1248
vir_bytes offset;
1249
vir_bytes count;
1250
{
4192 mejdrech 1251
    vir_bytes vir_hw;//, vir_user;
4163 mejdrech 1252
    int bytes, i, r;
1253
 
1254
    vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
1255
 
1256
    i= 0;
1257
    while (count > 0)
1258
    {
1259
        if (i >= IOVEC_NR)
1260
        {
1261
            dp_next_iovec(iovp);
1262
            i= 0;
1263
            continue;
1264
        }
1265
        assert(i < iovp->iod_iovec_s);
1266
        if (offset >= iovp->iod_iovec[i].iov_size)
1267
        {
1268
            offset -= iovp->iod_iovec[i].iov_size;
1269
            i++;
1270
            continue;
1271
        }
1272
        bytes = iovp->iod_iovec[i].iov_size - offset;
1273
        if (bytes > count)
1274
            bytes = count;
1275
 
1276
        r= sys_vircopy(SELF, D, vir_hw,
1277
            iovp->iod_proc_nr, D,
1278
            iovp->iod_iovec[i].iov_addr + offset, bytes);
1279
        if (r != OK)
1280
            panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
1281
 
1282
        count -= bytes;
1283
        vir_hw += bytes;
1284
        offset += bytes;
1285
    }
1286
    assert(count == 0);
1287
}
1288
 
1289
/*===========================================================================*
4192 mejdrech 1290
 *              dp_pio8_nic2user                 *
1291
 *===========================================================================*/
1292
static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
1293
dpeth_t *dep;
1294
int nic_addr;
1295
iovec_dat_t *iovp;
1296
vir_bytes offset;
1297
vir_bytes count;
1298
{
1299
//  phys_bytes phys_user;
1300
    int bytes, i;
1301
 
1302
    outb_reg0(dep, DP_RBCR0, count & 0xFF);
1303
    outb_reg0(dep, DP_RBCR1, count >> 8);
1304
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1305
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1306
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1307
 
1308
    i= 0;
1309
    while (count > 0)
1310
    {
1311
        if (i >= IOVEC_NR)
1312
        {
1313
            dp_next_iovec(iovp);
1314
            i= 0;
1315
            continue;
1316
        }
1317
        assert(i < iovp->iod_iovec_s);
1318
        if (offset >= iovp->iod_iovec[i].iov_size)
1319
        {
1320
            offset -= iovp->iod_iovec[i].iov_size;
1321
            i++;
1322
            continue;
1323
        }
1324
        bytes = iovp->iod_iovec[i].iov_size - offset;
1325
        if (bytes > count)
1326
            bytes = count;
1327
 
1328
        do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
1329
            iovp->iod_iovec[i].iov_addr + offset, bytes);
1330
        count -= bytes;
1331
        offset += bytes;
1332
    }
1333
    assert(count == 0);
1334
}
1335
 
1336
/*===========================================================================*
1337
 *              dp_pio16_nic2user                *
1338
 *===========================================================================*/
1339
static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
1340
dpeth_t *dep;
1341
int nic_addr;
1342
iovec_dat_t *iovp;
1343
vir_bytes offset;
1344
vir_bytes count;
1345
{
1346
    vir_bytes vir_user;
1347
    vir_bytes ecount;
1348
    int i, r, bytes, user_proc;
1349
    u8_t two_bytes[2];
1350
    int odd_byte;
1351
 
1352
    ecount= (count+1) & ~1;
1353
    odd_byte= 0;
1354
 
1355
    outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
1356
    outb_reg0(dep, DP_RBCR1, ecount >> 8);
1357
    outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
1358
    outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
1359
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
1360
 
1361
    i= 0;
1362
    while (count > 0)
1363
    {
1364
        if (i >= IOVEC_NR)
1365
        {
1366
            dp_next_iovec(iovp);
1367
            i= 0;
1368
            continue;
1369
        }
1370
        assert(i < iovp->iod_iovec_s);
1371
        if (offset >= iovp->iod_iovec[i].iov_size)
1372
        {
1373
            offset -= iovp->iod_iovec[i].iov_size;
1374
            i++;
1375
            continue;
1376
        }
1377
        bytes = iovp->iod_iovec[i].iov_size - offset;
1378
        if (bytes > count)
1379
            bytes = count;
1380
 
1381
        user_proc= iovp->iod_proc_nr;
1382
        vir_user= iovp->iod_iovec[i].iov_addr + offset;
1383
        if (odd_byte)
1384
        {
1385
            r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
1386
                user_proc, D, vir_user,  1);
1387
            if (r != OK)
1388
            {
1389
                panic("DP8390",
1390
                    "dp_pio16_nic2user: sys_vircopy failed",
1391
                    r);
1392
            }
1393
            count--;
1394
            offset++;
1395
            bytes--;
1396
            vir_user++;
1397
            odd_byte= 0;
1398
            if (!bytes)
1399
                continue;
1400
        }
1401
        ecount= bytes & ~1;
1402
        if (ecount != 0)
1403
        {
1404
            do_vir_insw(dep->de_data_port, user_proc, vir_user,
1405
                ecount);
1406
            count -= ecount;
1407
            offset += ecount;
1408
            bytes -= ecount;
1409
            vir_user += ecount;
1410
        }
1411
        if (bytes)
1412
        {
1413
            assert(bytes == 1);
1414
            *(u16_t *)two_bytes= inw(dep->de_data_port);
1415
            r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
1416
                user_proc, D, vir_user,  1);
1417
            if (r != OK)
1418
            {
1419
                panic("DP8390",
1420
                    "dp_pio16_nic2user: sys_vircopy failed",
1421
                    r);
1422
            }
1423
            count--;
1424
            offset++;
1425
            bytes--;
1426
            vir_user++;
1427
            odd_byte= 1;
1428
        }
1429
    }
1430
    assert(count == 0);
1431
}
1432
 
1433
/*===========================================================================*
1434
 *              dp_next_iovec                    *
1435
 *===========================================================================*/
1436
static void dp_next_iovec(iovp)
1437
iovec_dat_t *iovp;
1438
{
1439
    assert(iovp->iod_iovec_s > IOVEC_NR);
1440
 
1441
    iovp->iod_iovec_s -= IOVEC_NR;
1442
 
1443
    iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
1444
 
1445
    get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
1446
        (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
1447
        sizeof(iovec_t), iovp->iod_iovec);
1448
}
1449
 
1450
/*===========================================================================*
4163 mejdrech 1451
 *              conf_hw                      *
1452
 *===========================================================================*/
1453
static void conf_hw(dep)
1454
dpeth_t *dep;
1455
{
1456
//  static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0    /* ,... */ };
1457
 
1458
//  int ifnr;
1459
//  dp_conf_t *dcp;
1460
 
1461
//  dep->de_mode= DEM_DISABLED; /* Superfluous */
1462
//  ifnr= dep-de_table;
1463
 
1464
//  dcp= &dp_conf[ifnr];
1465
//  update_conf(dep, dcp);
1466
//  if (dep->de_mode != DEM_ENABLED)
1467
//      return;
1468
    if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
1469
    {
1470
        printf("%s: No ethernet card found at 0x%x\n",
1471
            dep->de_name, dep->de_base_port);
1472
        dep->de_mode= DEM_DISABLED;
1473
        return;
1474
    }
1475
 
1476
/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
1477
 
1478
    dep->de_mode = DEM_ENABLED;
1479
 
1480
    dep->de_flags = DEF_EMPTY;
1481
//  dep->de_stat = empty_stat;
1482
}
1483
 
1484
/*===========================================================================*
1485
 *              map_hw_buffer                    *
1486
 *===========================================================================*/
1487
static void map_hw_buffer(dep)
1488
dpeth_t *dep;
1489
{
1490
//  int r;
1491
//  size_t o, size;
1492
//  char *buf, *abuf;
1493
 
1494
    if (dep->de_prog_IO)
1495
    {
4192 mejdrech 1496
#if 0
4163 mejdrech 1497
        if(debug){
1498
            printf(
1499
            "map_hw_buffer: programmed I/O, no need to map buffer\n");
1500
        }
4192 mejdrech 1501
#endif
4163 mejdrech 1502
        dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */
1503
        return;
4192 mejdrech 1504
    }else{
4307 mejdrech 1505
        printf( "map_hw_buffer: no buffer!\n" );
4163 mejdrech 1506
    }
1507
 
1508
//  size = dep->de_ramsize + PAGE_SIZE; /* Add PAGE_SIZE for
1509
//                       * alignment
1510
//                       */
1511
//  buf= malloc(size);
1512
//  if (buf == NULL)
1513
//      panic(__FILE__, "map_hw_buffer: cannot malloc size", size);
1514
//  o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
1515
//  abuf= buf + o;
1516
//  printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf);
1517
 
1518
//  r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf,
1519
//          dep->de_ramsize, (phys_bytes)dep->de_linmem);
1520
//  if (r != OK)
1521
//      panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r);
1522
//  dep->de_locmem = abuf;
1523
}
1524
 
1525
/*===========================================================================*
1526
 *              reply                        *
1527
 *===========================================================================*/
1528
static void reply(dep, err, may_block)
1529
dpeth_t *dep;
1530
int err;
1531
int may_block;
1532
{
1533
/*  message reply;
1534
    int status;
1535
    int r;
1536
 
1537
    status = 0;
1538
    if (dep->de_flags & DEF_PACK_SEND)
1539
        status |= DL_PACK_SEND;
1540
    if (dep->de_flags & DEF_PACK_RECV)
1541
        status |= DL_PACK_RECV;
1542
 
1543
    reply.m_type = DL_TASK_REPLY;
1544
    reply.DL_PORT = dep - de_table;
1545
    reply.DL_PROC = dep->de_client;
1546
    reply.DL_STAT = status | ((u32_t) err << 16);
1547
    reply.DL_COUNT = dep->de_read_s;
1548
    reply.DL_CLCK = 0;  *//* Don't know */
1549
/*  r= send(dep->de_client, &reply);
1550
 
1551
    if (r == ELOCKED && may_block)
1552
    {
1553
#if 0
1554
        printf("send locked\n");
1555
#endif
1556
        return;
1557
    }
1558
 
1559
    if (r < 0)
1560
        panic("", "dp8390: send failed:", r);
1561
 
4327 mejdrech 1562
*/  dep->de_read_s = 0;
4498 mejdrech 1563
//  dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
4163 mejdrech 1564
}
1565
 
4192 mejdrech 1566
/*===========================================================================*
1567
 *              get_userdata                     *
1568
 *===========================================================================*/
1569
static void get_userdata(user_proc, user_addr, count, loc_addr)
1570
int user_proc;
1571
vir_bytes user_addr;
1572
vir_bytes count;
1573
void *loc_addr;
1574
{
1575
    int r;
1576
 
1577
    r= sys_vircopy(user_proc, D, user_addr,
1578
        SELF, D, (vir_bytes)loc_addr, count);
1579
    if (r != OK)
1580
        panic("DP8390", "get_userdata: sys_vircopy failed", r);
1581
}
1582
 
1583
static void insb(port_t port, void *buf, size_t size)
1584
{
4243 mejdrech 1585
    size_t i;
4192 mejdrech 1586
 
1587
    for( i = 0; i < size; ++ i ){
1588
        *(( uint8_t * )( buf + i )) = inb( port );
1589
    }
1590
}
1591
 
1592
static void insw(port_t port, void *buf, size_t size)
1593
{
4243 mejdrech 1594
    size_t i;
4192 mejdrech 1595
 
1596
    for( i = 0; i < size; i += 2 ){
1597
        *(( uint16_t * )( buf + i )) = inw( port );
1598
    }
1599
}
1600
 
1601
static void outsb(port_t port, void *buf, size_t size)
1602
{
4243 mejdrech 1603
    size_t i;
4192 mejdrech 1604
 
1605
    for( i = 0; i < size; ++ i ){
1606
        outb( port, *(( uint8_t * )( buf + i )));
1607
    }
1608
}
1609
 
1610
static void outsw(port_t port, void *buf, size_t size)
1611
{
4243 mejdrech 1612
    size_t i;
4192 mejdrech 1613
 
1614
    for( i = 0; i < size; i += 2 ){
1615
        outw( port, *(( uint16_t * )( buf + i )));
1616
    }
1617
}
1618
 
4163 mejdrech 1619
/*
1620
 * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
1621
 */
1622
 
1623
/** @}
1624
 */