Subversion Repositories HelenOS

Rev

Rev 4723 | 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:
4756 mejdrech 24
 *  2009 ported to HelenOS, Lukas Mejdrech
4163 mejdrech 25
 */
26
 
27
/** @addtogroup ne2k
28
 *  @{
29
 */
30
 
4350 mejdrech 31
/** @file
4756 mejdrech 32
 *  NE1000 and NE2000 network interface initialization and probe functions implementation.
4350 mejdrech 33
 */
34
 
4163 mejdrech 35
#include <stdio.h>
36
#include <unistd.h>
37
 
38
#include "dp8390_port.h"
39
 
40
/*
41
ne2000.c
42
 
43
Driver for the ne2000 ethernet cards. This file contains only the ne2000
44
specific code, the rest is in dp8390.c
45
 
46
Created:    March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
47
*/
48
 
49
//#include "../drivers.h"
50
 
51
//#include <net/gen/ether.h>
52
//#include <net/gen/eth_io.h>
53
//#if __minix_vmd
54
//#include "config.h"
55
//#endif
56
 
57
#include "local.h"
58
#include "dp8390.h"
59
#include "ne2000.h"
60
 
61
#if ENABLE_NE2000
62
 
4756 mejdrech 63
/** Number of bytes to transfer.
64
 */
4163 mejdrech 65
#define N 100
66
 
67
//#define MILLIS_TO_TICKS(m)  (((m)*HZ/1000)+1)
68
 
4756 mejdrech 69
/** Sleeps for the defined millicesonds.
70
 *  @param[in] millis The number of milliseconds to sleep.
71
 */
72
#define milli_delay( millis )   usleep(( millis ) * 1000 )
73
 
74
/** Type definition of the testing function.
75
 */
4163 mejdrech 76
_PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat)  );
77
 
4756 mejdrech 78
/** First data pattern.
79
 */
4163 mejdrech 80
u8_t    pat0[]= { 0x00, 0x00, 0x00, 0x00 };
4756 mejdrech 81
 
82
/** Second data pattern.
83
 */
4163 mejdrech 84
u8_t    pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
4756 mejdrech 85
 
86
/** Third data pattern.
87
 */
4163 mejdrech 88
u8_t    pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
4756 mejdrech 89
 
90
/** Fourth data pattern.
91
 */
4163 mejdrech 92
u8_t    pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
93
 
4756 mejdrech 94
/** Tests 8 bit NE2000 network interface.
95
 *  @param[in,out] dep The network interface structure.
96
 *  @param[in] pos The starting position.
97
 *  @param[in] pat The data pattern to be written.
98
 *  @returns True on success.
99
 *  @returns FALSE otherwise.
100
 */
101
static int test_8(dpeth_t *dep, int pos, u8_t *pat);
102
 
103
/** Tests 16 bit NE2000 network interface.
104
 *  @param[in,out] dep The network interface structure.
105
 *  @param[in] pos The starting position.
106
 *  @param[in] pat The data pattern to be written.
107
 *  @returns True on success.
108
 *  @returns FALSE otherwise.
109
 */
110
static int test_16(dpeth_t *dep, int pos, u8_t *pat);
111
 
112
/** Stops the NE2000 network interface.
113
 *  @param[in,out] dep The network interface structure.
114
 */
115
static void ne_stop(dpeth_t *dep);
4163 mejdrech 116
//_PROTOTYPE( static void milli_delay, (unsigned long millis)       );
117
 
4756 mejdrech 118
/** Initializes the NE2000 network interface.
119
 *  @param[in,out] dep The network interface structure.
120
 */
121
void ne_init(struct dpeth *dep);
4163 mejdrech 122
 
123
/*===========================================================================*
124
 *              ne_probe                     *
125
 *===========================================================================*/
126
int ne_probe(dep)
127
dpeth_t *dep;
128
{
129
    int byte;
130
    int i;
131
    int loc1, loc2;
132
    testf_t f;
133
 
134
    dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
135
 
136
    /* We probe for an ne1000 or an ne2000 by testing whether the
137
     * on board is reachable through the dp8390. Note that the
138
     * ne1000 is an 8bit card and has a memory region distict from
139
     * the 16bit ne2000
140
     */
141
 
142
    for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
143
    {
144
        /* Reset the ethernet card */
145
        byte= inb_ne(dep, NE_RESET);
146
        milli_delay(2);
147
        outb_ne(dep, NE_RESET, byte);
148
        milli_delay(2);
149
 
150
        /* Reset the dp8390 */
151
        outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
152
        for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
153
            ; /* Do nothing */
154
 
155
        /* Check if the dp8390 is really there */
156
        if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) !=
157
            (CR_STP|CR_DM_ABORT))
