~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to uspace/srv/net/netif/dp8390/ne2000.c

  • Committer: Pavel Rimsky
  • Date: 2010-02-20 20:54:53 UTC
  • mfrom: (292 head)
  • mto: This revision was merged to the branch mainline in revision 296.
  • Revision ID: pavel@pavel-laptop-20100220205453-70sim280j709dgp3
Synchronize with head.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 ported to HelenOS, Lukas Mejdrech
 
25
 */
 
26
 
 
27
/** @addtogroup ne2k
 
28
 *  @{
 
29
 */
 
30
 
 
31
/** @file
 
32
 *  NE1000 and NE2000 network interface initialization and probe functions implementation.
 
33
 */
 
34
 
 
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
/** Number of bytes to transfer.
 
64
 */
 
65
#define N 100
 
66
 
 
67
//#define MILLIS_TO_TICKS(m)  (((m)*HZ/1000)+1)
 
68
 
 
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
 */
 
76
_PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat)  );
 
77
 
 
78
/** First data pattern.
 
79
 */
 
80
u8_t    pat0[]= { 0x00, 0x00, 0x00, 0x00 };
 
81
 
 
82
/** Second data pattern.
 
83
 */
 
84
u8_t    pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
 
85
 
 
86
/** Third data pattern.
 
87
 */
 
88
u8_t    pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
 
89
 
 
90
/** Fourth data pattern.
 
91
 */
 
92
u8_t    pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
 
93
 
 
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);
 
116
//_PROTOTYPE( static void milli_delay, (unsigned long millis)           );
 
117
 
 
118
/** Initializes the NE2000 network interface.
 
119
 *  @param[in,out] dep The network interface structure.
 
120
 */
 
121
void ne_init(struct dpeth *dep);
 
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
 */