Subversion Repositories HelenOS

Rev

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