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