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