Subversion Repositories HelenOS

Rev

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