source: mainline/uspace/srv/net/netif/dp8390/ne2000.c@ 21580dd

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 21580dd was 21580dd, checked in by Lukas Mejdrech <lukas@…>, 15 years ago

Merged with network branch svn://svn.helenos.org/HelenOS/branches/network revision 4759; ipc_share_* and ipc_data_* changed to async_*; client connection in module.c returns on IPC_M_PHONE_HUNGUP; * Qemu scripts renamed to net-qe.*; (the dp8390 does not respond)

  • Property mode set to 100644
File size: 10.4 KB
Line 
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/*
41ne2000.c
42
43Driver for the ne2000 ethernet cards. This file contains only the ne2000
44specific code, the rest is in dp8390.c
45
46Created: 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 */
80u8_t pat0[]= { 0x00, 0x00, 0x00, 0x00 };
81
82/** Second data pattern.
83 */
84u8_t pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
85
86/** Third data pattern.
87 */
88u8_t pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
89
90/** Fourth data pattern.
91 */
92u8_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 */
101static 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 */
110static 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 */
115static 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 */
121void ne_init(struct dpeth *dep);
122
123/*===========================================================================*
124 * ne_probe *
125 *===========================================================================*/
126int ne_probe(dep)
127dpeth_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 *===========================================================================*/
208void ne_init(dep)
209dpeth_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 *===========================================================================*/
285static int test_8(dep, pos, pat)
286dpeth_t *dep;
287int pos;
288u8_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 *===========================================================================*/
337static int test_16(dep, pos, pat)
338dpeth_t *dep;
339int pos;
340u8_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 *===========================================================================*/
393static void ne_stop(dep)
394dpeth_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/*
404static 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 */
Note: See TracBrowser for help on using the repository browser.