Deleted Added
full compact
if_ex.c (61488) if_ex.c (63090)
1/*
2 * Copyright (c) 1996, Javier Mart�n Rueda (jmrueda@diatel.upm.es)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
1/*
2 * Copyright (c) 1996, Javier Mart�n Rueda (jmrueda@diatel.upm.es)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/dev/ex/if_ex.c 61488 2000-06-10 11:09:03Z peter $
27 * $FreeBSD: head/sys/dev/ex/if_ex.c 63090 2000-07-13 22:54:34Z archie $
28 *
29 * MAINTAINER: Matthew N. Dodd <winter@jurai.net>
30 * <mdodd@FreeBSD.org>
31 */
32
33/*
34 * Intel EtherExpress Pro/10, Pro/10+ Ethernet driver
35 *
36 * Revision history:
37 *
38 * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast.
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/sockio.h>
45#include <sys/mbuf.h>
46#include <sys/socket.h>
47
48#include <sys/module.h>
49#include <sys/bus.h>
50
51#include <machine/bus.h>
52#include <machine/resource.h>
53#include <sys/rman.h>
54
55#include <net/if.h>
56#include <net/if_arp.h>
57#include <net/if_media.h>
58#include <net/ethernet.h>
59#include <net/bpf.h>
60
61#include <netinet/in.h>
62#include <netinet/if_ether.h>
63
64#include <machine/clock.h>
65
66#include <isa/isavar.h>
67#include <isa/pnpvar.h>
68
69#include <dev/ex/if_exreg.h>
70#include <dev/ex/if_exvar.h>
71
72#ifdef EXDEBUG
73# define Start_End 1
74# define Rcvd_Pkts 2
75# define Sent_Pkts 4
76# define Status 8
77static int debug_mask = 0;
78static int exintr_count = 0;
79# define DODEBUG(level, action) if (level & debug_mask) action
80#else
81# define DODEBUG(level, action)
82#endif
83
84char irq2eemap[] =
85 { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1, -1, -1 };
86u_char ee2irqmap[] =
87 { 9, 3, 5, 10, 11, 0, 0, 0 };
88
89char plus_irq2eemap[] =
90 { -1, -1, -1, 0, 1, 2, -1, 3, -1, 4, 5, 6, 7, -1, -1, -1 };
91u_char plus_ee2irqmap[] =
92 { 3, 4, 5, 7, 9, 10, 11, 12 };
93
94/* Network Interface Functions */
95static void ex_init __P((void *));
96static void ex_start __P((struct ifnet *));
97static int ex_ioctl __P((struct ifnet *, u_long, caddr_t));
98static void ex_watchdog __P((struct ifnet *));
99
100/* ifmedia Functions */
101static int ex_ifmedia_upd __P((struct ifnet *));
102static void ex_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
103
104static int ex_get_media __P((u_int32_t iobase));
105
106static void ex_stop __P((struct ex_softc *));
107static void ex_reset __P((struct ex_softc *));
108
109static void ex_tx_intr __P((struct ex_softc *));
110static void ex_rx_intr __P((struct ex_softc *));
111
112int
113look_for_card (u_int32_t iobase)
114{
115 int count1, count2;
116
117 /*
118 * Check for the i82595 signature, and check that the round robin
119 * counter actually advances.
120 */
121 if (((count1 = inb(iobase + ID_REG)) & Id_Mask) != Id_Sig)
122 return(0);
123 count2 = inb(iobase + ID_REG);
124 count2 = inb(iobase + ID_REG);
125 count2 = inb(iobase + ID_REG);
126
127 return((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits));
128}
129
130void
131ex_get_address (u_int32_t iobase, u_char *enaddr)
132{
133 u_int16_t eaddr_tmp;
134
135 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Lo);
136 enaddr[5] = eaddr_tmp & 0xff;
137 enaddr[4] = eaddr_tmp >> 8;
138 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Mid);
139 enaddr[3] = eaddr_tmp & 0xff;
140 enaddr[2] = eaddr_tmp >> 8;
141 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Hi);
142 enaddr[1] = eaddr_tmp & 0xff;
143 enaddr[0] = eaddr_tmp >> 8;
144
145 return;
146}
147
148int
149ex_card_type (u_char *enaddr)
150{
151 if ((enaddr[0] == 0x00) && (enaddr[1] == 0xA0) && (enaddr[2] == 0xC9))
152 return (CARD_TYPE_EX_10_PLUS);
153
154 return (CARD_TYPE_EX_10);
155}
156
157/*
158 * Caller is responsible for eventually calling
159 * ex_release_resources() on failure.
160 */
161int
162ex_alloc_resources (device_t dev)
163{
164 struct ex_softc * sc = device_get_softc(dev);
165 int error = 0;
166
167 sc->ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->ioport_rid,
168 0, ~0, 1, RF_ACTIVE);
169 if (!sc->ioport) {
170 device_printf(dev, "No I/O space?!\n");
171 error = ENOMEM;
172 goto bad;
173 }
174
175 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
176 0, ~0, 1, RF_ACTIVE);
177
178 if (!sc->irq) {
179 device_printf(dev, "No IRQ?!\n");
180 error = ENOMEM;
181 goto bad;
182 }
183
184bad:
185 return (error);
186}
187
188void
189ex_release_resources (device_t dev)
190{
191 struct ex_softc * sc = device_get_softc(dev);
192
193 if (sc->ih) {
194 bus_teardown_intr(dev, sc->irq, sc->ih);
195 sc->ih = NULL;
196 }
197
198 if (sc->ioport) {
199 bus_release_resource(dev, SYS_RES_IOPORT,
200 sc->ioport_rid, sc->ioport);
201 sc->ioport = NULL;
202 }
203
204 if (sc->irq) {
205 bus_release_resource(dev, SYS_RES_IRQ,
206 sc->irq_rid, sc->irq);
207 sc->irq = NULL;
208 }
209
210 return;
211}
212
213int
214ex_attach(device_t dev)
215{
216 struct ex_softc * sc = device_get_softc(dev);
217 struct ifnet * ifp = &sc->arpcom.ac_if;
218 struct ifmedia * ifm;
219 int unit = device_get_unit(dev);
220 u_int16_t temp;
221
222 /* work out which set of irq <-> internal tables to use */
223 if (ex_card_type(sc->arpcom.ac_enaddr) == CARD_TYPE_EX_10_PLUS) {
224 sc->irq2ee = plus_irq2eemap;
225 sc->ee2irq = plus_ee2irqmap;
226 } else {
227 sc->irq2ee = irq2eemap;
228 sc->ee2irq = ee2irqmap;
229 }
230
231 sc->mem_size = CARD_RAM_SIZE; /* XXX This should be read from the card itself. */
232
233 /*
234 * Initialize the ifnet structure.
235 */
236 ifp->if_softc = sc;
237 ifp->if_unit = unit;
238 ifp->if_name = "ex";
239 ifp->if_mtu = ETHERMTU;
240 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST /* XXX not done yet. | IFF_MULTICAST */;
241 ifp->if_output = ether_output;
242 ifp->if_start = ex_start;
243 ifp->if_ioctl = ex_ioctl;
244 ifp->if_watchdog = ex_watchdog;
245 ifp->if_init = ex_init;
246 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
247
248 ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts);
249
250 temp = eeprom_read(sc->iobase, EE_W5);
251 if (temp & EE_W5_PORT_TPE)
252 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
253 if (temp & EE_W5_PORT_BNC)
254 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL);
255 if (temp & EE_W5_PORT_AUI)
256 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL);
257
258 ifmedia_set(&sc->ifmedia, ex_get_media(sc->iobase));
259
260 ifm = &sc->ifmedia;
261 ifm->ifm_media = ifm->ifm_cur->ifm_media;
262 ex_ifmedia_upd(ifp);
263
264 /*
265 * Attach the interface.
266 */
28 *
29 * MAINTAINER: Matthew N. Dodd <winter@jurai.net>
30 * <mdodd@FreeBSD.org>
31 */
32
33/*
34 * Intel EtherExpress Pro/10, Pro/10+ Ethernet driver
35 *
36 * Revision history:
37 *
38 * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast.
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/sockio.h>
45#include <sys/mbuf.h>
46#include <sys/socket.h>
47
48#include <sys/module.h>
49#include <sys/bus.h>
50
51#include <machine/bus.h>
52#include <machine/resource.h>
53#include <sys/rman.h>
54
55#include <net/if.h>
56#include <net/if_arp.h>
57#include <net/if_media.h>
58#include <net/ethernet.h>
59#include <net/bpf.h>
60
61#include <netinet/in.h>
62#include <netinet/if_ether.h>
63
64#include <machine/clock.h>
65
66#include <isa/isavar.h>
67#include <isa/pnpvar.h>
68
69#include <dev/ex/if_exreg.h>
70#include <dev/ex/if_exvar.h>
71
72#ifdef EXDEBUG
73# define Start_End 1
74# define Rcvd_Pkts 2
75# define Sent_Pkts 4
76# define Status 8
77static int debug_mask = 0;
78static int exintr_count = 0;
79# define DODEBUG(level, action) if (level & debug_mask) action
80#else
81# define DODEBUG(level, action)
82#endif
83
84char irq2eemap[] =
85 { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1, -1, -1 };
86u_char ee2irqmap[] =
87 { 9, 3, 5, 10, 11, 0, 0, 0 };
88
89char plus_irq2eemap[] =
90 { -1, -1, -1, 0, 1, 2, -1, 3, -1, 4, 5, 6, 7, -1, -1, -1 };
91u_char plus_ee2irqmap[] =
92 { 3, 4, 5, 7, 9, 10, 11, 12 };
93
94/* Network Interface Functions */
95static void ex_init __P((void *));
96static void ex_start __P((struct ifnet *));
97static int ex_ioctl __P((struct ifnet *, u_long, caddr_t));
98static void ex_watchdog __P((struct ifnet *));
99
100/* ifmedia Functions */
101static int ex_ifmedia_upd __P((struct ifnet *));
102static void ex_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
103
104static int ex_get_media __P((u_int32_t iobase));
105
106static void ex_stop __P((struct ex_softc *));
107static void ex_reset __P((struct ex_softc *));
108
109static void ex_tx_intr __P((struct ex_softc *));
110static void ex_rx_intr __P((struct ex_softc *));
111
112int
113look_for_card (u_int32_t iobase)
114{
115 int count1, count2;
116
117 /*
118 * Check for the i82595 signature, and check that the round robin
119 * counter actually advances.
120 */
121 if (((count1 = inb(iobase + ID_REG)) & Id_Mask) != Id_Sig)
122 return(0);
123 count2 = inb(iobase + ID_REG);
124 count2 = inb(iobase + ID_REG);
125 count2 = inb(iobase + ID_REG);
126
127 return((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits));
128}
129
130void
131ex_get_address (u_int32_t iobase, u_char *enaddr)
132{
133 u_int16_t eaddr_tmp;
134
135 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Lo);
136 enaddr[5] = eaddr_tmp & 0xff;
137 enaddr[4] = eaddr_tmp >> 8;
138 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Mid);
139 enaddr[3] = eaddr_tmp & 0xff;
140 enaddr[2] = eaddr_tmp >> 8;
141 eaddr_tmp = eeprom_read(iobase, EE_Eth_Addr_Hi);
142 enaddr[1] = eaddr_tmp & 0xff;
143 enaddr[0] = eaddr_tmp >> 8;
144
145 return;
146}
147
148int
149ex_card_type (u_char *enaddr)
150{
151 if ((enaddr[0] == 0x00) && (enaddr[1] == 0xA0) && (enaddr[2] == 0xC9))
152 return (CARD_TYPE_EX_10_PLUS);
153
154 return (CARD_TYPE_EX_10);
155}
156
157/*
158 * Caller is responsible for eventually calling
159 * ex_release_resources() on failure.
160 */
161int
162ex_alloc_resources (device_t dev)
163{
164 struct ex_softc * sc = device_get_softc(dev);
165 int error = 0;
166
167 sc->ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->ioport_rid,
168 0, ~0, 1, RF_ACTIVE);
169 if (!sc->ioport) {
170 device_printf(dev, "No I/O space?!\n");
171 error = ENOMEM;
172 goto bad;
173 }
174
175 sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
176 0, ~0, 1, RF_ACTIVE);
177
178 if (!sc->irq) {
179 device_printf(dev, "No IRQ?!\n");
180 error = ENOMEM;
181 goto bad;
182 }
183
184bad:
185 return (error);
186}
187
188void
189ex_release_resources (device_t dev)
190{
191 struct ex_softc * sc = device_get_softc(dev);
192
193 if (sc->ih) {
194 bus_teardown_intr(dev, sc->irq, sc->ih);
195 sc->ih = NULL;
196 }
197
198 if (sc->ioport) {
199 bus_release_resource(dev, SYS_RES_IOPORT,
200 sc->ioport_rid, sc->ioport);
201 sc->ioport = NULL;
202 }
203
204 if (sc->irq) {
205 bus_release_resource(dev, SYS_RES_IRQ,
206 sc->irq_rid, sc->irq);
207 sc->irq = NULL;
208 }
209
210 return;
211}
212
213int
214ex_attach(device_t dev)
215{
216 struct ex_softc * sc = device_get_softc(dev);
217 struct ifnet * ifp = &sc->arpcom.ac_if;
218 struct ifmedia * ifm;
219 int unit = device_get_unit(dev);
220 u_int16_t temp;
221
222 /* work out which set of irq <-> internal tables to use */
223 if (ex_card_type(sc->arpcom.ac_enaddr) == CARD_TYPE_EX_10_PLUS) {
224 sc->irq2ee = plus_irq2eemap;
225 sc->ee2irq = plus_ee2irqmap;
226 } else {
227 sc->irq2ee = irq2eemap;
228 sc->ee2irq = ee2irqmap;
229 }
230
231 sc->mem_size = CARD_RAM_SIZE; /* XXX This should be read from the card itself. */
232
233 /*
234 * Initialize the ifnet structure.
235 */
236 ifp->if_softc = sc;
237 ifp->if_unit = unit;
238 ifp->if_name = "ex";
239 ifp->if_mtu = ETHERMTU;
240 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST /* XXX not done yet. | IFF_MULTICAST */;
241 ifp->if_output = ether_output;
242 ifp->if_start = ex_start;
243 ifp->if_ioctl = ex_ioctl;
244 ifp->if_watchdog = ex_watchdog;
245 ifp->if_init = ex_init;
246 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
247
248 ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts);
249
250 temp = eeprom_read(sc->iobase, EE_W5);
251 if (temp & EE_W5_PORT_TPE)
252 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
253 if (temp & EE_W5_PORT_BNC)
254 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL);
255 if (temp & EE_W5_PORT_AUI)
256 ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL);
257
258 ifmedia_set(&sc->ifmedia, ex_get_media(sc->iobase));
259
260 ifm = &sc->ifmedia;
261 ifm->ifm_media = ifm->ifm_cur->ifm_media;
262 ex_ifmedia_upd(ifp);
263
264 /*
265 * Attach the interface.
266 */
267 if_attach(ifp);
268 ether_ifattach(ifp);
267 ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
269
270 device_printf(sc->dev, "Ethernet address %6D\n",
271 sc->arpcom.ac_enaddr, ":");
268
269 device_printf(sc->dev, "Ethernet address %6D\n",
270 sc->arpcom.ac_enaddr, ":");
272 /*
273 * If BPF is in the kernel, call the attach for it
274 */
275 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
276
277 return(0);
278}
279
280static void
281ex_init(void *xsc)
282{
283 struct ex_softc * sc = (struct ex_softc *) xsc;
284 struct ifnet * ifp = &sc->arpcom.ac_if;
285 int s;
286 int i;
287 register int iobase = sc->iobase;
288 unsigned short temp_reg;
289
290 DODEBUG(Start_End, printf("ex_init%d: start\n", ifp->if_unit););
291
292 if (ifp->if_addrhead.tqh_first == NULL) {
293 return;
294 }
295 s = splimp();
296 ifp->if_timer = 0;
297
298 /*
299 * Load the ethernet address into the card.
300 */
301 outb(iobase + CMD_REG, Bank2_Sel);
302 temp_reg = inb(iobase + EEPROM_REG);
303 if (temp_reg & Trnoff_Enable) {
304 outb(iobase + EEPROM_REG, temp_reg & ~Trnoff_Enable);
305 }
306 for (i = 0; i < ETHER_ADDR_LEN; i++) {
307 outb(iobase + I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]);
308 }
309 /*
310 * - Setup transmit chaining and discard bad received frames.
311 * - Match broadcast.
312 * - Clear test mode.
313 * - Set receiving mode.
314 * - Set IRQ number.
315 */
316 outb(iobase + REG1, inb(iobase + REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp | Disc_Bad_Fr);
317 outb(iobase + REG2, inb(iobase + REG2) | No_SA_Ins | RX_CRC_InMem);
318 outb(iobase + REG3, inb(iobase + REG3) & 0x3f /* XXX constants. */ );
319 outb(iobase + CMD_REG, Bank1_Sel);
320 outb(iobase + INT_NO_REG, (inb(iobase + INT_NO_REG) & 0xf8) | sc->irq2ee[sc->irq_no]);
321
322 /*
323 * Divide the available memory in the card into rcv and xmt buffers.
324 * By default, I use the first 3/4 of the memory for the rcv buffer,
325 * and the remaining 1/4 of the memory for the xmt buffer.
326 */
327 sc->rx_mem_size = sc->mem_size * 3 / 4;
328 sc->tx_mem_size = sc->mem_size - sc->rx_mem_size;
329 sc->rx_lower_limit = 0x0000;
330 sc->rx_upper_limit = sc->rx_mem_size - 2;
331 sc->tx_lower_limit = sc->rx_mem_size;
332 sc->tx_upper_limit = sc->mem_size - 2;
333 outb(iobase + RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8);
334 outb(iobase + RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8);
335 outb(iobase + XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8);
336 outb(iobase + XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8);
337
338 /*
339 * Enable receive and transmit interrupts, and clear any pending int.
340 */
341 outb(iobase + REG1, inb(iobase + REG1) | TriST_INT);
342 outb(iobase + CMD_REG, Bank0_Sel);
343 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
344 outb(iobase + STATUS_REG, All_Int);
345
346 /*
347 * Initialize receive and transmit ring buffers.
348 */
349 outw(iobase + RCV_BAR, sc->rx_lower_limit);
350 sc->rx_head = sc->rx_lower_limit;
351 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit | 0xfe);
352 outw(iobase + XMT_BAR, sc->tx_lower_limit);
353 sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
354
355 ifp->if_flags |= IFF_RUNNING;
356 ifp->if_flags &= ~IFF_OACTIVE;
357 DODEBUG(Status, printf("OIDLE init\n"););
358
359 /*
360 * Final reset of the board, and enable operation.
361 */
362 outb(iobase + CMD_REG, Sel_Reset_CMD);
363 DELAY(2);
364 outb(iobase + CMD_REG, Rcv_Enable_CMD);
365
366 ex_start(ifp);
367 splx(s);
368
369 DODEBUG(Start_End, printf("ex_init%d: finish\n", ifp->if_unit););
370}
371
372
373static void
374ex_start(struct ifnet *ifp)
375{
376 struct ex_softc * sc = ifp->if_softc;
377 int iobase = sc->iobase;
378 int i, s, len, data_len, avail, dest, next;
379 unsigned char tmp16[2];
380 struct mbuf * opkt;
381 struct mbuf * m;
382
383 DODEBUG(Start_End, printf("ex_start%d: start\n", unit););
384
385 s = splimp();
386
387 /*
388 * Main loop: send outgoing packets to network card until there are no
389 * more packets left, or the card cannot accept any more yet.
390 */
391 while (((opkt = ifp->if_snd.ifq_head) != NULL) &&
392 !(ifp->if_flags & IFF_OACTIVE)) {
393
394 /*
395 * Ensure there is enough free transmit buffer space for
396 * this packet, including its header. Note: the header
397 * cannot wrap around the end of the transmit buffer and
398 * must be kept together, so we allow space for twice the
399 * length of the header, just in case.
400 */
401
402 for (len = 0, m = opkt; m != NULL; m = m->m_next) {
403 len += m->m_len;
404 }
405
406 data_len = len;
407
408 DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len););
409
410 if (len & 1) {
411 len += XMT_HEADER_LEN + 1;
412 } else {
413 len += XMT_HEADER_LEN;
414 }
415
416 if ((i = sc->tx_tail - sc->tx_head) >= 0) {
417 avail = sc->tx_mem_size - i;
418 } else {
419 avail = -i;
420 }
421
422 DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
423
424 if (avail >= len + XMT_HEADER_LEN) {
425 IF_DEQUEUE(&ifp->if_snd, opkt);
426
427#ifdef EX_PSA_INTR
428 /*
429 * Disable rx and tx interrupts, to avoid corruption
430 * of the host address register by interrupt service
431 * routines.
432 * XXX Is this necessary with splimp() enabled?
433 */
434 outb(iobase + MASK_REG, All_Int);
435#endif
436
437 /*
438 * Compute the start and end addresses of this
439 * frame in the tx buffer.
440 */
441 dest = sc->tx_tail;
442 next = dest + len;
443
444 if (next > sc->tx_upper_limit) {
445 if ((sc->tx_upper_limit + 2 - sc->tx_tail) <=
446 XMT_HEADER_LEN) {
447 dest = sc->tx_lower_limit;
448 next = dest + len;
449 } else {
450 next = sc->tx_lower_limit +
451 next - sc->tx_upper_limit - 2;
452 }
453 }
454
455 /*
456 * Build the packet frame in the card's ring buffer.
457 */
458 DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next););
459
460 outw(iobase + HOST_ADDR_REG, dest);
461 outw(iobase + IO_PORT_REG, Transmit_CMD);
462 outw(iobase + IO_PORT_REG, 0);
463 outw(iobase + IO_PORT_REG, next);
464 outw(iobase + IO_PORT_REG, data_len);
465
466 /*
467 * Output the packet data to the card. Ensure all
468 * transfers are 16-bit wide, even if individual
469 * mbufs have odd length.
470 */
471
472 for (m = opkt, i = 0; m != NULL; m = m->m_next) {
473 DODEBUG(Sent_Pkts, printf("[%d]", m->m_len););
474 if (i) {
475 tmp16[1] = *(mtod(m, caddr_t));
476 outsw(iobase + IO_PORT_REG, tmp16, 1);
477 }
478 outsw(iobase + IO_PORT_REG,
479 mtod(m, caddr_t) + i, (m->m_len - i) / 2);
480
481 if ((i = (m->m_len - i) & 1) != 0) {
482 tmp16[0] = *(mtod(m, caddr_t) +
483 m->m_len - 1);
484 }
485 }
486 if (i) {
487 outsw(iobase + IO_PORT_REG, tmp16, 1);
488 }
489
490 /*
491 * If there were other frames chained, update the
492 * chain in the last one.
493 */
494 if (sc->tx_head != sc->tx_tail) {
495 if (sc->tx_tail != dest) {
496 outw(iobase + HOST_ADDR_REG,
497 sc->tx_last + XMT_Chain_Point);
498 outw(iobase + IO_PORT_REG, dest);
499 }
500 outw(iobase + HOST_ADDR_REG,
501 sc->tx_last + XMT_Byte_Count);
502 i = inw(iobase + IO_PORT_REG);
503 outw(iobase + HOST_ADDR_REG,
504 sc->tx_last + XMT_Byte_Count);
505 outw(iobase + IO_PORT_REG, i | Ch_bit);
506 }
507
508 /*
509 * Resume normal operation of the card:
510 * - Make a dummy read to flush the DRAM write
511 * pipeline.
512 * - Enable receive and transmit interrupts.
513 * - Send Transmit or Resume_XMT command, as
514 * appropriate.
515 */
516 inw(iobase + IO_PORT_REG);
517#ifdef EX_PSA_INTR
518 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
519#endif
520 if (sc->tx_head == sc->tx_tail) {
521 outw(iobase + XMT_BAR, dest);
522 outb(iobase + CMD_REG, Transmit_CMD);
523 sc->tx_head = dest;
524 DODEBUG(Sent_Pkts, printf("Transmit\n"););
525 } else {
526 outb(iobase + CMD_REG, Resume_XMT_List_CMD);
527 DODEBUG(Sent_Pkts, printf("Resume\n"););
528 }
529
530 sc->tx_last = dest;
531 sc->tx_tail = next;
532
533 if (ifp->if_bpf != NULL) {
534 bpf_mtap(ifp, opkt);
535 }
536
537 ifp->if_timer = 2;
538 ifp->if_opackets++;
539 m_freem(opkt);
540 } else {
541 ifp->if_flags |= IFF_OACTIVE;
542 DODEBUG(Status, printf("OACTIVE start\n"););
543 }
544 }
545
546 splx(s);
547
548 DODEBUG(Start_End, printf("ex_start%d: finish\n", unit););
549}
550
551static void
552ex_stop(struct ex_softc *sc)
553{
554 int iobase = sc->iobase;
555
556 DODEBUG(Start_End, printf("ex_stop%d: start\n", unit););
557
558 /*
559 * Disable card operation:
560 * - Disable the interrupt line.
561 * - Flush transmission and disable reception.
562 * - Mask and clear all interrupts.
563 * - Reset the 82595.
564 */
565 outb(iobase + CMD_REG, Bank1_Sel);
566 outb(iobase + REG1, inb(iobase + REG1) & ~TriST_INT);
567 outb(iobase + CMD_REG, Bank0_Sel);
568 outb(iobase + CMD_REG, Rcv_Stop);
569 sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
570 sc->tx_last = 0; /* XXX I think these two lines are not necessary, because ex_init will always be called again to reinit the interface. */
571 outb(iobase + MASK_REG, All_Int);
572 outb(iobase + STATUS_REG, All_Int);
573 outb(iobase + CMD_REG, Reset_CMD);
574 DELAY(200);
575
576 DODEBUG(Start_End, printf("ex_stop%d: finish\n", unit););
577
578 return;
579}
580
581void
582ex_intr(void *arg)
583{
584 struct ex_softc * sc = (struct ex_softc *)arg;
585 struct ifnet * ifp = &sc->arpcom.ac_if;
586 int iobase = sc->iobase;
587 int int_status, send_pkts;
588
589 DODEBUG(Start_End, printf("ex_intr%d: start\n", unit););
590
591#ifdef EXDEBUG
592 if (++exintr_count != 1)
593 printf("WARNING: nested interrupt (%d). Mail the author.\n", exintr_count);
594#endif
595
596 send_pkts = 0;
597 while ((int_status = inb(iobase + STATUS_REG)) & (Tx_Int | Rx_Int)) {
598 if (int_status & Rx_Int) {
599 outb(iobase + STATUS_REG, Rx_Int);
600
601 ex_rx_intr(sc);
602 } else if (int_status & Tx_Int) {
603 outb(iobase + STATUS_REG, Tx_Int);
604
605 ex_tx_intr(sc);
606 send_pkts = 1;
607 }
608 }
609
610 /*
611 * If any packet has been transmitted, and there are queued packets to
612 * be sent, attempt to send more packets to the network card.
613 */
614
615 if (send_pkts && (ifp->if_snd.ifq_head != NULL)) {
616 ex_start(ifp);
617 }
618
619#ifdef EXDEBUG
620 exintr_count--;
621#endif
622
623 DODEBUG(Start_End, printf("ex_intr%d: finish\n", unit););
624
625 return;
626}
627
628static void
629ex_tx_intr(struct ex_softc *sc)
630{
631 struct ifnet * ifp = &sc->arpcom.ac_if;
632 int iobase = sc->iobase;
633 int tx_status;
634
635 DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", unit););
636
637 /*
638 * - Cancel the watchdog.
639 * For all packets transmitted since last transmit interrupt:
640 * - Advance chain pointer to next queued packet.
641 * - Update statistics.
642 */
643
644 ifp->if_timer = 0;
645
646 while (sc->tx_head != sc->tx_tail) {
647 outw(iobase + HOST_ADDR_REG, sc->tx_head);
648
649 if (! inw(iobase + IO_PORT_REG) & Done_bit)
650 break;
651
652 tx_status = inw(iobase + IO_PORT_REG);
653 sc->tx_head = inw(iobase + IO_PORT_REG);
654
655 if (tx_status & TX_OK_bit) {
656 ifp->if_opackets++;
657 } else {
658 ifp->if_oerrors++;
659 }
660
661 ifp->if_collisions += tx_status & No_Collisions_bits;
662 }
663
664 /*
665 * The card should be ready to accept more packets now.
666 */
667
668 ifp->if_flags &= ~IFF_OACTIVE;
669
670 DODEBUG(Status, printf("OIDLE tx_intr\n"););
671 DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", unit););
672
673 return;
674}
675
676static void
677ex_rx_intr(struct ex_softc *sc)
678{
679 struct ifnet * ifp = &sc->arpcom.ac_if;
680 int iobase = sc->iobase;
681 int rx_status;
682 int pkt_len;
683 int QQQ;
684 struct mbuf * m;
685 struct mbuf * ipkt;
686 struct ether_header * eh;
687
688 DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", unit););
689
690 /*
691 * For all packets received since last receive interrupt:
692 * - If packet ok, read it into a new mbuf and queue it to interface,
693 * updating statistics.
694 * - If packet bad, just discard it, and update statistics.
695 * Finally, advance receive stop limit in card's memory to new location.
696 */
697
698 outw(iobase + HOST_ADDR_REG, sc->rx_head);
699
700 while (inw(iobase + IO_PORT_REG) == RCV_Done) {
701
702 rx_status = inw(iobase + IO_PORT_REG);
703 sc->rx_head = inw(iobase + IO_PORT_REG);
704 QQQ = pkt_len = inw(iobase + IO_PORT_REG);
705
706 if (rx_status & RCV_OK_bit) {
707 MGETHDR(m, M_DONTWAIT, MT_DATA);
708 ipkt = m;
709 if (ipkt == NULL) {
710 ifp->if_iqdrops++;
711 } else {
712 ipkt->m_pkthdr.rcvif = ifp;
713 ipkt->m_pkthdr.len = pkt_len;
714 ipkt->m_len = MHLEN;
715
716 while (pkt_len > 0) {
717 if (pkt_len > MINCLSIZE) {
718 MCLGET(m, M_DONTWAIT);
719 if (m->m_flags & M_EXT) {
720 m->m_len = MCLBYTES;
721 } else {
722 m_freem(ipkt);
723 ifp->if_iqdrops++;
724 goto rx_another;
725 }
726 }
727 m->m_len = min(m->m_len, pkt_len);
728
729 /*
730 * NOTE: I'm assuming that all mbufs allocated are of even length,
731 * except for the last one in an odd-length packet.
732 */
733
734 insw(iobase + IO_PORT_REG,
735 mtod(m, caddr_t), m->m_len / 2);
736
737 if (m->m_len & 1) {
738 *(mtod(m, caddr_t) + m->m_len - 1) = inb(iobase + IO_PORT_REG);
739 }
740 pkt_len -= m->m_len;
741
742 if (pkt_len > 0) {
743 MGET(m->m_next, M_DONTWAIT, MT_DATA);
744 if (m->m_next == NULL) {
745 m_freem(ipkt);
746 ifp->if_iqdrops++;
747 goto rx_another;
748 }
749 m = m->m_next;
750 m->m_len = MLEN;
751 }
752 }
753 eh = mtod(ipkt, struct ether_header *);
754#ifdef EXDEBUG
755 if (debug_mask & Rcvd_Pkts) {
756 if ((eh->ether_dhost[5] != 0xff) || (eh->ether_dhost[0] != 0xff)) {
757 printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":");
758 printf("%6D\n", eh->ether_dhost, ":");
759 } /* QQQ */
760 }
761#endif
762 m_adj(ipkt, sizeof(struct ether_header));
763 ether_input(ifp, eh, ipkt);
764 ifp->if_ipackets++;
765 }
766 } else {
767 ifp->if_ierrors++;
768 }
769 outw(iobase + HOST_ADDR_REG, sc->rx_head);
770rx_another: ;
771 }
772
773 if (sc->rx_head < sc->rx_lower_limit + 2)
774 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit);
775 else
776 outw(iobase + RCV_STOP_REG, sc->rx_head - 2);
777
778 DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", unit););
779
780 return;
781}
782
783
784static int
785ex_ioctl(register struct ifnet *ifp, u_long cmd, caddr_t data)
786{
787 struct ex_softc * sc = ifp->if_softc;
788 struct ifreq * ifr = (struct ifreq *)data;
789 int s;
790 int error = 0;
791
792 DODEBUG(Start_End, printf("ex_ioctl%d: start ", ifp->if_unit););
793
794 s = splimp();
795
796 switch(cmd) {
797 case SIOCSIFADDR:
798 case SIOCGIFADDR:
799 case SIOCSIFMTU:
800 error = ether_ioctl(ifp, cmd, data);
801 break;
802
803 case SIOCSIFFLAGS:
804 DODEBUG(Start_End, printf("SIOCSIFFLAGS"););
805 if ((ifp->if_flags & IFF_UP) == 0 &&
806 (ifp->if_flags & IFF_RUNNING)) {
807
808 ifp->if_flags &= ~IFF_RUNNING;
809 ex_stop(sc);
810 } else {
811 ex_init(sc);
812 }
813 break;
814#ifdef NODEF
815 case SIOCGHWADDR:
816 DODEBUG(Start_End, printf("SIOCGHWADDR"););
817 bcopy((caddr_t)sc->sc_addr, (caddr_t)&ifr->ifr_data,
818 sizeof(sc->sc_addr));
819 break;
820#endif
821 case SIOCADDMULTI:
822 DODEBUG(Start_End, printf("SIOCADDMULTI"););
823 case SIOCDELMULTI:
824 DODEBUG(Start_End, printf("SIOCDELMULTI"););
825 /* XXX Support not done yet. */
826 error = EINVAL;
827 break;
828 case SIOCSIFMEDIA:
829 case SIOCGIFMEDIA:
830 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
831 break;
832 default:
833 DODEBUG(Start_End, printf("unknown"););
834 error = EINVAL;
835 }
836
837 splx(s);
838
839 DODEBUG(Start_End, printf("\nex_ioctl%d: finish\n", ifp->if_unit););
840
841 return(error);
842}
843
844
845static void
846ex_reset(struct ex_softc *sc)
847{
848 int s;
849
850 DODEBUG(Start_End, printf("ex_reset%d: start\n", unit););
851
852 s = splimp();
853
854 ex_stop(sc);
855 ex_init(sc);
856
857 splx(s);
858
859 DODEBUG(Start_End, printf("ex_reset%d: finish\n", unit););
860
861 return;
862}
863
864static void
865ex_watchdog(struct ifnet *ifp)
866{
867 struct ex_softc * sc = ifp->if_softc;
868
869 DODEBUG(Start_End, printf("ex_watchdog%d: start\n", ifp->if_unit););
870
871 ifp->if_flags &= ~IFF_OACTIVE;
872
873 DODEBUG(Status, printf("OIDLE watchdog\n"););
874
875 ifp->if_oerrors++;
876 ex_reset(sc);
877 ex_start(ifp);
878
879 DODEBUG(Start_End, printf("ex_watchdog%d: finish\n", ifp->if_unit););
880
881 return;
882}
883
884static int
885ex_get_media (u_int32_t iobase)
886{
887 int tmp;
888
889 outb(iobase + CMD_REG, Bank2_Sel);
890 tmp = inb(iobase + REG3);
891 outb(iobase + CMD_REG, Bank0_Sel);
892
893 if (tmp & TPE_bit)
894 return(IFM_ETHER|IFM_10_T);
895 if (tmp & BNC_bit)
896 return(IFM_ETHER|IFM_10_2);
897
898 return (IFM_ETHER|IFM_10_5);
899}
900
901static int
902ex_ifmedia_upd (ifp)
903 struct ifnet * ifp;
904{
905 struct ex_softc * sc = ifp->if_softc;
906
907 return (0);
908}
909
910static void
911ex_ifmedia_sts(ifp, ifmr)
912 struct ifnet * ifp;
913 struct ifmediareq * ifmr;
914{
915 struct ex_softc * sc = ifp->if_softc;
916
917 ifmr->ifm_active = ex_get_media(sc->iobase);
918
919 return;
920}
921
922u_short
923eeprom_read(u_int32_t iobase, int location)
924{
925 int i;
926 u_short data = 0;
927 int ee_addr;
928 int read_cmd = location | EE_READ_CMD;
929 short ctrl_val = EECS;
930
931 ee_addr = iobase + EEPROM_REG;
932 outb(iobase + CMD_REG, Bank2_Sel);
933 outb(ee_addr, EECS);
934 for (i = 8; i >= 0; i--) {
935 short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val;
936 outb(ee_addr, outval);
937 outb(ee_addr, outval | EESK);
938 DELAY(3);
939 outb(ee_addr, outval);
940 DELAY(2);
941 }
942 outb(ee_addr, ctrl_val);
943
944 for (i = 16; i > 0; i--) {
945 outb(ee_addr, ctrl_val | EESK);
946 DELAY(3);
947 data = (data << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
948 outb(ee_addr, ctrl_val);
949 DELAY(2);
950 }
951
952 ctrl_val &= ~EECS;
953 outb(ee_addr, ctrl_val | EESK);
954 DELAY(3);
955 outb(ee_addr, ctrl_val);
956 DELAY(2);
957 outb(iobase + CMD_REG, Bank0_Sel);
958 return(data);
959}
271
272 return(0);
273}
274
275static void
276ex_init(void *xsc)
277{
278 struct ex_softc * sc = (struct ex_softc *) xsc;
279 struct ifnet * ifp = &sc->arpcom.ac_if;
280 int s;
281 int i;
282 register int iobase = sc->iobase;
283 unsigned short temp_reg;
284
285 DODEBUG(Start_End, printf("ex_init%d: start\n", ifp->if_unit););
286
287 if (ifp->if_addrhead.tqh_first == NULL) {
288 return;
289 }
290 s = splimp();
291 ifp->if_timer = 0;
292
293 /*
294 * Load the ethernet address into the card.
295 */
296 outb(iobase + CMD_REG, Bank2_Sel);
297 temp_reg = inb(iobase + EEPROM_REG);
298 if (temp_reg & Trnoff_Enable) {
299 outb(iobase + EEPROM_REG, temp_reg & ~Trnoff_Enable);
300 }
301 for (i = 0; i < ETHER_ADDR_LEN; i++) {
302 outb(iobase + I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]);
303 }
304 /*
305 * - Setup transmit chaining and discard bad received frames.
306 * - Match broadcast.
307 * - Clear test mode.
308 * - Set receiving mode.
309 * - Set IRQ number.
310 */
311 outb(iobase + REG1, inb(iobase + REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp | Disc_Bad_Fr);
312 outb(iobase + REG2, inb(iobase + REG2) | No_SA_Ins | RX_CRC_InMem);
313 outb(iobase + REG3, inb(iobase + REG3) & 0x3f /* XXX constants. */ );
314 outb(iobase + CMD_REG, Bank1_Sel);
315 outb(iobase + INT_NO_REG, (inb(iobase + INT_NO_REG) & 0xf8) | sc->irq2ee[sc->irq_no]);
316
317 /*
318 * Divide the available memory in the card into rcv and xmt buffers.
319 * By default, I use the first 3/4 of the memory for the rcv buffer,
320 * and the remaining 1/4 of the memory for the xmt buffer.
321 */
322 sc->rx_mem_size = sc->mem_size * 3 / 4;
323 sc->tx_mem_size = sc->mem_size - sc->rx_mem_size;
324 sc->rx_lower_limit = 0x0000;
325 sc->rx_upper_limit = sc->rx_mem_size - 2;
326 sc->tx_lower_limit = sc->rx_mem_size;
327 sc->tx_upper_limit = sc->mem_size - 2;
328 outb(iobase + RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8);
329 outb(iobase + RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8);
330 outb(iobase + XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8);
331 outb(iobase + XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8);
332
333 /*
334 * Enable receive and transmit interrupts, and clear any pending int.
335 */
336 outb(iobase + REG1, inb(iobase + REG1) | TriST_INT);
337 outb(iobase + CMD_REG, Bank0_Sel);
338 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
339 outb(iobase + STATUS_REG, All_Int);
340
341 /*
342 * Initialize receive and transmit ring buffers.
343 */
344 outw(iobase + RCV_BAR, sc->rx_lower_limit);
345 sc->rx_head = sc->rx_lower_limit;
346 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit | 0xfe);
347 outw(iobase + XMT_BAR, sc->tx_lower_limit);
348 sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
349
350 ifp->if_flags |= IFF_RUNNING;
351 ifp->if_flags &= ~IFF_OACTIVE;
352 DODEBUG(Status, printf("OIDLE init\n"););
353
354 /*
355 * Final reset of the board, and enable operation.
356 */
357 outb(iobase + CMD_REG, Sel_Reset_CMD);
358 DELAY(2);
359 outb(iobase + CMD_REG, Rcv_Enable_CMD);
360
361 ex_start(ifp);
362 splx(s);
363
364 DODEBUG(Start_End, printf("ex_init%d: finish\n", ifp->if_unit););
365}
366
367
368static void
369ex_start(struct ifnet *ifp)
370{
371 struct ex_softc * sc = ifp->if_softc;
372 int iobase = sc->iobase;
373 int i, s, len, data_len, avail, dest, next;
374 unsigned char tmp16[2];
375 struct mbuf * opkt;
376 struct mbuf * m;
377
378 DODEBUG(Start_End, printf("ex_start%d: start\n", unit););
379
380 s = splimp();
381
382 /*
383 * Main loop: send outgoing packets to network card until there are no
384 * more packets left, or the card cannot accept any more yet.
385 */
386 while (((opkt = ifp->if_snd.ifq_head) != NULL) &&
387 !(ifp->if_flags & IFF_OACTIVE)) {
388
389 /*
390 * Ensure there is enough free transmit buffer space for
391 * this packet, including its header. Note: the header
392 * cannot wrap around the end of the transmit buffer and
393 * must be kept together, so we allow space for twice the
394 * length of the header, just in case.
395 */
396
397 for (len = 0, m = opkt; m != NULL; m = m->m_next) {
398 len += m->m_len;
399 }
400
401 data_len = len;
402
403 DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len););
404
405 if (len & 1) {
406 len += XMT_HEADER_LEN + 1;
407 } else {
408 len += XMT_HEADER_LEN;
409 }
410
411 if ((i = sc->tx_tail - sc->tx_head) >= 0) {
412 avail = sc->tx_mem_size - i;
413 } else {
414 avail = -i;
415 }
416
417 DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
418
419 if (avail >= len + XMT_HEADER_LEN) {
420 IF_DEQUEUE(&ifp->if_snd, opkt);
421
422#ifdef EX_PSA_INTR
423 /*
424 * Disable rx and tx interrupts, to avoid corruption
425 * of the host address register by interrupt service
426 * routines.
427 * XXX Is this necessary with splimp() enabled?
428 */
429 outb(iobase + MASK_REG, All_Int);
430#endif
431
432 /*
433 * Compute the start and end addresses of this
434 * frame in the tx buffer.
435 */
436 dest = sc->tx_tail;
437 next = dest + len;
438
439 if (next > sc->tx_upper_limit) {
440 if ((sc->tx_upper_limit + 2 - sc->tx_tail) <=
441 XMT_HEADER_LEN) {
442 dest = sc->tx_lower_limit;
443 next = dest + len;
444 } else {
445 next = sc->tx_lower_limit +
446 next - sc->tx_upper_limit - 2;
447 }
448 }
449
450 /*
451 * Build the packet frame in the card's ring buffer.
452 */
453 DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next););
454
455 outw(iobase + HOST_ADDR_REG, dest);
456 outw(iobase + IO_PORT_REG, Transmit_CMD);
457 outw(iobase + IO_PORT_REG, 0);
458 outw(iobase + IO_PORT_REG, next);
459 outw(iobase + IO_PORT_REG, data_len);
460
461 /*
462 * Output the packet data to the card. Ensure all
463 * transfers are 16-bit wide, even if individual
464 * mbufs have odd length.
465 */
466
467 for (m = opkt, i = 0; m != NULL; m = m->m_next) {
468 DODEBUG(Sent_Pkts, printf("[%d]", m->m_len););
469 if (i) {
470 tmp16[1] = *(mtod(m, caddr_t));
471 outsw(iobase + IO_PORT_REG, tmp16, 1);
472 }
473 outsw(iobase + IO_PORT_REG,
474 mtod(m, caddr_t) + i, (m->m_len - i) / 2);
475
476 if ((i = (m->m_len - i) & 1) != 0) {
477 tmp16[0] = *(mtod(m, caddr_t) +
478 m->m_len - 1);
479 }
480 }
481 if (i) {
482 outsw(iobase + IO_PORT_REG, tmp16, 1);
483 }
484
485 /*
486 * If there were other frames chained, update the
487 * chain in the last one.
488 */
489 if (sc->tx_head != sc->tx_tail) {
490 if (sc->tx_tail != dest) {
491 outw(iobase + HOST_ADDR_REG,
492 sc->tx_last + XMT_Chain_Point);
493 outw(iobase + IO_PORT_REG, dest);
494 }
495 outw(iobase + HOST_ADDR_REG,
496 sc->tx_last + XMT_Byte_Count);
497 i = inw(iobase + IO_PORT_REG);
498 outw(iobase + HOST_ADDR_REG,
499 sc->tx_last + XMT_Byte_Count);
500 outw(iobase + IO_PORT_REG, i | Ch_bit);
501 }
502
503 /*
504 * Resume normal operation of the card:
505 * - Make a dummy read to flush the DRAM write
506 * pipeline.
507 * - Enable receive and transmit interrupts.
508 * - Send Transmit or Resume_XMT command, as
509 * appropriate.
510 */
511 inw(iobase + IO_PORT_REG);
512#ifdef EX_PSA_INTR
513 outb(iobase + MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
514#endif
515 if (sc->tx_head == sc->tx_tail) {
516 outw(iobase + XMT_BAR, dest);
517 outb(iobase + CMD_REG, Transmit_CMD);
518 sc->tx_head = dest;
519 DODEBUG(Sent_Pkts, printf("Transmit\n"););
520 } else {
521 outb(iobase + CMD_REG, Resume_XMT_List_CMD);
522 DODEBUG(Sent_Pkts, printf("Resume\n"););
523 }
524
525 sc->tx_last = dest;
526 sc->tx_tail = next;
527
528 if (ifp->if_bpf != NULL) {
529 bpf_mtap(ifp, opkt);
530 }
531
532 ifp->if_timer = 2;
533 ifp->if_opackets++;
534 m_freem(opkt);
535 } else {
536 ifp->if_flags |= IFF_OACTIVE;
537 DODEBUG(Status, printf("OACTIVE start\n"););
538 }
539 }
540
541 splx(s);
542
543 DODEBUG(Start_End, printf("ex_start%d: finish\n", unit););
544}
545
546static void
547ex_stop(struct ex_softc *sc)
548{
549 int iobase = sc->iobase;
550
551 DODEBUG(Start_End, printf("ex_stop%d: start\n", unit););
552
553 /*
554 * Disable card operation:
555 * - Disable the interrupt line.
556 * - Flush transmission and disable reception.
557 * - Mask and clear all interrupts.
558 * - Reset the 82595.
559 */
560 outb(iobase + CMD_REG, Bank1_Sel);
561 outb(iobase + REG1, inb(iobase + REG1) & ~TriST_INT);
562 outb(iobase + CMD_REG, Bank0_Sel);
563 outb(iobase + CMD_REG, Rcv_Stop);
564 sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
565 sc->tx_last = 0; /* XXX I think these two lines are not necessary, because ex_init will always be called again to reinit the interface. */
566 outb(iobase + MASK_REG, All_Int);
567 outb(iobase + STATUS_REG, All_Int);
568 outb(iobase + CMD_REG, Reset_CMD);
569 DELAY(200);
570
571 DODEBUG(Start_End, printf("ex_stop%d: finish\n", unit););
572
573 return;
574}
575
576void
577ex_intr(void *arg)
578{
579 struct ex_softc * sc = (struct ex_softc *)arg;
580 struct ifnet * ifp = &sc->arpcom.ac_if;
581 int iobase = sc->iobase;
582 int int_status, send_pkts;
583
584 DODEBUG(Start_End, printf("ex_intr%d: start\n", unit););
585
586#ifdef EXDEBUG
587 if (++exintr_count != 1)
588 printf("WARNING: nested interrupt (%d). Mail the author.\n", exintr_count);
589#endif
590
591 send_pkts = 0;
592 while ((int_status = inb(iobase + STATUS_REG)) & (Tx_Int | Rx_Int)) {
593 if (int_status & Rx_Int) {
594 outb(iobase + STATUS_REG, Rx_Int);
595
596 ex_rx_intr(sc);
597 } else if (int_status & Tx_Int) {
598 outb(iobase + STATUS_REG, Tx_Int);
599
600 ex_tx_intr(sc);
601 send_pkts = 1;
602 }
603 }
604
605 /*
606 * If any packet has been transmitted, and there are queued packets to
607 * be sent, attempt to send more packets to the network card.
608 */
609
610 if (send_pkts && (ifp->if_snd.ifq_head != NULL)) {
611 ex_start(ifp);
612 }
613
614#ifdef EXDEBUG
615 exintr_count--;
616#endif
617
618 DODEBUG(Start_End, printf("ex_intr%d: finish\n", unit););
619
620 return;
621}
622
623static void
624ex_tx_intr(struct ex_softc *sc)
625{
626 struct ifnet * ifp = &sc->arpcom.ac_if;
627 int iobase = sc->iobase;
628 int tx_status;
629
630 DODEBUG(Start_End, printf("ex_tx_intr%d: start\n", unit););
631
632 /*
633 * - Cancel the watchdog.
634 * For all packets transmitted since last transmit interrupt:
635 * - Advance chain pointer to next queued packet.
636 * - Update statistics.
637 */
638
639 ifp->if_timer = 0;
640
641 while (sc->tx_head != sc->tx_tail) {
642 outw(iobase + HOST_ADDR_REG, sc->tx_head);
643
644 if (! inw(iobase + IO_PORT_REG) & Done_bit)
645 break;
646
647 tx_status = inw(iobase + IO_PORT_REG);
648 sc->tx_head = inw(iobase + IO_PORT_REG);
649
650 if (tx_status & TX_OK_bit) {
651 ifp->if_opackets++;
652 } else {
653 ifp->if_oerrors++;
654 }
655
656 ifp->if_collisions += tx_status & No_Collisions_bits;
657 }
658
659 /*
660 * The card should be ready to accept more packets now.
661 */
662
663 ifp->if_flags &= ~IFF_OACTIVE;
664
665 DODEBUG(Status, printf("OIDLE tx_intr\n"););
666 DODEBUG(Start_End, printf("ex_tx_intr%d: finish\n", unit););
667
668 return;
669}
670
671static void
672ex_rx_intr(struct ex_softc *sc)
673{
674 struct ifnet * ifp = &sc->arpcom.ac_if;
675 int iobase = sc->iobase;
676 int rx_status;
677 int pkt_len;
678 int QQQ;
679 struct mbuf * m;
680 struct mbuf * ipkt;
681 struct ether_header * eh;
682
683 DODEBUG(Start_End, printf("ex_rx_intr%d: start\n", unit););
684
685 /*
686 * For all packets received since last receive interrupt:
687 * - If packet ok, read it into a new mbuf and queue it to interface,
688 * updating statistics.
689 * - If packet bad, just discard it, and update statistics.
690 * Finally, advance receive stop limit in card's memory to new location.
691 */
692
693 outw(iobase + HOST_ADDR_REG, sc->rx_head);
694
695 while (inw(iobase + IO_PORT_REG) == RCV_Done) {
696
697 rx_status = inw(iobase + IO_PORT_REG);
698 sc->rx_head = inw(iobase + IO_PORT_REG);
699 QQQ = pkt_len = inw(iobase + IO_PORT_REG);
700
701 if (rx_status & RCV_OK_bit) {
702 MGETHDR(m, M_DONTWAIT, MT_DATA);
703 ipkt = m;
704 if (ipkt == NULL) {
705 ifp->if_iqdrops++;
706 } else {
707 ipkt->m_pkthdr.rcvif = ifp;
708 ipkt->m_pkthdr.len = pkt_len;
709 ipkt->m_len = MHLEN;
710
711 while (pkt_len > 0) {
712 if (pkt_len > MINCLSIZE) {
713 MCLGET(m, M_DONTWAIT);
714 if (m->m_flags & M_EXT) {
715 m->m_len = MCLBYTES;
716 } else {
717 m_freem(ipkt);
718 ifp->if_iqdrops++;
719 goto rx_another;
720 }
721 }
722 m->m_len = min(m->m_len, pkt_len);
723
724 /*
725 * NOTE: I'm assuming that all mbufs allocated are of even length,
726 * except for the last one in an odd-length packet.
727 */
728
729 insw(iobase + IO_PORT_REG,
730 mtod(m, caddr_t), m->m_len / 2);
731
732 if (m->m_len & 1) {
733 *(mtod(m, caddr_t) + m->m_len - 1) = inb(iobase + IO_PORT_REG);
734 }
735 pkt_len -= m->m_len;
736
737 if (pkt_len > 0) {
738 MGET(m->m_next, M_DONTWAIT, MT_DATA);
739 if (m->m_next == NULL) {
740 m_freem(ipkt);
741 ifp->if_iqdrops++;
742 goto rx_another;
743 }
744 m = m->m_next;
745 m->m_len = MLEN;
746 }
747 }
748 eh = mtod(ipkt, struct ether_header *);
749#ifdef EXDEBUG
750 if (debug_mask & Rcvd_Pkts) {
751 if ((eh->ether_dhost[5] != 0xff) || (eh->ether_dhost[0] != 0xff)) {
752 printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":");
753 printf("%6D\n", eh->ether_dhost, ":");
754 } /* QQQ */
755 }
756#endif
757 m_adj(ipkt, sizeof(struct ether_header));
758 ether_input(ifp, eh, ipkt);
759 ifp->if_ipackets++;
760 }
761 } else {
762 ifp->if_ierrors++;
763 }
764 outw(iobase + HOST_ADDR_REG, sc->rx_head);
765rx_another: ;
766 }
767
768 if (sc->rx_head < sc->rx_lower_limit + 2)
769 outw(iobase + RCV_STOP_REG, sc->rx_upper_limit);
770 else
771 outw(iobase + RCV_STOP_REG, sc->rx_head - 2);
772
773 DODEBUG(Start_End, printf("ex_rx_intr%d: finish\n", unit););
774
775 return;
776}
777
778
779static int
780ex_ioctl(register struct ifnet *ifp, u_long cmd, caddr_t data)
781{
782 struct ex_softc * sc = ifp->if_softc;
783 struct ifreq * ifr = (struct ifreq *)data;
784 int s;
785 int error = 0;
786
787 DODEBUG(Start_End, printf("ex_ioctl%d: start ", ifp->if_unit););
788
789 s = splimp();
790
791 switch(cmd) {
792 case SIOCSIFADDR:
793 case SIOCGIFADDR:
794 case SIOCSIFMTU:
795 error = ether_ioctl(ifp, cmd, data);
796 break;
797
798 case SIOCSIFFLAGS:
799 DODEBUG(Start_End, printf("SIOCSIFFLAGS"););
800 if ((ifp->if_flags & IFF_UP) == 0 &&
801 (ifp->if_flags & IFF_RUNNING)) {
802
803 ifp->if_flags &= ~IFF_RUNNING;
804 ex_stop(sc);
805 } else {
806 ex_init(sc);
807 }
808 break;
809#ifdef NODEF
810 case SIOCGHWADDR:
811 DODEBUG(Start_End, printf("SIOCGHWADDR"););
812 bcopy((caddr_t)sc->sc_addr, (caddr_t)&ifr->ifr_data,
813 sizeof(sc->sc_addr));
814 break;
815#endif
816 case SIOCADDMULTI:
817 DODEBUG(Start_End, printf("SIOCADDMULTI"););
818 case SIOCDELMULTI:
819 DODEBUG(Start_End, printf("SIOCDELMULTI"););
820 /* XXX Support not done yet. */
821 error = EINVAL;
822 break;
823 case SIOCSIFMEDIA:
824 case SIOCGIFMEDIA:
825 error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, cmd);
826 break;
827 default:
828 DODEBUG(Start_End, printf("unknown"););
829 error = EINVAL;
830 }
831
832 splx(s);
833
834 DODEBUG(Start_End, printf("\nex_ioctl%d: finish\n", ifp->if_unit););
835
836 return(error);
837}
838
839
840static void
841ex_reset(struct ex_softc *sc)
842{
843 int s;
844
845 DODEBUG(Start_End, printf("ex_reset%d: start\n", unit););
846
847 s = splimp();
848
849 ex_stop(sc);
850 ex_init(sc);
851
852 splx(s);
853
854 DODEBUG(Start_End, printf("ex_reset%d: finish\n", unit););
855
856 return;
857}
858
859static void
860ex_watchdog(struct ifnet *ifp)
861{
862 struct ex_softc * sc = ifp->if_softc;
863
864 DODEBUG(Start_End, printf("ex_watchdog%d: start\n", ifp->if_unit););
865
866 ifp->if_flags &= ~IFF_OACTIVE;
867
868 DODEBUG(Status, printf("OIDLE watchdog\n"););
869
870 ifp->if_oerrors++;
871 ex_reset(sc);
872 ex_start(ifp);
873
874 DODEBUG(Start_End, printf("ex_watchdog%d: finish\n", ifp->if_unit););
875
876 return;
877}
878
879static int
880ex_get_media (u_int32_t iobase)
881{
882 int tmp;
883
884 outb(iobase + CMD_REG, Bank2_Sel);
885 tmp = inb(iobase + REG3);
886 outb(iobase + CMD_REG, Bank0_Sel);
887
888 if (tmp & TPE_bit)
889 return(IFM_ETHER|IFM_10_T);
890 if (tmp & BNC_bit)
891 return(IFM_ETHER|IFM_10_2);
892
893 return (IFM_ETHER|IFM_10_5);
894}
895
896static int
897ex_ifmedia_upd (ifp)
898 struct ifnet * ifp;
899{
900 struct ex_softc * sc = ifp->if_softc;
901
902 return (0);
903}
904
905static void
906ex_ifmedia_sts(ifp, ifmr)
907 struct ifnet * ifp;
908 struct ifmediareq * ifmr;
909{
910 struct ex_softc * sc = ifp->if_softc;
911
912 ifmr->ifm_active = ex_get_media(sc->iobase);
913
914 return;
915}
916
917u_short
918eeprom_read(u_int32_t iobase, int location)
919{
920 int i;
921 u_short data = 0;
922 int ee_addr;
923 int read_cmd = location | EE_READ_CMD;
924 short ctrl_val = EECS;
925
926 ee_addr = iobase + EEPROM_REG;
927 outb(iobase + CMD_REG, Bank2_Sel);
928 outb(ee_addr, EECS);
929 for (i = 8; i >= 0; i--) {
930 short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val;
931 outb(ee_addr, outval);
932 outb(ee_addr, outval | EESK);
933 DELAY(3);
934 outb(ee_addr, outval);
935 DELAY(2);
936 }
937 outb(ee_addr, ctrl_val);
938
939 for (i = 16; i > 0; i--) {
940 outb(ee_addr, ctrl_val | EESK);
941 DELAY(3);
942 data = (data << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
943 outb(ee_addr, ctrl_val);
944 DELAY(2);
945 }
946
947 ctrl_val &= ~EECS;
948 outb(ee_addr, ctrl_val | EESK);
949 DELAY(3);
950 outb(ee_addr, ctrl_val);
951 DELAY(2);
952 outb(iobase + CMD_REG, Bank0_Sel);
953 return(data);
954}