mkfs: move directory entry manipulation
[minix.git] / drivers / dp8390 / ne2000.c
blobf6d47d4c8504ce17c8697f5561f84d7206e9df2d
1 /*
2 ne2000.c
4 Driver for the ne2000 ethernet cards. This file contains only the ne2000
5 specific code, the rest is in dp8390.c
7 Created: March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
8 */
10 #include <minix/drivers.h>
12 #include <net/gen/ether.h>
13 #include <net/gen/eth_io.h>
14 #if __minix_vmd
15 #include "config.h"
16 #endif
18 #include "local.h"
19 #include "dp8390.h"
20 #include "ne2000.h"
22 #if ENABLE_NE2000
24 #define N 100
26 extern u32_t system_hz;
28 #define MILLIS_TO_TICKS(m) (((m)*system_hz/1000)+1)
30 typedef int(*testf_t) (dpeth_t *dep, int pos, u8_t *pat);
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 };
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);
42 /*===========================================================================*
43 * ne_probe *
44 *===========================================================================*/
45 int ne_probe(dpeth_t *dep)
47 int byte;
48 int i;
49 int loc1, loc2;
50 testf_t f;
52 dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
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
60 for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
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);
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 */
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))
77 return 0;
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)
85 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
86 DCR_BMS);
88 else
90 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
91 DCR_BMS);
94 if (dep->de_16bit)
96 loc1= NE2000_START;
97 loc2= NE2000_START + NE2000_SIZE - 4;
98 f= test_16;
100 else
102 loc1= NE1000_START;
103 loc2= NE1000_START + NE1000_SIZE - 4;
104 f= test_8;
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))
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;
120 return 0;
123 /*===========================================================================*
124 * ne_init *
125 *===========================================================================*/
126 void ne_init(dep)
127 dpeth_t *dep;
129 int i;
130 int word, sendq_nr;
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);
142 for (i= 0; i<6; i++)
144 if (dep->de_16bit)
146 word= inw_ne(dep, NE_DATA);
147 dep->de_address.ea_addr[i]= word;
149 else
151 dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
154 dep->de_data_port= dep->de_base_port + NE_DATA;
155 if (dep->de_16bit)
157 dep->de_ramsize= NE2000_SIZE;
158 dep->de_offset_page= NE2000_START / DP_PAGESIZE;
160 else
162 dep->de_ramsize= NE1000_SIZE;
163 dep->de_offset_page= NE1000_START / DP_PAGESIZE;
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++)
175 dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
176 i*SENDQ_PAGES;
179 dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
180 dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
182 /* Can't override the default IRQ. */
183 dep->de_irq &= ~DEI_DEFAULT;
185 if (!debug)
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);
191 else
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);
200 /*===========================================================================*
201 * test_8 *
202 *===========================================================================*/
203 static int test_8(dep, pos, pat)
204 dpeth_t *dep;
205 int pos;
206 u8_t *pat;
208 u8_t buf[4];
209 int i;
210 int r;
212 outb_reg0(dep, DP_ISR, 0xFF);
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);
221 for (i= 0; i<4; i++)
222 outb_ne(dep, NE_DATA, pat[i]);
224 for (i= 0; i<N; i++)
226 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
227 break;
229 if (i == N)
231 if (debug)
233 printf("%s: NE1000 remote DMA test failed\n",
234 dep->de_name);
236 return 0;
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);
245 for (i= 0; i<4; i++)
246 buf[i]= inb_ne(dep, NE_DATA);
248 r= (memcmp(buf, pat, 4) == 0);
249 return r;
252 /*===========================================================================*
253 * test_16 *
254 *===========================================================================*/
255 static int test_16(dep, pos, pat)
256 dpeth_t *dep;
257 int pos;
258 u8_t *pat;
260 u8_t buf[4];
261 int i;
262 int r;
264 outb_reg0(dep, DP_ISR, 0xFF);
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);
273 for (i= 0; i<4; i += 2)
275 outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
278 for (i= 0; i<N; i++)
280 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
281 break;
283 if (i == N)
285 if (debug)
287 printf("%s: NE2000 remote DMA test failed\n",
288 dep->de_name);
290 return 0;
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);
299 for (i= 0; i<4; i += 2)
301 *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
304 r= (memcmp(buf, pat, 4) == 0);
305 return r;
308 /*===========================================================================*
309 * ne_stop *
310 *===========================================================================*/
311 static void ne_stop(dep)
312 dpeth_t *dep;
314 int byte;
316 /* Reset the ethernet card */
317 byte= inb_ne(dep, NE_RESET);
318 milli_delay(2);
319 outb_ne(dep, NE_RESET, byte);
322 static void milli_delay(unsigned long millis)
324 tickdelay(MILLIS_TO_TICKS(millis));
327 #endif /* ENABLE_NE2000 */
330 * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $