1 /* $NetBSD: lemac.c,v 1.35 2008/04/08 12:07:26 cegger Exp $ */
4 * Copyright (c) 1994, 1995, 1997 Matt Thomas <matt@3am-software.com>
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. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * DEC EtherWORKS 3 Ethernet Controllers
30 * Written by Matt Thomas
31 * BPF support code stolen directly from if_ec.c
33 * This driver supports the LEMAC DE203/204/205 cards.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: lemac.c,v 1.35 2008/04/08 12:07:26 cegger Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
45 #include <sys/protosw.h>
46 #include <sys/socket.h>
47 #include <sys/sockio.h>
48 #include <sys/errno.h>
49 #include <sys/malloc.h>
50 #include <sys/device.h>
56 #include <net/if_types.h>
57 #include <net/if_dl.h>
58 #include <net/route.h>
59 #include <net/if_ether.h>
60 #include <net/if_media.h>
63 #include <netinet/in.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/in_var.h>
66 #include <netinet/ip.h>
67 #include <netinet/if_inarp.h>
73 #include <dev/ic/lemacreg.h>
74 #include <dev/ic/lemacvar.h>
76 #include <i386/isa/decether.h>
79 #include <uvm/uvm_extern.h>
86 static void lemac_init(lemac_softc_t
*sc
);
87 static void lemac_ifstart(struct ifnet
*ifp
);
88 static void lemac_reset(lemac_softc_t
*sc
);
89 static void lemac_rne_intr(lemac_softc_t
*sc
);
90 static void lemac_tne_intr(lemac_softc_t
*sc
);
91 static void lemac_txd_intr(lemac_softc_t
*sc
, unsigned cs_value
);
92 static void lemac_rxd_intr(lemac_softc_t
*sc
, unsigned cs_value
);
93 static int lemac_read_eeprom(lemac_softc_t
*sc
);
94 static void lemac_init_adapmem(lemac_softc_t
*sc
);
96 static const u_int16_t lemac_allmulti_mctbl
[LEMAC_MCTBL_SIZE
/sizeof(u_int16_t
)] = {
97 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
98 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
99 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
100 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
101 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
102 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
103 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
104 0xFFFFU
, 0xFFFFU
, 0xFFFFU
, 0xFFFFU
,
108 * Some tuning/monitoring variables.
110 unsigned lemac_txmax
= 16;
118 * Handle CS_RXD (Receiver disabled) here.
120 * Check Free Memory Queue Count. If not equal to zero
121 * then just turn Receiver back on. If it is equal to
122 * zero then check to see if transmitter is disabled.
123 * Process transmit TXD loop once more. If all else
124 * fails then do software init (0xC0 to EEPROM Init)
125 * and rebuild Free Memory Queue.
128 sc
->sc_cntrs
.cntr_rxd_intrs
++;
131 * Re-enable Receiver.
134 cs_value
&= ~LEMAC_CS_RXD
;
135 LEMAC_OUTB(sc
, LEMAC_REG_CS
, cs_value
);
137 if (LEMAC_INB(sc
, LEMAC_REG_FMC
) > 0)
140 if (cs_value
& LEMAC_CS_TXD
)
141 lemac_txd_intr(sc
, cs_value
);
143 if ((LEMAC_INB(sc
, LEMAC_REG_CS
) & LEMAC_CS_RXD
) == 0)
146 printf("%s: fatal RXD error, attempting recovery\n", sc
->sc_if
.if_xname
);
149 if (sc
->sc_if
.if_flags
& IFF_UP
) {
155 * Error during initialization. Mark card as disabled.
157 printf("%s: recovery failed -- board disabled\n", sc
->sc_if
.if_xname
);
164 unsigned txcount
= LEMAC_INB(sc
, LEMAC_REG_TDC
);
166 sc
->sc_cntrs
.cntr_tne_intrs
++;
167 while (txcount
-- > 0) {
168 unsigned txsts
= LEMAC_INB(sc
, LEMAC_REG_TDQ
);
169 sc
->sc_if
.if_opackets
++; /* another one done */
170 if ((txsts
& (LEMAC_TDQ_LCL
|LEMAC_TDQ_NCL
))
171 || (txsts
& LEMAC_TDQ_COL
) == LEMAC_TDQ_EXCCOL
) {
172 if (txsts
& LEMAC_TDQ_NCL
)
173 sc
->sc_flags
&= ~LEMAC_LINKUP
;
174 sc
->sc_if
.if_oerrors
++;
176 sc
->sc_flags
|= LEMAC_LINKUP
;
177 if ((txsts
& LEMAC_TDQ_COL
) != LEMAC_TDQ_NOCOL
)
178 sc
->sc_if
.if_collisions
++;
181 sc
->sc_if
.if_flags
&= ~IFF_OACTIVE
;
182 lemac_ifstart(&sc
->sc_if
);
191 * Read transmit status, remove transmit buffer from
192 * transmit queue and place on free memory queue,
193 * then reset transmitter.
194 * Increment appropriate counters.
197 sc
->sc_cntrs
.cntr_txd_intrs
++;
198 if (sc
->sc_txctl
& LEMAC_TX_STP
) {
199 sc
->sc_if
.if_oerrors
++;
200 /* return page to free queue */
201 LEMAC_OUTB(sc
, LEMAC_REG_FMQ
, LEMAC_INB(sc
, LEMAC_REG_TDQ
));
204 /* Turn back on transmitter if disabled */
205 LEMAC_OUTB(sc
, LEMAC_REG_CS
, cs_value
& ~LEMAC_CS_TXD
);
206 sc
->sc_if
.if_flags
&= ~IFF_OACTIVE
;
219 for (word_off
= 0; word_off
< LEMAC_EEP_SIZE
/ 2; word_off
++) {
220 LEMAC_OUTB(sc
, LEMAC_REG_PI1
, word_off
);
221 LEMAC_OUTB(sc
, LEMAC_REG_IOP
, LEMAC_IOP_EEREAD
);
223 DELAY(LEMAC_EEP_DELAY
);
225 *ep
= LEMAC_INB(sc
, LEMAC_REG_EE1
); cksum
+= *ep
++;
226 *ep
= LEMAC_INB(sc
, LEMAC_REG_EE2
); cksum
+= *ep
++;
230 * Set up Transmit Control Byte for use later during transmit.
233 sc
->sc_txctl
|= LEMAC_TX_FLAGS
;
235 if ((sc
->sc_eeprom
[LEMAC_EEP_SWFLAGS
] & LEMAC_EEP_SW_SQE
) == 0)
236 sc
->sc_txctl
&= ~LEMAC_TX_SQE
;
238 if (sc
->sc_eeprom
[LEMAC_EEP_SWFLAGS
] & LEMAC_EEP_SW_LAB
)
239 sc
->sc_txctl
|= LEMAC_TX_LAB
;
241 memcpy(sc
->sc_prodname
, &sc
->sc_eeprom
[LEMAC_EEP_PRDNM
], LEMAC_EEP_PRDNMSZ
);
242 sc
->sc_prodname
[LEMAC_EEP_PRDNMSZ
] = '\0';
253 conf
= LEMAC_INB(sc
, LEMAC_REG_CNF
);
255 if ((sc
->sc_eeprom
[LEMAC_EEP_SETUP
] & LEMAC_EEP_ST_DRAM
) == 0) {
256 sc
->sc_lastpage
= 63;
257 conf
&= ~LEMAC_CNF_DRAM
;
259 sc
->sc_lastpage
= 127;
260 conf
|= LEMAC_CNF_DRAM
;
263 LEMAC_OUTB(sc
, LEMAC_REG_CNF
, conf
);
265 for (pg
= 1; pg
<= sc
->sc_lastpage
; pg
++)
266 LEMAC_OUTB(sc
, LEMAC_REG_FMQ
, pg
);
275 struct ether_header eh
;
278 if (length
- sizeof(eh
) > ETHERMTU
279 || length
- sizeof(eh
) < ETHERMIN
) {
280 sc
->sc_if
.if_ierrors
++;
283 if (LEMAC_USE_PIO_MODE(sc
)) {
284 LEMAC_INSB(sc
, LEMAC_REG_DAT
, sizeof(eh
), (void *) &eh
);
286 LEMAC_GETBUF16(sc
, offset
, sizeof(eh
) / 2, (void *) &eh
);
289 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
291 sc
->sc_if
.if_ierrors
++;
294 if (length
+ 2 > MHLEN
) {
295 MCLGET(m
, M_DONTWAIT
);
296 if ((m
->m_flags
& M_EXT
) == 0) {
298 sc
->sc_if
.if_ierrors
++;
303 memcpy(m
->m_data
, (void *)&eh
, sizeof(eh
));
304 if (LEMAC_USE_PIO_MODE(sc
)) {
305 LEMAC_INSB(sc
, LEMAC_REG_DAT
, length
- sizeof(eh
),
306 mtod(m
, char *) + sizeof(eh
));
308 LEMAC_GETBUF16(sc
, offset
+ sizeof(eh
), (length
- sizeof(eh
)) / 2,
309 (void *)(mtod(m
, char *) + sizeof(eh
)));
311 m
->m_data
[length
- 1] = LEMAC_GET8(sc
, offset
+ length
- 1);
314 if (sc
->sc_if
.if_bpf
!= NULL
) {
315 m
->m_pkthdr
.len
= m
->m_len
= length
;
316 bpf_mtap(sc
->sc_if
.if_bpf
, m
);
319 * If this is single cast but not to us
322 if ((eh
.ether_dhost
[0] & 1) == 0
323 && !LEMAC_ADDREQUAL(eh
.ether_dhost
, sc
->sc_enaddr
)) {
328 m
->m_pkthdr
.len
= m
->m_len
= length
;
329 m
->m_pkthdr
.rcvif
= &sc
->sc_if
;
330 (*sc
->sc_if
.if_input
)(&sc
->sc_if
, m
);
339 sc
->sc_cntrs
.cntr_rne_intrs
++;
340 rxcount
= LEMAC_INB(sc
, LEMAC_REG_RQC
);
342 unsigned rxpg
= LEMAC_INB(sc
, LEMAC_REG_RQ
);
345 sc
->sc_if
.if_ipackets
++;
346 if (LEMAC_USE_PIO_MODE(sc
)) {
347 LEMAC_OUTB(sc
, LEMAC_REG_IOP
, rxpg
);
348 LEMAC_OUTB(sc
, LEMAC_REG_PI1
, 0);
349 LEMAC_OUTB(sc
, LEMAC_REG_PI2
, 0);
350 LEMAC_INSB(sc
, LEMAC_REG_DAT
, sizeof(rxlen
), (void *) &rxlen
);
352 LEMAC_OUTB(sc
, LEMAC_REG_MPN
, rxpg
);
353 rxlen
= LEMAC_GET32(sc
, 0);
355 if (rxlen
& LEMAC_RX_OK
) {
356 sc
->sc_flags
|= LEMAC_LINKUP
;
358 * Get receive length - subtract out checksum.
360 rxlen
= ((rxlen
>> 8) & 0x7FF) - 4;
361 lemac_input(sc
, sizeof(rxlen
), rxlen
);
363 sc
->sc_if
.if_ierrors
++;
365 LEMAC_OUTB(sc
, LEMAC_REG_FMQ
, rxpg
); /* Return this page to Free Memory Queue */
366 } /* end while (recv_count--) */
372 * This is the standard method of reading the DEC Address ROMS.
373 * I don't understand it but it does work.
377 unsigned char *hwaddr
,
378 const bus_space_tag_t iot
,
379 const bus_space_handle_t ioh
,
380 const bus_addr_t ioreg
,
383 int cksum
, rom_cksum
;
384 unsigned char addrbuf
[6];
387 int idx
, idx2
, found
, octet
;
388 static u_char testpat
[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA };
391 for (idx
= 0; idx
< 32; idx
++) {
392 octet
= bus_space_read_1(iot
, ioh
, ioreg
);
394 if (octet
== testpat
[idx2
]) {
395 if (++idx2
== sizeof(testpat
)) {
412 hwaddr
[0] = bus_space_read_1(iot
, ioh
, ioreg
);
413 hwaddr
[1] = bus_space_read_1(iot
, ioh
, ioreg
);
415 /* hardware address can't be multicast */
419 cksum
= *(u_short
*) &hwaddr
[0];
421 hwaddr
[2] = bus_space_read_1(iot
, ioh
, ioreg
);
422 hwaddr
[3] = bus_space_read_1(iot
, ioh
, ioreg
);
424 if (cksum
> 65535) cksum
-= 65535;
425 cksum
+= *(u_short
*) &hwaddr
[2];
426 if (cksum
> 65535) cksum
-= 65535;
428 hwaddr
[4] = bus_space_read_1(iot
, ioh
, ioreg
);
429 hwaddr
[5] = bus_space_read_1(iot
, ioh
, ioreg
);
431 if (cksum
> 65535) cksum
-= 65535;
432 cksum
+= *(u_short
*) &hwaddr
[4];
433 if (cksum
>= 65535) cksum
-= 65535;
435 /* 00-00-00 is an illegal OUI */
436 if (hwaddr
[0] == 0 && hwaddr
[1] == 0 && hwaddr
[2] == 0)
439 rom_cksum
= bus_space_read_1(iot
, ioh
, ioreg
);
440 rom_cksum
|= bus_space_read_1(iot
, ioh
, ioreg
) << 8;
442 if (cksum
!= rom_cksum
)
455 crc
= ether_crc32_le(mca
, ETHER_ADDR_LEN
);
458 * The following two lines convert the N bit index into a longword index
459 * and a longword mask.
461 #if LEMAC_MCTBL_BITS < 0
462 crc
>>= (32 + LEMAC_MCTBL_BITS
);
463 crc
&= (1 << -LEMAC_MCTBL_BITS
) - 1;
465 crc
&= (1 << LEMAC_MCTBL_BITS
) - 1;
467 bit
= 1 << (crc
& 0x0F);
471 * Set or clear hash filter bit in our table.
474 mctbl
[idx
] |= bit
; /* Set Bit */
476 mctbl
[idx
] &= ~bit
; /* Clear Bit */
481 lemac_multicast_filter(
484 struct ether_multistep step
;
485 struct ether_multi
*enm
;
487 memset(sc
->sc_mctbl
, 0, LEMAC_MCTBL_BITS
/ 8);
489 lemac_multicast_op(sc
->sc_mctbl
, etherbroadcastaddr
, TRUE
);
491 ETHER_FIRST_MULTI(step
, &sc
->sc_ec
, enm
);
492 while (enm
!= NULL
) {
493 if (!LEMAC_ADDREQUAL(enm
->enm_addrlo
, enm
->enm_addrhi
)) {
494 sc
->sc_flags
|= LEMAC_ALLMULTI
;
495 sc
->sc_if
.if_flags
|= IFF_ALLMULTI
;
498 lemac_multicast_op(sc
->sc_mctbl
, enm
->enm_addrlo
, TRUE
);
499 ETHER_NEXT_MULTI(step
, enm
);
501 sc
->sc_flags
&= ~LEMAC_ALLMULTI
;
502 sc
->sc_if
.if_flags
&= ~IFF_ALLMULTI
;
506 * Do a hard reset of the board;
510 lemac_softc_t
* const sc
)
517 sc
->sc_flags
&= ~LEMAC_LINKUP
;
518 sc
->sc_if
.if_flags
&= ~IFF_OACTIVE
;
519 LEMAC_INTR_DISABLE(sc
);
521 LEMAC_OUTB(sc
, LEMAC_REG_IOP
, LEMAC_IOP_EEINIT
);
522 DELAY(LEMAC_EEP_DELAY
);
525 * Read EEPROM information. NOTE - the placement of this function
526 * is important because functions hereafter may rely on information
527 * read from the EEPROM.
529 if ((data
= lemac_read_eeprom(sc
)) != LEMAC_EEP_CKSUM
) {
530 printf("%s: reset: EEPROM checksum failed (0x%x)\n",
531 sc
->sc_if
.if_xname
, data
);
536 * Update the control register to reflect the media choice
538 data
= LEMAC_INB(sc
, LEMAC_REG_CTL
);
539 if ((data
& (LEMAC_CTL_APD
|LEMAC_CTL_PSL
)) != sc
->sc_ctlmode
) {
540 data
&= ~(LEMAC_CTL_APD
|LEMAC_CTL_PSL
);
541 data
|= sc
->sc_ctlmode
;
542 LEMAC_OUTB(sc
, LEMAC_REG_CTL
, data
);
546 * Force to 2K mode if not already configured.
549 data
= LEMAC_INB(sc
, LEMAC_REG_MBR
);
550 if (LEMAC_IS_2K_MODE(data
)) {
551 sc
->sc_flags
|= LEMAC_2K_MODE
;
552 } else if (LEMAC_IS_64K_MODE(data
)) {
553 data
= (((data
* 2) & 0xF) << 4);
554 sc
->sc_flags
|= LEMAC_WAS_64K_MODE
;
555 LEMAC_OUTB(sc
, LEMAC_REG_MBR
, data
);
556 } else if (LEMAC_IS_32K_MODE(data
)) {
557 data
= ((data
& 0xF) << 4);
558 sc
->sc_flags
|= LEMAC_WAS_32K_MODE
;
559 LEMAC_OUTB(sc
, LEMAC_REG_MBR
, data
);
561 sc
->sc_flags
|= LEMAC_PIO_MODE
;
566 * Initialize Free Memory Queue, Init mcast table with broadcast.
569 lemac_init_adapmem(sc
);
570 sc
->sc_flags
|= LEMAC_ALIVE
;
575 lemac_softc_t
* const sc
)
577 if ((sc
->sc_flags
& LEMAC_ALIVE
) == 0)
581 * If the interface has the up flag
583 if (sc
->sc_if
.if_flags
& IFF_UP
) {
584 int saved_cs
= LEMAC_INB(sc
, LEMAC_REG_CS
);
585 LEMAC_OUTB(sc
, LEMAC_REG_CS
, saved_cs
| (LEMAC_CS_TXD
| LEMAC_CS_RXD
));
586 LEMAC_OUTB(sc
, LEMAC_REG_PA0
, sc
->sc_enaddr
[0]);
587 LEMAC_OUTB(sc
, LEMAC_REG_PA1
, sc
->sc_enaddr
[1]);
588 LEMAC_OUTB(sc
, LEMAC_REG_PA2
, sc
->sc_enaddr
[2]);
589 LEMAC_OUTB(sc
, LEMAC_REG_PA3
, sc
->sc_enaddr
[3]);
590 LEMAC_OUTB(sc
, LEMAC_REG_PA4
, sc
->sc_enaddr
[4]);
591 LEMAC_OUTB(sc
, LEMAC_REG_PA5
, sc
->sc_enaddr
[5]);
593 LEMAC_OUTB(sc
, LEMAC_REG_IC
, LEMAC_INB(sc
, LEMAC_REG_IC
) | LEMAC_IC_IE
);
595 if (sc
->sc_if
.if_flags
& IFF_PROMISC
) {
596 LEMAC_OUTB(sc
, LEMAC_REG_CS
, LEMAC_CS_MCE
| LEMAC_CS_PME
);
598 LEMAC_INTR_DISABLE(sc
);
599 lemac_multicast_filter(sc
);
600 if (sc
->sc_flags
& LEMAC_ALLMULTI
)
601 memcpy(sc
->sc_mctbl
, lemac_allmulti_mctbl
,
602 sizeof(sc
->sc_mctbl
));
603 if (LEMAC_USE_PIO_MODE(sc
)) {
604 LEMAC_OUTB(sc
, LEMAC_REG_IOP
, 0);
605 LEMAC_OUTB(sc
, LEMAC_REG_PI1
, LEMAC_MCTBL_OFF
& 0xFF);
606 LEMAC_OUTB(sc
, LEMAC_REG_PI2
, LEMAC_MCTBL_OFF
>> 8);
607 LEMAC_OUTSB(sc
, LEMAC_REG_DAT
, sizeof(sc
->sc_mctbl
), (void *) sc
->sc_mctbl
);
609 LEMAC_OUTB(sc
, LEMAC_REG_MPN
, 0);
610 LEMAC_PUTBUF8(sc
, LEMAC_MCTBL_OFF
, sizeof(sc
->sc_mctbl
), (void *) sc
->sc_mctbl
);
613 LEMAC_OUTB(sc
, LEMAC_REG_CS
, LEMAC_CS_MCE
);
616 LEMAC_OUTB(sc
, LEMAC_REG_CTL
, LEMAC_INB(sc
, LEMAC_REG_CTL
) ^ LEMAC_CTL_LED
);
618 LEMAC_INTR_ENABLE(sc
);
619 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
620 lemac_ifstart(&sc
->sc_if
);
622 LEMAC_OUTB(sc
, LEMAC_REG_CS
, LEMAC_CS_RXD
|LEMAC_CS_TXD
);
624 LEMAC_INTR_DISABLE(sc
);
625 sc
->sc_if
.if_flags
&= ~IFF_RUNNING
;
633 lemac_softc_t
* const sc
= LEMAC_IFP_TO_SOFTC(ifp
);
635 if ((ifp
->if_flags
& IFF_RUNNING
) == 0)
638 LEMAC_INTR_DISABLE(sc
);
645 IFQ_POLL(&ifp
->if_snd
, m
);
649 if ((sc
->sc_csr
.csr_tqc
= LEMAC_INB(sc
, LEMAC_REG_TQC
)) >= lemac_txmax
) {
650 sc
->sc_cntrs
.cntr_txfull
++;
651 ifp
->if_flags
|= IFF_OACTIVE
;
656 * get free memory page
658 tx_pg
= sc
->sc_csr
.csr_fmq
= LEMAC_INB(sc
, LEMAC_REG_FMQ
);
660 * Check for good transmit page.
662 if (tx_pg
== 0 || tx_pg
> sc
->sc_lastpage
) {
663 sc
->sc_cntrs
.cntr_txnospc
++;
664 ifp
->if_flags
|= IFF_OACTIVE
;
668 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
671 * The first four bytes of each transmit buffer are for
672 * control information. The first byte is the control
673 * byte, then the length (why not word aligned?), then
674 * the offset to the buffer.
677 if (LEMAC_USE_PIO_MODE(sc
)) {
678 LEMAC_OUTB(sc
, LEMAC_REG_IOP
, tx_pg
); /* Shift 2K window. */
679 LEMAC_OUTB(sc
, LEMAC_REG_PI1
, 0);
680 LEMAC_OUTB(sc
, LEMAC_REG_PI2
, 0);
681 LEMAC_OUTB(sc
, LEMAC_REG_DAT
, sc
->sc_txctl
);
682 LEMAC_OUTB(sc
, LEMAC_REG_DAT
, (m
->m_pkthdr
.len
>> 0) & 0xFF);
683 LEMAC_OUTB(sc
, LEMAC_REG_DAT
, (m
->m_pkthdr
.len
>> 8) & 0xFF);
684 LEMAC_OUTB(sc
, LEMAC_REG_DAT
, LEMAC_TX_HDRSZ
);
685 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
)
686 LEMAC_OUTSB(sc
, LEMAC_REG_DAT
, m0
->m_len
, m0
->m_data
);
688 bus_size_t txoff
= /* (mtod(m, u_int32_t) & (sizeof(u_int32_t) - 1)) + */ LEMAC_TX_HDRSZ
;
689 LEMAC_OUTB(sc
, LEMAC_REG_MPN
, tx_pg
); /* Shift 2K window. */
690 LEMAC_PUT8(sc
, 0, sc
->sc_txctl
);
691 LEMAC_PUT8(sc
, 1, (m
->m_pkthdr
.len
>> 0) & 0xFF);
692 LEMAC_PUT8(sc
, 2, (m
->m_pkthdr
.len
>> 8) & 0xFF);
693 LEMAC_PUT8(sc
, 3, txoff
);
696 * Copy the packet to the board
698 for (m0
= m
; m0
!= NULL
; m0
= m0
->m_next
) {
700 LEMAC_PUTBUF8(sc
, txoff
, m0
->m_len
, m0
->m_data
);
703 const u_int8_t
*cp
= m0
->m_data
;
706 if ((txoff
& 3) == (((long)cp
) & 3) && len
>= 4) {
708 int alen
= (~txoff
& 3);
709 LEMAC_PUTBUF8(sc
, txoff
, alen
, cp
);
710 cp
+= alen
; txoff
+= alen
; len
-= alen
;
713 LEMAC_PUTBUF32(sc
, txoff
, len
/ 4, cp
);
714 cp
+= len
& ~3; txoff
+= len
& ~3; len
&= 3;
718 if ((txoff
& 1) == (((long)cp
) & 1) && len
>= 2) {
720 int alen
= (~txoff
& 1);
721 LEMAC_PUTBUF8(sc
, txoff
, alen
, cp
);
722 cp
+= alen
; txoff
+= alen
; len
-= alen
;
725 LEMAC_PUTBUF16(sc
, txoff
, len
/ 2, (const void *) cp
);
726 cp
+= len
& ~1; txoff
+= len
& ~1; len
&= 1;
730 LEMAC_PUTBUF8(sc
, txoff
, len
, cp
);
737 LEMAC_OUTB(sc
, LEMAC_REG_TQ
, tx_pg
); /* tell chip to transmit this packet */
739 if (sc
->sc_if
.if_bpf
!= NULL
)
740 bpf_mtap(sc
->sc_if
.if_bpf
, m
);
742 m_freem(m
); /* free the mbuf */
744 LEMAC_INTR_ENABLE(sc
);
753 lemac_softc_t
* const sc
= LEMAC_IFP_TO_SOFTC(ifp
);
760 case SIOCINITIFADDR
: {
761 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
763 ifp
->if_flags
|= IFF_UP
;
765 switch (ifa
->ifa_addr
->sa_family
) {
768 arp_ifinit(&sc
->sc_if
, ifa
);
782 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
791 * Update multicast listeners
793 if ((error
= ether_ioctl(ifp
, cmd
, data
)) == ENETRESET
) {
794 /* reset multicast filtering */
795 if (ifp
->if_flags
& IFF_RUNNING
)
804 error
= ifmedia_ioctl(ifp
, (struct ifreq
*)data
,
805 &sc
->sc_ifmedia
, cmd
);
810 error
= ether_ioctl(ifp
, cmd
, data
);
820 lemac_ifmedia_change(
821 struct ifnet
* const ifp
)
823 lemac_softc_t
* const sc
= LEMAC_IFP_TO_SOFTC(ifp
);
826 switch (IFM_SUBTYPE(sc
->sc_ifmedia
.ifm_media
)) {
827 case IFM_10_T
: new_ctl
= LEMAC_CTL_APD
; break;
829 case IFM_10_5
: new_ctl
= LEMAC_CTL_APD
|LEMAC_CTL_PSL
; break;
830 case IFM_AUTO
: new_ctl
= 0; break;
831 default: return EINVAL
;
833 if (sc
->sc_ctlmode
!= new_ctl
) {
834 sc
->sc_ctlmode
= new_ctl
;
836 if (sc
->sc_if
.if_flags
& IFF_UP
)
843 * Media status callback
846 lemac_ifmedia_status(
847 struct ifnet
* const ifp
,
848 struct ifmediareq
*req
)
850 lemac_softc_t
*sc
= LEMAC_IFP_TO_SOFTC(ifp
);
851 unsigned data
= LEMAC_INB(sc
, LEMAC_REG_CNF
);
853 req
->ifm_status
= IFM_AVALID
;
854 if (sc
->sc_flags
& LEMAC_LINKUP
)
855 req
->ifm_status
|= IFM_ACTIVE
;
857 if (sc
->sc_ctlmode
& LEMAC_CTL_APD
) {
858 if (sc
->sc_ctlmode
& LEMAC_CTL_PSL
) {
859 req
->ifm_active
= IFM_10_5
;
861 req
->ifm_active
= IFM_10_T
;
865 * The link bit of the configuration register reflects the
866 * current media choice when auto-port is enabled.
868 if (data
& LEMAC_CNF_NOLINK
) {
869 req
->ifm_active
= IFM_10_5
;
871 req
->ifm_active
= IFM_10_T
;
875 req
->ifm_active
|= IFM_ETHER
;
880 const bus_space_tag_t iot
,
881 const bus_space_handle_t ioh
)
883 unsigned char hwaddr
[6];
885 if (lemac_read_macaddr(hwaddr
, iot
, ioh
, LEMAC_REG_APD
, 0) == 0)
887 if (lemac_read_macaddr(hwaddr
, iot
, ioh
, LEMAC_REG_APD
, 1) == 0)
894 const bus_space_tag_t iot
,
895 const bus_space_handle_t ioh
,
902 *irq_p
= LEMAC_DECODEIRQ(bus_space_read_1(iot
, ioh
, LEMAC_REG_IC
) & LEMAC_IC_IRQMSK
);
904 data
= bus_space_read_1(iot
, ioh
, LEMAC_REG_MBR
);
905 if (LEMAC_IS_2K_MODE(data
)) {
906 *maddr_p
= data
* (2 * 1024) + (512 * 1024);
908 } else if (LEMAC_IS_64K_MODE(data
)) {
909 *maddr_p
= data
* 64 * 1024;
910 *msize_p
= 64 * 1024;
911 } else if (LEMAC_IS_32K_MODE(data
)) {
912 *maddr_p
= data
* 32 * 1024;
921 * What to do upon receipt of an interrupt.
927 lemac_softc_t
* const sc
= arg
;
930 LEMAC_INTR_DISABLE(sc
); /* Mask interrupts */
933 * Determine cause of interrupt. Receive events take
934 * priority over Transmit.
937 cs_value
= LEMAC_INB(sc
, LEMAC_REG_CS
);
940 * Check for Receive Queue not being empty.
941 * Check for Transmit Done Queue not being empty.
944 if (cs_value
& LEMAC_CS_RNE
)
946 if (cs_value
& LEMAC_CS_TNE
)
950 * Check for Transmitter Disabled.
951 * Check for Receiver Disabled.
954 if (cs_value
& LEMAC_CS_TXD
)
955 lemac_txd_intr(sc
, cs_value
);
956 if (cs_value
& LEMAC_CS_RXD
)
957 lemac_rxd_intr(sc
, cs_value
);
960 * Toggle LED and unmask interrupts.
963 sc
->sc_csr
.csr_cs
= LEMAC_INB(sc
, LEMAC_REG_CS
);
965 LEMAC_OUTB(sc
, LEMAC_REG_CTL
, LEMAC_INB(sc
, LEMAC_REG_CTL
) ^ LEMAC_CTL_LED
);
966 LEMAC_INTR_ENABLE(sc
); /* Unmask interrupts */
970 rnd_add_uint32(&sc
->rnd_source
, cs_value
);
980 lemac_reset((lemac_softc_t
*) arg
);
983 static const char * const lemac_modes
[4] = {
984 "PIO mode (internal 2KB window)",
986 "changed 32KB window to 2KB",
987 "changed 64KB window to 2KB",
994 struct ifnet
* const ifp
= &sc
->sc_if
;
996 strlcpy(ifp
->if_xname
, device_xname(&sc
->sc_dv
), IFNAMSIZ
);
1000 (void) lemac_read_macaddr(sc
->sc_enaddr
, sc
->sc_iot
, sc
->sc_ioh
,
1003 printf(": %s\n", sc
->sc_prodname
);
1005 printf("%s: address %s, %dKB RAM, %s\n",
1007 ether_sprintf(sc
->sc_enaddr
),
1008 sc
->sc_lastpage
* 2 + 2,
1009 lemac_modes
[sc
->sc_flags
& LEMAC_MODE_MASK
]);
1011 ifp
->if_softc
= (void *) sc
;
1012 ifp
->if_start
= lemac_ifstart
;
1013 ifp
->if_ioctl
= lemac_ifioctl
;
1015 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
1016 #ifdef IFF_NOTRAILERS
1021 if (sc
->sc_flags
& LEMAC_ALIVE
) {
1024 IFQ_SET_READY(&ifp
->if_snd
);
1027 ether_ifattach(ifp
, sc
->sc_enaddr
);
1030 rnd_attach_source(&sc
->rnd_source
, device_xname(&sc
->sc_dv
),
1034 ifmedia_init(&sc
->sc_ifmedia
, 0,
1035 lemac_ifmedia_change
,
1036 lemac_ifmedia_status
);
1037 if (sc
->sc_prodname
[4] == '5') /* DE205 is UTP/AUI */
1038 ifmedia_add(&sc
->sc_ifmedia
, IFM_ETHER
| IFM_AUTO
, 0, 0);
1039 if (sc
->sc_prodname
[4] != '3') /* DE204 & 205 have UTP */
1040 ifmedia_add(&sc
->sc_ifmedia
, IFM_ETHER
| IFM_10_T
, 0, 0);
1041 if (sc
->sc_prodname
[4] != '4') /* DE203 & 205 have BNC */
1042 ifmedia_add(&sc
->sc_ifmedia
, IFM_ETHER
| IFM_10_5
, 0, 0);
1043 switch (sc
->sc_prodname
[4]) {
1044 case '3': media
= IFM_10_5
; break;
1045 case '4': media
= IFM_10_T
; break;
1046 default: media
= IFM_AUTO
; break;
1048 ifmedia_set(&sc
->sc_ifmedia
, IFM_ETHER
| media
);
1050 printf("%s: disabled due to error\n", ifp
->if_xname
);