1 /* $NetBSD: ne.c,v 1.7 2008/12/14 18:46:33 christos Exp $ */
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
37 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
39 * Copyright (C) 1993, David Greenman. This software may be used, modified,
40 * copied, distributed, and sold, in both source and binary form provided that
41 * the above copyright and these terms are retained. Under no circumstances is
42 * the author responsible for the proper functioning of this software, nor does
43 * the author assume any responsibility for damages incurred with its use.
47 * this code is mainly obtained from /sys/dev/ic/ne2000.c .
50 #include <sys/types.h>
51 #include <machine/pio.h>
53 #include <lib/libsa/stand.h>
57 #include <lib/libkern/libkern.h>
62 #include <dev/ic/dp8390reg.h>
63 #include <dev/ic/ne2000reg.h>
71 #define NE_BASEREG BASEREG
72 #define NE_ASIC_BASEREG (NE_BASEREG+NE2000_ASIC_OFFSET)
74 #define NIC_PORT(x) (NE_BASEREG + (x))
75 #define NIC_INB(x) inb(NIC_PORT(x))
76 #define NIC_OUTB(x, b) outb(NIC_PORT(x), (b))
80 #define DELAY(x) delay(x)
82 #define ASIC_PORT(x) (NE_ASIC_BASEREG + (x))
83 #define ASIC_INB(x) inb(ASIC_PORT(x))
84 #define ASIC_INW(x) inw(ASIC_PORT(x))
85 #define ASIC_OUTB(x, b) outb(ASIC_PORT(x), (b))
86 #define ASIC_OUTW(x, b) outw(ASIC_PORT(x), (b))
91 static struct btinfo_netif bi_netif
;
95 EtherInit(unsigned char *myadr
)
100 printf("ne: trying iobase=0x%x\n", NE_BASEREG
);
102 dp8390_iobase
= NE_BASEREG
;
103 dp8390_membase
= dp8390_memsize
= 8192*2;
104 dp8390_cr_proto
= ED_CR_RD2
;
105 dp8390_dcr_reg
= ED_DCR_FT1
| ED_DCR_LS
112 tmp
= ASIC_INB(NE2000_ASIC_RESET
);
114 ASIC_OUTB(NE2000_ASIC_RESET
, tmp
);
117 NIC_OUTB(ED_P0_CR
, ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STP
);
120 tmp
= NIC_INB(ED_P0_CR
);
121 if ((tmp
& (ED_CR_RD2
| ED_CR_TXP
| ED_CR_STA
| ED_CR_STP
)) !=
122 (ED_CR_RD2
| ED_CR_STP
)) {
126 tmp
= NIC_INB(ED_P0_ISR
);
127 if ((tmp
& ED_ISR_RST
) != ED_ISR_RST
) {
131 NIC_OUTB(ED_P0_CR
, ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STA
);
133 for (i
= 0; i
< 100; i
++) {
134 if ((NIC_INB(ED_P0_ISR
) & ED_ISR_RST
) ==
136 /* Ack the reset bit. */
137 NIC_OUTB(ED_P0_ISR
, ED_ISR_RST
);
143 printf("ne: found\n");
146 * This prevents packets from being stored in the NIC memory when
147 * the readmem routine turns on the start bit in the CR.
149 NIC_OUTB(ED_P0_RCR
, ED_RCR_MON
);
151 /* Temporarily initialize DCR for byte operations. */
152 NIC_OUTB(ED_P0_DCR
, ED_DCR_FT1
| ED_DCR_LS
);
154 NIC_OUTB(ED_P0_PSTART
, 8192 >> ED_PAGE_SHIFT
);
155 NIC_OUTB(ED_P0_PSTOP
, 16384 >> ED_PAGE_SHIFT
);
158 for (i
= 0; i
< 6; i
++)
159 myadr
[i
] = eth_myaddr
[i
] = HWADDR
[i
];
164 ne2000_readmem(0, romdata
, 16);
165 for (i
= 0; i
< 6; i
++)
166 myadr
[i
] = eth_myaddr
[i
] = romdata
[i
*2];
174 strncpy(bi_netif
.ifname
, "ne", sizeof(bi_netif
.ifname
));
175 bi_netif
.bus
= BI_BUS_ISA
;
176 bi_netif
.addr
.iobase
= NE_BASEREG
;
178 BI_ADD(&bi_netif
, BTINFO_NETIF
, sizeof(bi_netif
));
191 tmp
= ASIC_INB(NE2000_ASIC_RESET
);
193 ASIC_OUTB(NE2000_ASIC_RESET
, tmp
);
196 NIC_OUTB(ED_P0_CR
, ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STP
);
201 ne2000_writemem(uint8_t *src
, int dst
, size_t len
)
204 int maxwait
= 100; /* about 120us */
206 /* Select page 0 registers. */
207 NIC_OUTB(ED_P0_CR
, ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STA
);
209 /* Reset remote DMA complete flag. */
210 NIC_OUTB(ED_P0_ISR
, ED_ISR_RDC
);
212 /* Set up DMA byte count. */
213 NIC_OUTB(ED_P0_RBCR0
, len
);
214 NIC_OUTB(ED_P0_RBCR1
, len
>> 8);
216 /* Set up destination address in NIC mem. */
217 NIC_OUTB(ED_P0_RSAR0
, dst
);
218 NIC_OUTB(ED_P0_RSAR1
, dst
>> 8);
220 /* Set remote DMA write. */
221 NIC_OUTB(ED_P0_CR
, ED_CR_RD1
| ED_CR_PAGE_0
| ED_CR_STA
);
224 for (i
= 0; i
< len
; i
+= 2, src
+= 2)
225 ASIC_OUTW(NE2000_ASIC_DATA
, *(uint16_t *)src
);
227 for (i
= 0; i
< len
; i
++)
228 ASIC_OUTB(NE2000_ASIC_DATA
, *src
++);
232 * Wait for remote DMA to complete. This is necessary because on the
233 * transmit side, data is handled internally by the NIC in bursts, and
234 * we can't start another remote DMA until this one completes. Not
235 * waiting causes really bad things to happen - like the NIC wedging
238 while (((NIC_INB(ED_P0_ISR
) & ED_ISR_RDC
) != ED_ISR_RDC
) && --maxwait
)
242 printf("ne2000_writemem: failed to complete\n");
246 ne2000_readmem(int src
, uint8_t *dst
, size_t amount
)
250 /* Select page 0 registers. */
251 NIC_OUTB(ED_P0_CR
, ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STA
);
253 /* Round up to a word. */
257 /* Set up DMA byte count. */
258 NIC_OUTB(ED_P0_RBCR0
, amount
);
259 NIC_OUTB(ED_P0_RBCR1
, amount
>> 8);
261 /* Set up source address in NIC mem. */
262 NIC_OUTB(ED_P0_RSAR0
, src
);
263 NIC_OUTB(ED_P0_RSAR1
, src
>> 8);
265 NIC_OUTB(ED_P0_CR
, ED_CR_RD0
| ED_CR_PAGE_0
| ED_CR_STA
);
268 for (i
= 0; i
< amount
; i
+= 2, dst
+= 2)
269 *(uint16_t *)dst
= ASIC_INW(NE2000_ASIC_DATA
);
271 for (i
= 0; i
< amount
; i
++)
272 *dst
++ = ASIC_INB(NE2000_ASIC_DATA
);