158
        {
159
            return 0;
160
        }
161
 
162
        /* Disable the receiver and init TCR and DCR. */
163
        outb_reg0(dep, DP_RCR, RCR_MON);
164
        outb_reg0(dep, DP_TCR, TCR_NORMAL);
165
        if (dep->de_16bit)
166
        {
167
            outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
168
                DCR_BMS);
169
        }
170
        else
171
        {
172
            outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
173
                DCR_BMS);
174
        }
175
 
176
        if (dep->de_16bit)
177
        {
178
            loc1= NE2000_START;
179
            loc2= NE2000_START + NE2000_SIZE - 4;
180
            f= test_16;
181
        }
182
        else
183
        {
184
            loc1= NE1000_START;
185
            loc2= NE1000_START + NE1000_SIZE - 4;
186
            f= test_8;
187
        }
188
        if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
189
            f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
190
            f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
191
            f(dep, loc2, pat2) && f(dep, loc2, pat3))
192
        {
193
            /* We don't need a memory segment */
194
            dep->de_linmem= 0;
195
            if (!dep->de_pci)
196
                dep->de_initf= ne_init;
197
            dep->de_stopf= ne_stop;
198
            dep->de_prog_IO= 1;
199
            return 1;
200
        }
201
    }
202
    return 0;
203
}
204
 
205
/*===========================================================================*
206
 *              ne_init                      *
207
 *===========================================================================*/
208
void ne_init(dep)
209
dpeth_t *dep;
210
{
211
    int i;
212
    int word, sendq_nr;
213
 
214
    /* Setup a transfer to get the ethernet address. */
215
    if (dep->de_16bit)
216
        outb_reg0(dep, DP_RBCR0, 6*2);
217
    else
218
        outb_reg0(dep, DP_RBCR0, 6);
219
    outb_reg0(dep, DP_RBCR1, 0);
220
    outb_reg0(dep, DP_RSAR0, 0);
221
    outb_reg0(dep, DP_RSAR1, 0);
222
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
223
 
224
    for (i= 0; i<6; i++)
225
    {
226
        if (dep->de_16bit)
227
        {
228
            word= inw_ne(dep, NE_DATA);
229
            dep->de_address.ea_addr[i]= word;
230
        }
231
        else
232
        {
233
            dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
234
        }
235
    }
236
    dep->de_data_port= dep->de_base_port + NE_DATA;
237
    if (dep->de_16bit)
238
    {
239
        dep->de_ramsize= NE2000_SIZE;
240
        dep->de_offset_page= NE2000_START / DP_PAGESIZE;
241
    }
242
    else
243
    {
244
        dep->de_ramsize= NE1000_SIZE;
245
        dep->de_offset_page= NE1000_START / DP_PAGESIZE;
246
    }
247
 
248
    /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
249
    sendq_nr= dep->de_ramsize / 0x2000;
250
    if (sendq_nr < 1)
251
        sendq_nr= 1;
252
    else if (sendq_nr > SENDQ_NR)
253
        sendq_nr= SENDQ_NR;
254
    dep->de_sendq_nr= sendq_nr;
255
    for (i= 0; i<sendq_nr; i++)
256
    {
257
        dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
258
            i*SENDQ_PAGES; 
259
    }
260
 
261
    dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
262
    dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
263
 
264
    /* Can't override the default IRQ. */
265
    dep->de_irq &= ~DEI_DEFAULT;
266
 
267
    if (!debug)
268
    {
269
        printf("%s: NE%d000 at %X:%d\n",
270
            dep->de_name, dep->de_16bit ? 2 : 1,
271
            dep->de_base_port, dep->de_irq);
272
    }
273
    else
274
    {
275
        printf("%s: Novell NE%d000 ethernet card at I/O address "
276
            "0x%X, memory size 0x%X, irq %d\n",
277
            dep->de_name, dep->de_16bit ? 2 : 1,
278
            dep->de_base_port, dep->de_ramsize, dep->de_irq);
279
    }
280
}
281
 
