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