1 /* $NetBSD: le_poll.c,v 1.4 2001/11/08 21:40:25 scw Exp $ */
4 * Copyright (c) 1993 Adam Glass
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Adam Glass.
18 * 4. The name of the Author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 struct lereg1
*sc_r1
; /* LANCE registers */
39 struct lereg2
*sc_r2
; /* RAM */
44 static void le_error(const char *, struct lereg1
*);
45 static void le_reset(u_char
*);
46 static int le_poll(void *, int);
49 le_error(const char *str
, struct lereg1
*ler1
)
52 /* ler1->ler1_rap = LE_CSRO done in caller */
53 if (ler1
->ler1_rdp
& LE_C0_BABL
) {
54 printf("le0: been babbling, found by '%s'\n", str
);
57 if (ler1
->ler1_rdp
& LE_C0_CERR
) {
58 ler1
->ler1_rdp
= LE_C0_CERR
;
60 if (ler1
->ler1_rdp
& LE_C0_MISS
) {
61 ler1
->ler1_rdp
= LE_C0_MISS
;
63 if (ler1
->ler1_rdp
& LE_C0_MERR
) {
64 printf("le0: memory error in '%s'\n", str
);
70 le_reset(u_char
*myea
)
72 struct lereg1
*ler1
= le_softc
.sc_r1
;
73 struct lereg2
*ler2
= le_softc
.sc_r2
;
75 int timo
= 100000, stat
= 0, i
;
77 ler1
->ler1_rap
= LE_CSR0
;
78 ler1
->ler1_rdp
= LE_C0_STOP
; /* do nothing until we are finished */
80 memset(ler2
, 0, sizeof(*ler2
));
82 ler2
->ler2_mode
= LE_MODE_NORMAL
;
83 ler2
->ler2_padr
[0] = myea
[1];
84 ler2
->ler2_padr
[1] = myea
[0];
85 ler2
->ler2_padr
[2] = myea
[3];
86 ler2
->ler2_padr
[3] = myea
[2];
87 ler2
->ler2_padr
[4] = myea
[5];
88 ler2
->ler2_padr
[5] = myea
[4];
91 ler2
->ler2_ladrf0
= 0;
92 ler2
->ler2_ladrf1
= 0;
94 a
= (u_int
)ler2
->ler2_rmd
;
95 ler2
->ler2_rlen
= LE_RLEN
| (a
>> 16);
96 ler2
->ler2_rdra
= a
& LE_ADDR_LOW_MASK
;
98 a
= (u_int
)ler2
->ler2_tmd
;
99 ler2
->ler2_tlen
= LE_TLEN
| (a
>> 16);
100 ler2
->ler2_tdra
= a
& LE_ADDR_LOW_MASK
;
102 ler1
->ler1_rap
= LE_CSR1
;
104 ler1
->ler1_rdp
= a
& LE_ADDR_LOW_MASK
;
105 ler1
->ler1_rap
= LE_CSR2
;
106 ler1
->ler1_rdp
= a
>> 16;
108 for (i
= 0; i
< LERBUF
; i
++) {
109 a
= (u_int
)&ler2
->ler2_rbuf
[i
];
110 ler2
->ler2_rmd
[i
].rmd0
= a
& LE_ADDR_LOW_MASK
;
111 ler2
->ler2_rmd
[i
].rmd1_bits
= LE_R1_OWN
;
112 ler2
->ler2_rmd
[i
].rmd1_hadr
= a
>> 16;
113 ler2
->ler2_rmd
[i
].rmd2
= -LEMTU
;
114 ler2
->ler2_rmd
[i
].rmd3
= 0;
116 for (i
= 0; i
< LETBUF
; i
++) {
117 a
= (u_int
)&ler2
->ler2_tbuf
[i
];
118 ler2
->ler2_tmd
[i
].tmd0
= a
& LE_ADDR_LOW_MASK
;
119 ler2
->ler2_tmd
[i
].tmd1_bits
= 0;
120 ler2
->ler2_tmd
[i
].tmd1_hadr
= a
>> 16;
121 ler2
->ler2_tmd
[i
].tmd2
= 0;
122 ler2
->ler2_tmd
[i
].tmd3
= 0;
125 ler1
->ler1_rap
= LE_CSR3
;
126 ler1
->ler1_rdp
= LE_C3_BSWP
;
128 ler1
->ler1_rap
= LE_CSR0
;
129 ler1
->ler1_rdp
= LE_C0_INIT
;
132 printf("le0: init timeout, stat = 0x%x\n", stat
);
135 stat
= ler1
->ler1_rdp
;
136 } while ((stat
& LE_C0_IDON
) == 0);
138 ler1
->ler1_rdp
= LE_C0_IDON
;
139 le_softc
.next_rmd
= 0;
140 le_softc
.next_tmd
= 0;
141 ler1
->ler1_rap
= LE_CSR0
;
142 ler1
->ler1_rdp
= LE_C0_STRT
;
146 le_poll(void *pkt
, int len
)
148 struct lereg1
*ler1
= le_softc
.sc_r1
;
149 struct lereg2
*ler2
= le_softc
.sc_r2
;
154 ler1
->ler1_rap
= LE_CSR0
;
155 if ((ler1
->ler1_rdp
& LE_C0_RINT
) != 0)
156 ler1
->ler1_rdp
= LE_C0_RINT
;
157 rmd
= &ler2
->ler2_rmd
[le_softc
.next_rmd
];
158 if (rmd
->rmd1_bits
& LE_R1_OWN
) {
161 if (ler1
->ler1_rdp
& LE_C0_ERR
)
162 le_error("le_poll", ler1
);
163 if (rmd
->rmd1_bits
& LE_R1_ERR
) {
164 printf("le0_poll: rmd status 0x%x\n", rmd
->rmd1_bits
);
168 if ((rmd
->rmd1_bits
& (LE_R1_STP
|LE_R1_ENP
)) != (LE_R1_STP
|LE_R1_ENP
)) {
169 printf("le_poll: chained packet\n");
174 if (length
>= LEMTU
) {
176 printf("csr0 when bad things happen: %x\n", ler1
->ler1_rdp
);
184 memcpy(pkt
, (char *)&ler2
->ler2_rbuf
[le_softc
.next_rmd
],
188 a
= (u_int
)&ler2
->ler2_rbuf
[le_softc
.next_rmd
];
189 rmd
->rmd0
= a
& LE_ADDR_LOW_MASK
;
190 rmd
->rmd1_hadr
= a
>> 16;
193 (le_softc
.next_rmd
== (LERBUF
- 1)) ? 0 : (le_softc
.next_rmd
+ 1);
194 rmd
->rmd1_bits
= LE_R1_OWN
;
198 int le_put(u_char
*pkt
, size_t len
)
200 struct lereg1
*ler1
= le_softc
.sc_r1
;
201 struct lereg2
*ler2
= le_softc
.sc_r2
;
203 int timo
= 100000, stat
= 0;
206 ler1
->ler1_rap
= LE_CSR0
;
207 if (ler1
->ler1_rdp
& LE_C0_ERR
)
208 le_error("le_put(way before xmit)", ler1
);
209 tmd
= &ler2
->ler2_tmd
[le_softc
.next_tmd
];
210 while (tmd
->tmd1_bits
& LE_T1_OWN
) {
211 printf("le0: output buffer busy\n");
213 memcpy((char *)ler2
->ler2_tbuf
[le_softc
.next_tmd
], pkt
, len
);
219 if (ler1
->ler1_rdp
& LE_C0_ERR
)
220 le_error("le_put(before xmit)", ler1
);
221 tmd
->tmd1_bits
= LE_T1_STP
| LE_T1_ENP
| LE_T1_OWN
;
222 a
= (u_int
)&ler2
->ler2_tbuf
[le_softc
.next_tmd
];
223 tmd
->tmd0
= a
& LE_ADDR_LOW_MASK
;
224 tmd
->tmd1_hadr
= a
>> 16;
225 ler1
->ler1_rdp
= LE_C0_TDMD
;
226 if (ler1
->ler1_rdp
& LE_C0_ERR
)
227 le_error("le_put(after xmit)", ler1
);
230 printf("le0: transmit timeout, stat = 0x%x\n",
232 if (ler1
->ler1_rdp
& LE_C0_ERR
)
233 le_error("le_put(timeout)", ler1
);
236 stat
= ler1
->ler1_rdp
;
237 } while ((stat
& LE_C0_TINT
) == 0);
238 ler1
->ler1_rdp
= LE_C0_TINT
;
239 if (ler1
->ler1_rdp
& LE_C0_ERR
) {
240 if ((ler1
->ler1_rdp
&
241 (LE_C0_BABL
|LE_C0_CERR
|LE_C0_MISS
|LE_C0_MERR
)) !=
243 printf("le_put: xmit error, buf %d\n",
245 le_error("le_put(xmit error)", ler1
);
247 le_softc
.next_tmd
= 0;
249 (le_softc
.next_tmd
== (LETBUF
- 1)) ? 0 : le_softc
.next_tmd
+ 1;
251 if (tmd
->tmd1_bits
& LE_T1_ERR
) {
252 printf("le0: transmit error, error = 0x%x\n",
259 int le_get(u_char
*pkt
, size_t len
, u_long timeout
)
263 int stopat
= time() + timeout
;
267 while ((now
= time()) < stopat
&& !cc
) {
268 cc
= le_poll(pkt
, len
);
271 printf("%d \r", stopat
- now
);
275 if (cc
&& (pkt
[0] != myea
[0] || pkt
[1] != myea
[1] ||
276 pkt
[2] != myea
[2] || pkt
[3] != myea
[3] ||
277 pkt
[4] != myea
[4] || pkt
[5] != myea
[5])) {
278 cc
= 0; /* ignore broadcast / multicast */
280 printf("reject (%d sec left)\n", stopat
- now
);
292 int *ea
= (int *)LANCE_ADDR
;
293 u_long
*eram
= (u_long
*)ERAM_ADDR
;
296 if ((e
& 0x2fffff00) == 0x2fffff00) {
297 printf("ERROR: ethernet address not set! Use LSAD.\n");
309 printf("le0: ethernet address: %x:%x:%x:%x:%x:%x\n",
310 myea
[0], myea
[1], myea
[2], myea
[3], myea
[4], myea
[5]);
311 memset(&le_softc
, 0, sizeof(le_softc
));
312 le_softc
.sc_r1
= (struct lereg1
*)LANCE_REG_ADDR
;
313 le_softc
.sc_r2
= (struct lereg2
*)(*eram
- (1024*1024));
319 struct lereg1
*ler1
= le_softc
.sc_r1
;
321 ler1
->ler1_rap
= LE_CSR0
;
322 ler1
->ler1_rdp
= LE_C0_STOP
;