1 /* $NetBSD: if_le_vme.c,v 1.26 2009/07/08 12:23:10 tsutsui Exp $ */
4 * Copyright (c) 1998 maximum entropy. All rights reserved.
5 * Copyright (c) 1997 Leo Weppelman. All rights reserved.
6 * Copyright (c) 1992, 1993
7 * The Regents of the University of California. All rights reserved.
9 * This code is derived from software contributed to Berkeley by
10 * Ralph Campbell and Rick Macklem.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
40 * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
42 * This code is derived from software contributed to Berkeley by
43 * Ralph Campbell and Rick Macklem.
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by the University of
56 * California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
76 #include <sys/cdefs.h>
77 __KERNEL_RCSID(0, "$NetBSD: if_le_vme.c,v 1.26 2009/07/08 12:23:10 tsutsui Exp $");
82 #include <sys/param.h>
83 #include <sys/systm.h>
85 #include <sys/syslog.h>
86 #include <sys/socket.h>
87 #include <sys/device.h>
90 #include <net/if_media.h>
91 #include <net/if_ether.h>
94 #include <netinet/in.h>
95 #include <netinet/if_inarp.h>
98 #include <machine/cpu.h>
99 #include <machine/bus.h>
100 #include <machine/iomap.h>
101 #include <machine/scu.h>
102 #include <machine/intr.h>
104 #include <atari/atari/device.h>
106 #include <dev/ic/lancereg.h>
107 #include <dev/ic/lancevar.h>
108 #include <dev/ic/am7990reg.h>
109 #include <dev/ic/am7990var.h>
111 #include <atari/vme/vmevar.h>
112 #include <atari/vme/if_levar.h>
115 * All cards except BVME410 have 64KB RAM. However.... On the Riebl cards the
116 * area between the offsets 0xee70-0xeec0 is used to store config data.
118 struct le_addresses
{
126 { 0xfe00fff0, 0xfe010000, IRQUNK
, 16, 64*1024,
127 LE_OLD_RIEBL
|LE_NEW_RIEBL
}, /* Riebl */
128 { 0xffcffff0, 0xffcf0000, 5, 16, 64*1024,
130 { 0xfecffff0, 0xfecf0000, 5, 16, 64*1024,
131 LE_ROTHRON
}, /* Rhotron */
132 { 0xfeff4100, 0xfe000000, 4, 8, VMECF_MEMSIZ_DEFAULT
,
133 LE_BVME410
} /* BVME410 */
136 #define NLESTD __arraycount(lestd)
139 * Default mac for RIEBL cards without a (working) battery. The first 4 bytes
140 * are the manufacturer id.
142 static u_char riebl_def_mac
[] = {
143 0x00, 0x00, 0x36, 0x04, 0x00, 0x00
146 static int le_intr(struct le_softc
*, int);
147 static void lepseudointr(struct le_softc
*, void *);
148 static int le_vme_match(device_t
, cfdata_t
, void *);
149 static void le_vme_attach(device_t
, device_t
, void *);
150 static int probe_addresses(bus_space_tag_t
*, bus_space_tag_t
*,
151 bus_space_handle_t
*, bus_space_handle_t
*);
152 static void riebl_skip_reserved_area(struct lance_softc
*);
153 static int nm93c06_read(bus_space_tag_t
, bus_space_handle_t
, int);
154 static int bvme410_probe(bus_space_tag_t
, bus_space_handle_t
);
155 static int bvme410_mem_size(bus_space_tag_t
, u_long
);
156 static void bvme410_copytobuf(struct lance_softc
*, void *, int, int);
157 static void bvme410_zerobuf(struct lance_softc
*, int, int);
159 CFATTACH_DECL_NEW(le_vme
, sizeof(struct le_softc
),
160 le_vme_match
, le_vme_attach
, NULL
, NULL
);
162 #if defined(_KERNEL_OPT)
170 #define integrate static inline
174 hide
void lewrcsr(struct lance_softc
*, uint16_t, uint16_t);
175 hide
uint16_t lerdcsr(struct lance_softc
*, uint16_t);
178 lewrcsr(struct lance_softc
*sc
, uint16_t port
, uint16_t val
)
180 struct le_softc
*lesc
= (struct le_softc
*)sc
;
184 bus_space_write_2(lesc
->sc_iot
, lesc
->sc_ioh
, LER_RAP
, port
);
185 bus_space_write_2(lesc
->sc_iot
, lesc
->sc_ioh
, LER_RDP
, val
);
190 lerdcsr(struct lance_softc
*sc
, uint16_t port
)
192 struct le_softc
*lesc
= (struct le_softc
*)sc
;
197 bus_space_write_2(lesc
->sc_iot
, lesc
->sc_ioh
, LER_RAP
, port
);
198 val
= bus_space_read_2(lesc
->sc_iot
, lesc
->sc_ioh
, LER_RDP
);
205 le_vme_match(device_t parent
, cfdata_t cfp
, void *aux
)
207 struct vme_attach_args
*va
= aux
;
210 bus_space_tag_t memt
;
211 bus_space_handle_t ioh
;
212 bus_space_handle_t memh
;
217 for (i
= 0; i
< NLESTD
; i
++) {
218 struct le_addresses
*le_ap
= &lestd
[i
];
221 if ((va
->va_iobase
!= IOBASEUNK
)
222 && (va
->va_iobase
!= le_ap
->reg_addr
))
225 if ((va
->va_maddr
!= MADDRUNK
)
226 && (va
->va_maddr
!= le_ap
->mem_addr
))
229 if ((le_ap
->irq
!= IRQUNK
) && (va
->va_irq
!= le_ap
->irq
))
232 if (bus_space_map(iot
, le_ap
->reg_addr
, le_ap
->reg_size
, 0, &ioh
)) {
233 aprint_error("leprobe: cannot map io-area\n");
236 if (le_ap
->mem_size
== VMECF_MEMSIZ_DEFAULT
) {
237 if (bvme410_probe(iot
, ioh
)) {
238 bus_space_write_2(iot
, ioh
, BVME410_BAR
, 0x1); /* XXX */
239 le_ap
->mem_size
= bvme410_mem_size(memt
, le_ap
->mem_addr
);
242 if (le_ap
->mem_size
== VMECF_MEMSIZ_DEFAULT
) {
243 bus_space_unmap(iot
, ioh
, le_ap
->reg_size
);
247 if (bus_space_map(memt
, le_ap
->mem_addr
, le_ap
->mem_size
, 0, &memh
)) {
248 bus_space_unmap(iot
, ioh
, le_ap
->reg_size
);
249 aprint_error("leprobe: cannot map memory-area\n");
252 found
= probe_addresses(&iot
, &memt
, &ioh
, &memh
);
253 bus_space_unmap(iot
, ioh
, le_ap
->reg_size
);
254 bus_space_unmap(memt
, memh
, le_ap
->mem_size
);
257 va
->va_iobase
= le_ap
->reg_addr
;
258 va
->va_iosize
= le_ap
->reg_size
;
259 va
->va_maddr
= le_ap
->mem_addr
;
260 va
->va_msize
= le_ap
->mem_size
;
262 if (va
->va_irq
== IRQUNK
)
263 va
->va_irq
= le_ap
->irq
;
271 probe_addresses(bus_space_tag_t
*iot
, bus_space_tag_t
*memt
,
272 bus_space_handle_t
*ioh
, bus_space_handle_t
*memh
)
276 * Test accesibility of register and memory area
278 if (!bus_space_peek_2(*iot
, *ioh
, LER_RDP
))
280 if (!bus_space_peek_1(*memt
, *memh
, 0))
284 * Test for writable memory
286 bus_space_write_2(*memt
, *memh
, 0, 0xa5a5);
287 if (bus_space_read_2(*memt
, *memh
, 0) != 0xa5a5)
291 * Test writability of selector port.
293 bus_space_write_2(*iot
, *ioh
, LER_RAP
, LE_CSR1
);
294 if (bus_space_read_2(*iot
, *ioh
, LER_RAP
) != LE_CSR1
)
298 * Do a small register test
300 bus_space_write_2(*iot
, *ioh
, LER_RAP
, LE_CSR0
);
301 bus_space_write_2(*iot
, *ioh
, LER_RDP
, LE_C0_INIT
| LE_C0_STOP
);
302 if (bus_space_read_2(*iot
, *ioh
, LER_RDP
) != LE_C0_STOP
)
305 bus_space_write_2(*iot
, *ioh
, LER_RDP
, LE_C0_STOP
);
306 if (bus_space_read_2(*iot
, *ioh
, LER_RDP
) != LE_C0_STOP
)
313 * Interrupt mess. Because the card's interrupt is hardwired to either
314 * ipl5 or ipl3 (mostly on ipl5) and raising splnet to spl5() just won't do
315 * (it kills the serial at the least), we use a 2-level interrupt scheme. The
316 * card interrupt is routed to 'le_intr'. If the previous ipl was below
317 * splnet, just call the mi-function. If not, save the interrupt status,
318 * turn off card interrupts (the card is *very* persistent) and arrange
319 * for a softint 'callback' through 'lepseudointr'.
322 le_intr(struct le_softc
*lesc
, int sr
)
324 struct lance_softc
*sc
= &lesc
->sc_am7990
.lsc
;
327 if ((sr
& PSL_IPL
) < (ipl2psl_table
[IPL_NET
] & PSL_IPL
))
330 sc
->sc_saved_csr0
= csr0
= lerdcsr(sc
, LE_CSR0
);
331 lewrcsr(sc
, LE_CSR0
, csr0
& ~LE_C0_INEA
);
332 add_sicallback((si_farg
)lepseudointr
, lesc
, sc
);
339 lepseudointr(struct le_softc
*lesc
, void *sc
)
343 s
= splx(lesc
->sc_splval
);
349 le_vme_attach(device_t parent
, device_t self
, void *aux
)
351 struct le_softc
*lesc
= device_private(self
);
352 struct lance_softc
*sc
= &lesc
->sc_am7990
.lsc
;
353 struct vme_attach_args
*va
= aux
;
354 bus_space_handle_t ioh
;
355 bus_space_handle_t memh
;
356 struct le_addresses
*le_ap
;
360 aprint_normal("\n%s: ", device_xname(self
));
362 if (bus_space_map(va
->va_iot
, va
->va_iobase
, va
->va_iosize
, 0, &ioh
))
363 panic("leattach: cannot map io-area");
364 if (bus_space_map(va
->va_memt
, va
->va_maddr
, va
->va_msize
, 0, &memh
))
365 panic("leattach: cannot map mem-area");
367 lesc
->sc_iot
= va
->va_iot
;
369 lesc
->sc_memt
= va
->va_memt
;
370 lesc
->sc_memh
= memh
;
371 lesc
->sc_splval
= (va
->va_irq
<< 8) | PSL_S
; /* XXX */
372 le_ap
= (struct le_addresses
*)va
->va_aux
;
375 * Go on to find board type
377 if ((le_ap
->type_hint
& LE_PAM
)
378 && bus_space_peek_1(va
->va_iot
, ioh
, LER_EEPROM
)) {
379 aprint_normal("PAM card");
380 lesc
->sc_type
= LE_PAM
;
381 bus_space_read_1(va
->va_iot
, ioh
, LER_MEME
);
383 else if((le_ap
->type_hint
& LE_BVME410
)
384 && bvme410_probe(va
->va_iot
, ioh
)) {
385 aprint_normal("BVME410");
386 lesc
->sc_type
= LE_BVME410
;
388 else if (le_ap
->type_hint
& (LE_NEW_RIEBL
|LE_OLD_RIEBL
)) {
389 aprint_normal("Riebl card");
390 if(bus_space_read_4(va
->va_memt
, memh
, RIEBL_MAGIC_ADDR
)
392 lesc
->sc_type
= LE_NEW_RIEBL
;
394 aprint_normal("(without battery) ");
395 lesc
->sc_type
= LE_OLD_RIEBL
;
399 aprint_error("le_vme_attach: Unsupported card!");
401 switch (lesc
->sc_type
) {
403 sc
->sc_copytodesc
= bvme410_copytobuf
;
404 sc
->sc_copyfromdesc
= lance_copyfrombuf_contig
;
405 sc
->sc_copytobuf
= bvme410_copytobuf
;
406 sc
->sc_copyfrombuf
= lance_copyfrombuf_contig
;
407 sc
->sc_zerobuf
= bvme410_zerobuf
;
410 sc
->sc_copytodesc
= lance_copytobuf_contig
;
411 sc
->sc_copyfromdesc
= lance_copyfrombuf_contig
;
412 sc
->sc_copytobuf
= lance_copytobuf_contig
;
413 sc
->sc_copyfrombuf
= lance_copyfrombuf_contig
;
414 sc
->sc_zerobuf
= lance_zerobuf_contig
;
418 sc
->sc_rdcsr
= lerdcsr
;
419 sc
->sc_wrcsr
= lewrcsr
;
420 sc
->sc_hwinit
= NULL
;
421 sc
->sc_conf3
= LE_C3_BSWP
;
423 sc
->sc_memsize
= va
->va_msize
;
424 sc
->sc_mem
= (void *)memh
; /* XXX */
429 switch (lesc
->sc_type
) {
431 memcpy(sc
->sc_enaddr
, riebl_def_mac
,
432 sizeof(sc
->sc_enaddr
));
435 for (i
= 0; i
< sizeof(sc
->sc_enaddr
); i
++)
437 bus_space_read_1(va
->va_memt
, memh
, i
+ RIEBL_MAC_ADDR
);
440 i
= bus_space_read_1(va
->va_iot
, ioh
, LER_EEPROM
);
441 for (i
= 0; i
< sizeof(sc
->sc_enaddr
); i
++) {
443 (bus_space_read_2(va
->va_memt
, memh
, 2 * i
) << 4) |
444 (bus_space_read_2(va
->va_memt
, memh
, 2 * i
+ 1) & 0xf);
446 i
= bus_space_read_1(va
->va_iot
, ioh
, LER_MEME
);
449 for (i
= 0; i
< (sizeof(sc
->sc_enaddr
) >> 1); i
++) {
452 tmp
= nm93c06_read(va
->va_iot
, ioh
, i
);
453 sc
->sc_enaddr
[2 * i
] = (tmp
>> 8) & 0xff;
454 sc
->sc_enaddr
[2 * i
+ 1] = tmp
& 0xff;
456 bus_space_write_2(va
->va_iot
, ioh
, BVME410_BAR
, 0x1); /* XXX */
459 am7990_config(&lesc
->sc_am7990
);
461 if ((lesc
->sc_type
== LE_OLD_RIEBL
) || (lesc
->sc_type
== LE_NEW_RIEBL
))
462 riebl_skip_reserved_area(sc
);
465 * XXX: We always use uservector 64....
467 if ((lesc
->sc_intr
= intr_establish(64, USER_VEC
, 0,
468 (hw_ifun_t
)le_intr
, lesc
)) == NULL
) {
469 aprint_error("le_vme_attach: Can't establish interrupt\n");
474 * Notify the card of the vector
476 switch (lesc
->sc_type
) {
479 bus_space_write_2(va
->va_memt
, memh
, RIEBL_IVEC_ADDR
,
483 bus_space_write_1(va
->va_iot
, ioh
, LER_IVEC
, 64 + 64);
486 bus_space_write_2(va
->va_iot
, ioh
, BVME410_IVEC
, 64 + 64);
491 * Unmask the VME-interrupt we're on
493 if (machineid
& ATARI_TT
)
494 SCU
->vme_mask
|= 1 << va
->va_irq
;
498 * True if 'addr' containe within [start,len]
500 #define WITHIN(start, len, addr) \
501 ((addr >= start) && ((addr) <= ((start) + (len))))
503 riebl_skip_reserved_area(struct lance_softc
*sc
)
508 for(i
= 0; i
< sc
->sc_nrbuf
; i
++) {
509 if (WITHIN(sc
->sc_rbufaddr
[i
], LEBLEN
, RIEBL_RES_START
)
510 || WITHIN(sc
->sc_rbufaddr
[i
], LEBLEN
, RIEBL_RES_END
)) {
511 offset
= RIEBL_RES_END
- sc
->sc_rbufaddr
[i
];
513 sc
->sc_rbufaddr
[i
] += offset
;
516 for(i
= 0; i
< sc
->sc_ntbuf
; i
++) {
517 if (WITHIN(sc
->sc_tbufaddr
[i
], LEBLEN
, RIEBL_RES_START
)
518 || WITHIN(sc
->sc_tbufaddr
[i
], LEBLEN
, RIEBL_RES_END
)) {
519 offset
= RIEBL_RES_END
- sc
->sc_tbufaddr
[i
];
521 sc
->sc_tbufaddr
[i
] += offset
;
526 nm93c06_read(bus_space_tag_t iot
, bus_space_handle_t ioh
, int nm93c06reg
)
530 int bits
= 0x180 | (nm93c06reg
& 0xf);
533 bar
= 1 << BVME410_CS_SHIFT
;
534 bus_space_write_2(iot
, ioh
, BVME410_BAR
, bar
);
535 delay(1); /* tCSS = 1 us */
536 for (shift
= 9; shift
>= 0; shift
--) {
537 if (((bits
>> shift
) & 1) == 1)
538 bar
|= 1 << BVME410_DIN_SHIFT
;
540 bar
&= ~(1 << BVME410_DIN_SHIFT
);
541 bus_space_write_2(iot
, ioh
, BVME410_BAR
, bar
);
542 delay(1); /* tDIS = 0.4 us */
543 bar
|= 1 << BVME410_CLK_SHIFT
;
544 bus_space_write_2(iot
, ioh
, BVME410_BAR
, bar
);
545 delay(2); /* tSKH = 1 us, tSKH + tSKL >= 4 us */
546 bar
&= ~(1 << BVME410_CLK_SHIFT
);
547 bus_space_write_2(iot
, ioh
, BVME410_BAR
, bar
);
548 delay(2); /* tSKL = 1 us, tSKH + tSKL >= 4 us */
550 bar
&= ~(1 << BVME410_DIN_SHIFT
);
551 for (shift
= 15; shift
>= 0; shift
--) {
552 delay(1); /* tDIS = 100 ns, BVM manual says 0.4 us */
553 bar
|= 1 << BVME410_CLK_SHIFT
;
554 bus_space_write_2(iot
, ioh
, BVME410_BAR
, bar
);
555 delay(2); /* tSKH = 1 us, tSKH + tSKL >= 4 us */
556 data
|= (bus_space_read_2(iot
, ioh
, BVME410_BAR
) & 1) << shift
;
557 bar
&= ~(1 << BVME410_CLK_SHIFT
);
558 bus_space_write_2(iot
, ioh
, BVME410_BAR
, bar
);
559 delay(2); /* tSKL = 1 us, tSKH + tSKL >= 4 us */
561 bar
&= ~(1 << BVME410_CS_SHIFT
);
562 bus_space_write_2(iot
, ioh
, BVME410_BAR
, bar
);
563 delay(1); /* tCS = 1 us */
568 bvme410_probe(bus_space_tag_t iot
, bus_space_handle_t ioh
)
571 if (!bus_space_peek_2(iot
, ioh
, BVME410_IVEC
))
574 bus_space_write_2(iot
, ioh
, BVME410_IVEC
, 0x0000);
575 if (bus_space_read_2(iot
, ioh
, BVME410_IVEC
) != 0xff00)
578 bus_space_write_2(iot
, ioh
, BVME410_IVEC
, 0xffff);
579 if (bus_space_read_2(iot
, ioh
, BVME410_IVEC
) != 0xffff)
582 bus_space_write_2(iot
, ioh
, BVME410_IVEC
, 0xa5a5);
583 if (bus_space_read_2(iot
, ioh
, BVME410_IVEC
) != 0xffa5)
590 bvme410_mem_size(bus_space_tag_t memt
, u_long mem_addr
)
592 bus_space_handle_t memh
;
595 if (bus_space_map(memt
, mem_addr
, 256 * 1024, 0, &memh
))
596 return VMECF_MEMSIZ_DEFAULT
;
597 if (!bus_space_peek_1(memt
, memh
, 0)) {
598 bus_space_unmap(memt
, memh
, 256 * 1024);
599 return VMECF_MEMSIZ_DEFAULT
;
601 bus_space_write_1(memt
, memh
, 0, 128);
602 bus_space_write_1(memt
, memh
, 64 * 1024, 32);
603 bus_space_write_1(memt
, memh
, 32 * 1024, 8);
604 r
= (int)(bus_space_read_1(memt
, memh
, 0) * 2048);
605 bus_space_unmap(memt
, memh
, 256 * 1024);
610 * Need to be careful when writing to the bvme410 dual port memory.
611 * Continue writing each byte until it reads back the same.
615 bvme410_copytobuf(struct lance_softc
*sc
, void *from
, int boff
, int len
)
617 volatile char *buf
= (volatile char *)sc
->sc_mem
;
618 char *f
= (char *)from
;
620 for (buf
+= boff
; len
; buf
++,f
++,len
--)
623 } while (*buf
!= *f
);
627 bvme410_zerobuf(struct lance_softc
*sc
, int boff
, int len
)
629 volatile char *buf
= (volatile char *)sc
->sc_mem
;
631 for (buf
+= boff
; len
; buf
++,len
--)
634 } while (*buf
!= '\0');