source: trunk/minix/drivers/dp8390/ne2000.c@ 22

Last change on this file since 22 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

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