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