282
/*===========================================================================*
283
 *              test_8                       *
284
 *===========================================================================*/
285
static int test_8(dep, pos, pat)
286
dpeth_t *dep;
287
int pos;
288
u8_t *pat;
289
{
290
    u8_t buf[4];
291
    int i;
292
    int r;
293
 
294
    outb_reg0(dep, DP_ISR, 0xFF);
295
 
296
    /* Setup a transfer to put the pattern. */
297
    outb_reg0(dep, DP_RBCR0, 4);
298
    outb_reg0(dep, DP_RBCR1, 0);
299
    outb_reg0(dep, DP_RSAR0, pos & 0xFF);
300
    outb_reg0(dep, DP_RSAR1, pos >> 8);
301
    outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
302
 
303
    for (i= 0; i<4; i++)
304
        outb_ne(dep, NE_DATA, pat[i]);
305
 
306
    for (i= 0; i<N; i++)
307
    {
308
        if (inb_reg0(dep, DP_ISR) & ISR_RDC)
309
            break;
310
    }
311
    if (i == N)
312
    {
313
        if (debug)
314
        {
315
            printf("%s: NE1000 remote DMA test failed\n",
316
                dep->de_name);
317
        }
318
        return 0;
319
    }
320
 
321
    outb_reg0(dep, DP_RBCR0, 4);
322
    outb_reg0(dep, DP_RBCR1, 0);
323
    outb_reg0(dep, DP_RSAR0, pos & 0xFF);
324
    outb_reg0(dep, DP_RSAR1, pos >> 8);
325
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
326
 
327
    for (i= 0; i<4; i++)
328
        buf[i]= inb_ne(dep, NE_DATA);
329
 
330
    r= (memcmp(buf, pat, 4) == 0);
331
    return r;
332
}
333
 
334
/*===========================================================================*
335
 *              test_16                      *
336
 *===========================================================================*/
337
static int test_16(dep, pos, pat)
338
dpeth_t *dep;
339
int pos;
340
u8_t *pat;
341
{
342
    u8_t buf[4];
343
    int i;
344
    int r;
345
 
346
    outb_reg0(dep, DP_ISR, 0xFF);
347
 
348
    /* Setup a transfer to put the pattern. */
349
    outb_reg0(dep, DP_RBCR0, 4);
350
    outb_reg0(dep, DP_RBCR1, 0);
351
    outb_reg0(dep, DP_RSAR0, pos & 0xFF);
352
    outb_reg0(dep, DP_RSAR1, pos >> 8);
353
    outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
354
 
355
    for (i= 0; i<4; i += 2)
356
    {
357
        outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
358
    }
359
 
360
    for (i= 0; i<N; i++)
361
    {
362
        if (inb_reg0(dep, DP_ISR) & ISR_RDC)
363
            break;
364
    }
365
    if (i == N)
366
    {
367
        if (debug)
368
        {
369
            printf("%s: NE2000 remote DMA test failed\n",
370
                dep->de_name);
371
        }
372
        return 0;
373
    }
374
 
375
    outb_reg0(dep, DP_RBCR0, 4);
376
    outb_reg0(dep, DP_RBCR1, 0);
377
    outb_reg0(dep, DP_RSAR0, pos & 0xFF);
378
    outb_reg0(dep, DP_RSAR1, pos >> 8);
379
    outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
380
 
381
    for (i= 0; i<4; i += 2)
382
    {
383
        *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
384
    }
385
 
386
    r= (memcmp(buf, pat, 4) == 0);
387
    return r;
388
}
389
 
390
/*===========================================================================*
391
 *              ne_stop                      *
392
 *===========================================================================*/
393
static void ne_stop(dep)
394
dpeth_t *dep;
395
{
396
    int byte;
397
 
398
    /* Reset the ethernet card */
399
    byte= inb_ne(dep, NE_RESET);
400
    milli_delay(2);
401
    outb_ne(dep, NE_RESET, byte);
402
}
403
/*
404
static void milli_delay(unsigned long millis)
405
{
406
    tickdelay(MILLIS_TO_TICKS(millis));
407
}
408
*/
409
#endif /* ENABLE_NE2000 */
410
 
411
/*
412
 * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $
413
 */
414
 
415
/** @}
416
 */