FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/if_ie.c
1 /*-
2 * Copyright (c) 1992, 1993, University of Vermont and State
3 * Agricultural College.
4 * Copyright (c) 1992, 1993, Garrett A. Wollman.
5 *
6 * Portions:
7 * Copyright (c) 1990, 1991, William F. Jolitz
8 * Copyright (c) 1990, The Regents of the University of California
9 *
10 * 3Com 3C507 support:
11 * Copyright (c) 1993, 1994, Charles M. Hannum
12 *
13 * EtherExpress 16 support:
14 * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
15 * Copyright (c) 1997, Aaron C. Smith
16 *
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. All advertising materials mentioning features or use of this software
28 * must display the following acknowledgement:
29 * This product includes software developed by the University of
30 * Vermont and State Agricultural College and Garrett A. Wollman, by
31 * William F. Jolitz, by the University of California, Berkeley,
32 * Lawrence Berkeley Laboratory, and their contributors, by
33 * Charles M. Hannum, by Rodney W. Grimes, and by Aaron C. Smith.
34 * 4. Neither the names of the Universities nor the names of the authors
35 * may be used to endorse or promote products derived from this software
36 * without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 * $FreeBSD: src/sys/i386/isa/if_ie.c,v 1.36.2.5 1999/09/05 08:12:53 peter Exp $
51 */
52
53 /*
54 * Intel 82586 Ethernet chip
55 * Register, bit, and structure definitions.
56 *
57 * Written by GAW with reference to the Clarkson Packet Driver code for this
58 * chip written by Russ Nelson and others.
59 *
60 * Intel EtherExpress 16 support from if_ix.c, written by Rodney W. Grimes.
61 */
62
63 /*
64 * The i82586 is a very versatile chip, found in many implementations.
65 * Programming this chip is mostly the same, but certain details differ
66 * from card to card. This driver is written so that different cards
67 * can be automatically detected at run-time.
68 */
69
70 /*
71 Mode of operation:
72
73 We run the 82586 in a standard Ethernet mode. We keep NFRAMES received
74 frame descriptors around for the receiver to use, and NRXBUFS associated
75 receive buffer descriptors, both in a circular list. Whenever a frame is
76 received, we rotate both lists as necessary. (The 586 treats both lists
77 as a simple queue.) We also keep a transmit command around so that packets
78 can be sent off quickly.
79
80 We configure the adapter in AL-LOC = 1 mode, which means that the
81 Ethernet/802.3 MAC header is placed at the beginning of the receive buffer
82 rather than being split off into various fields in the RFD. This also
83 means that we must include this header in the transmit buffer as well.
84
85 By convention, all transmit commands, and only transmit commands, shall
86 have the I (IE_CMD_INTR) bit set in the command. This way, when an
87 interrupt arrives at ieintr(), it is immediately possible to tell
88 what precisely caused it. ANY OTHER command-sending routines should
89 run at splimp(), and should post an acknowledgement to every interrupt
90 they generate.
91
92 The 82586 has a 24-bit address space internally, and the adaptor's memory
93 is located at the top of this region. However, the value we are given in
94 configuration is normally the *bottom* of the adaptor RAM. So, we must go
95 through a few gyrations to come up with a kernel virtual address which
96 represents the actual beginning of the 586 address space. First, we
97 autosize the RAM by running through several possible sizes and trying to
98 initialize the adapter under the assumption that the selected size is
99 correct. Then, knowing the correct RAM size, we set up our pointers in
100 ie_softc[unit]. `iomem' represents the computed base of the 586 address
101 space. `iomembot' represents the actual configured base of adapter RAM.
102 Finally, `iosize' represents the calculated size of 586 RAM. Then, when
103 laying out commands, we use the interval [iomembot, iomembot + iosize); to
104 make 24-pointers, we subtract iomem, and to make 16-pointers, we subtract
105 iomem and and with 0xffff.
106
107 */
108
109 #include "ie.h"
110 #if NIE > 0
111
112 #include <sys/param.h>
113 #include <sys/systm.h>
114 #include <sys/kernel.h>
115 #include <sys/conf.h>
116 #include <sys/mbuf.h>
117 #include <sys/protosw.h>
118 #include <sys/socket.h>
119 #include <sys/ioctl.h>
120 #include <sys/errno.h>
121 #include <sys/syslog.h>
122
123 #include <net/if.h>
124 #include <net/if_types.h>
125 #include <net/if_dl.h>
126 #include <net/route.h>
127
128 #include "bpfilter.h"
129
130 #ifdef INET
131 #include <netinet/in.h>
132 #include <netinet/in_systm.h>
133 #include <netinet/in_var.h>
134 #include <netinet/ip.h>
135 #include <netinet/if_ether.h>
136 #endif
137
138 #ifdef IPX
139 #include <netipx/ipx.h>
140 #include <netipx/ipx_if.h>
141 #endif
142
143 #ifdef NS
144 #include <netns/ns.h>
145 #include <netns/ns_if.h>
146 #endif
147
148 #include <machine/clock.h>
149 #include <machine/md_var.h>
150
151 #include <i386/isa/isa_device.h>
152 #include <i386/isa/ic/i82586.h>
153 #include <i386/isa/icu.h>
154 #include <i386/isa/if_iereg.h>
155 #include <i386/isa/if_ie507.h>
156 #include <i386/isa/if_iee16.h>
157 #include <i386/isa/elink.h>
158
159 #include <vm/vm.h>
160
161 #if NBPFILTER > 0
162 #include <net/bpf.h>
163 #include <net/bpfdesc.h>
164 #endif
165
166 #ifdef DEBUG
167 #define IED_RINT 0x01
168 #define IED_TINT 0x02
169 #define IED_RNR 0x04
170 #define IED_CNA 0x08
171 #define IED_READFRAME 0x10
172 int ie_debug = IED_RNR;
173 #endif
174
175 #define IE_BUF_LEN ETHER_MAX_LEN /* length of transmit buffer */
176
177 /* Forward declaration */
178 struct ie_softc;
179
180 static struct mbuf *last_not_for_us;
181
182 static int ieprobe(struct isa_device *dvp);
183 static int ieattach(struct isa_device *dvp);
184 static int sl_probe(struct isa_device *dvp);
185 static int el_probe(struct isa_device *dvp);
186 static int ni_probe(struct isa_device *dvp);
187 static int ee16_probe(struct isa_device *dvp);
188
189 static int check_ie_present __P((int unit, caddr_t where, unsigned size));
190 static void ieinit(int unit);
191 static void ie_stop __P((int unit));
192 static int ieioctl(struct ifnet *ifp, int command, caddr_t data);
193 static void iestart(struct ifnet *ifp);
194
195 static void el_reset_586(int unit);
196 static void el_chan_attn(int unit);
197
198 static void sl_reset_586(int unit);
199 static void sl_chan_attn(int unit);
200
201 static void ee16_reset_586(int unit);
202 static void ee16_chan_attn(int unit);
203 static void ee16_interrupt_enable __P((struct ie_softc *ie));
204 static void ee16_eeprom_outbits __P((struct ie_softc *ie, int edata, int cnt));
205 static void ee16_eeprom_clock __P((struct ie_softc *ie, int state));
206 static u_short ee16_read_eeprom __P((struct ie_softc *ie, int location));
207 static int ee16_eeprom_inbits __P((struct ie_softc *ie));
208 static void ee16_shutdown(int howto, void *sc);
209
210 static void iereset(int unit);
211 static void ie_readframe(int unit, struct ie_softc *ie, int bufno);
212 static void ie_drop_packet_buffer(int unit, struct ie_softc *ie);
213 static void sl_read_ether(int unit, unsigned char addr[6]);
214 static void find_ie_mem_size(int unit);
215 static void chan_attn_timeout __P((void * rock));
216 static int command_and_wait(int unit, int command, void volatile *pcmd, int);
217 static void run_tdr __P((int unit, struct ie_tdr_cmd *cmd));
218 static int ierint(int unit, struct ie_softc *ie);
219 static int ietint(int unit, struct ie_softc *ie);
220 static int iernr(int unit, struct ie_softc *ie);
221 static void start_receiver(int unit);
222 static int ieget(int, struct ie_softc *, struct mbuf **,
223 struct ether_header *, int *);
224 static caddr_t setup_rfa(caddr_t ptr, struct ie_softc *ie);
225 static int mc_setup(int, caddr_t, volatile struct ie_sys_ctl_block *);
226 static void ie_mc_reset(int unit);
227
228 #ifdef DEBUG
229 void print_rbd(volatile struct ie_recv_buf_desc *rbd);
230
231 int in_ierint = 0;
232 int in_ietint = 0;
233 #endif
234
235 /*
236 * This tells the autoconf code how to set us up.
237 */
238 struct isa_driver iedriver = {
239 ieprobe, ieattach, "ie",
240 };
241
242 enum ie_hardware {
243 IE_STARLAN10,
244 IE_EN100,
245 IE_SLFIBER,
246 IE_3C507,
247 IE_NI5210,
248 IE_EE16,
249 IE_UNKNOWN
250 };
251
252 static const char *ie_hardware_names[] = {
253 "StarLAN 10",
254 "EN100",
255 "StarLAN Fiber",
256 "3C507",
257 "NI5210",
258 "EtherExpress 16",
259 "Unknown"
260 };
261
262 /*
263 sizeof(iscp) == 1+1+2+4 == 8
264 sizeof(scb) == 2+2+2+2+2+2+2+2 == 16
265 NFRAMES * sizeof(rfd) == NFRAMES*(2+2+2+2+6+6+2+2) == NFRAMES*24 == 384
266 sizeof(xmit_cmd) == 2+2+2+2+6+2 == 18
267 sizeof(transmit buffer) == 1512
268 sizeof(transmit buffer desc) == 8
269 -----
270 1946
271
272 NRXBUFS * sizeof(rbd) == NRXBUFS*(2+2+4+2+2) == NRXBUFS*12
273 NRXBUFS * IE_RBUF_SIZE == NRXBUFS*256
274
275 NRXBUFS should be (16384 - 1946) / (256 + 12) == 14438 / 268 == 53
276
277 With NRXBUFS == 48, this leaves us 1574 bytes for another command or
278 more buffers. Another transmit command would be 18+8+1512 == 1538
279 ---just barely fits!
280
281 Obviously all these would have to be reduced for smaller memory sizes.
282 With a larger memory, it would be possible to roughly double the number of
283 both transmit and receive buffers.
284 */
285
286 #define NFRAMES 8 /* number of receive frames */
287 #define NRXBUFS 48 /* number of buffers to allocate */
288 #define IE_RBUF_SIZE 256 /* size of each buffer,
289 * MUST BE POWER OF TWO
290 */
291 #define NTXBUFS 2 /* number of transmit commands */
292 #define IE_TBUF_SIZE ETHER_MAX_LEN /* size of transmit buffer */
293
294 /*
295 * Ethernet status, per interface.
296 */
297 static struct ie_softc {
298 struct arpcom arpcom;
299 void (*ie_reset_586)(int);
300 void (*ie_chan_attn)(int);
301 enum ie_hardware hard_type;
302 int hard_vers;
303
304 u_short port; /* i/o base address for this interface */
305 caddr_t iomem; /* memory size */
306 caddr_t iomembot; /* memory base address */
307 unsigned iosize;
308 int bus_use; /* 0 means 16bit, 1 means 8 bit adapter */
309
310 int want_mcsetup;
311 int promisc;
312 int nframes;
313 int nrxbufs;
314 int ntxbufs;
315 volatile struct ie_int_sys_conf_ptr *iscp;
316 volatile struct ie_sys_ctl_block *scb;
317 volatile struct ie_recv_frame_desc **rframes; /* nframes worth */
318 volatile struct ie_recv_buf_desc **rbuffs; /* nrxbufs worth */
319 volatile u_char **cbuffs; /* nrxbufs worth */
320 int rfhead, rftail, rbhead, rbtail;
321
322 volatile struct ie_xmit_cmd **xmit_cmds; /* ntxbufs worth */
323 volatile struct ie_xmit_buf **xmit_buffs; /* ntxbufs worth */
324 u_char **xmit_cbuffs; /* ntxbufs worth */
325 int xmit_count;
326
327 struct ie_en_addr mcast_addrs[MAXMCAST + 1];
328 int mcast_count;
329
330 u_short irq_encoded; /* encoded interrupt on IEE16 */
331
332 } ie_softc[NIE];
333
334 #define MK_24(base, ptr) ((caddr_t)((u_long)ptr - (u_long)base))
335 #define MK_16(base, ptr) ((u_short)(u_long)MK_24(base, ptr))
336
337 #define PORT ie_softc[unit].port
338 #define MEM ie_softc[unit].iomem
339
340 int
341 ieprobe(dvp)
342 struct isa_device *dvp;
343 {
344 int ret;
345
346 ret = sl_probe(dvp);
347 if (!ret) ret = el_probe(dvp);
348 if (!ret) ret = ni_probe(dvp);
349 if (!ret) ret = ee16_probe(dvp);
350
351 return (ret);
352 }
353
354 static int
355 sl_probe(dvp)
356 struct isa_device *dvp;
357 {
358 int unit = dvp->id_unit;
359 u_char c;
360
361 ie_softc[unit].port = dvp->id_iobase;
362 ie_softc[unit].iomembot = dvp->id_maddr;
363 ie_softc[unit].iomem = 0;
364 ie_softc[unit].bus_use = 0;
365
366 c = inb(PORT + IEATT_REVISION);
367 switch(SL_BOARD(c)) {
368 case SL10_BOARD:
369 ie_softc[unit].hard_type = IE_STARLAN10;
370 ie_softc[unit].ie_reset_586 = sl_reset_586;
371 ie_softc[unit].ie_chan_attn = sl_chan_attn;
372 break;
373 case EN100_BOARD:
374 ie_softc[unit].hard_type = IE_EN100;
375 ie_softc[unit].ie_reset_586 = sl_reset_586;
376 ie_softc[unit].ie_chan_attn = sl_chan_attn;
377 break;
378 case SLFIBER_BOARD:
379 ie_softc[unit].hard_type = IE_SLFIBER;
380 ie_softc[unit].ie_reset_586 = sl_reset_586;
381 ie_softc[unit].ie_chan_attn = sl_chan_attn;
382 break;
383
384 /*
385 * Anything else is not recognized or cannot be used.
386 */
387 default:
388 return 0;
389 }
390
391 ie_softc[unit].hard_vers = SL_REV(c);
392
393 /*
394 * Divine memory size on-board the card. Ususally 16k.
395 */
396 find_ie_mem_size(unit);
397
398 if(!ie_softc[unit].iosize) {
399 return 0;
400 }
401
402 dvp->id_msize = ie_softc[unit].iosize;
403
404 switch(ie_softc[unit].hard_type) {
405 case IE_EN100:
406 case IE_STARLAN10:
407 case IE_SLFIBER:
408 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
409 break;
410
411 default:
412 if (bootverbose)
413 printf("ie%d: unknown AT&T board type code %d\n", unit,
414 ie_softc[unit].hard_type);
415 return 0;
416 }
417
418 return 1;
419 }
420
421
422 static int
423 el_probe(dvp)
424 struct isa_device *dvp;
425 {
426 struct ie_softc *sc = &ie_softc[dvp->id_unit];
427 u_char c;
428 int i;
429 u_char signature[] = "*3COM*";
430 int unit = dvp->id_unit;
431
432 sc->port = dvp->id_iobase;
433 sc->iomembot = dvp->id_maddr;
434 sc->bus_use = 0;
435
436 /* Need this for part of the probe. */
437 sc->ie_reset_586 = el_reset_586;
438 sc->ie_chan_attn = el_chan_attn;
439
440 /* Reset and put card in CONFIG state without changing address. */
441 elink_reset();
442 outb(ELINK_ID_PORT, 0x00);
443 elink_idseq(ELINK_507_POLY);
444 elink_idseq(ELINK_507_POLY);
445 outb(ELINK_ID_PORT, 0xff);
446
447 c = inb(PORT + IE507_MADDR);
448 if(c & 0x20) {
449 #ifdef DEBUG
450 printf("ie%d: can't map 3C507 RAM in high memory\n", unit);
451 #endif
452 return 0;
453 }
454
455 /* go to RUN state */
456 outb(ELINK_ID_PORT, 0x00);
457 elink_idseq(ELINK_507_POLY);
458 outb(ELINK_ID_PORT, 0x00);
459
460 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
461
462 for (i = 0; i < 6; i++)
463 if (inb(PORT + i) != signature[i])
464 return 0;
465
466 c = inb(PORT + IE507_IRQ) & 0x0f;
467
468 if (dvp->id_irq != (1 << c)) {
469 printf("ie%d: kernel configured irq %d doesn't match board configured irq %d\n",
470 unit, ffs(dvp->id_irq) - 1, c);
471 return 0;
472 }
473
474 c = (inb(PORT + IE507_MADDR) & 0x1c) + 0xc0;
475
476 if (kvtop(dvp->id_maddr) != ((int)c << 12)) {
477 printf("ie%d: kernel configured maddr %lx doesn't match board configured maddr %x\n",
478 unit, kvtop(dvp->id_maddr),(int)c << 12);
479 return 0;
480 }
481
482 outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
483
484 sc->hard_type = IE_3C507;
485 sc->hard_vers = 0; /* 3C507 has no version number. */
486
487 /*
488 * Divine memory size on-board the card.
489 */
490 find_ie_mem_size(unit);
491
492 if (!sc->iosize) {
493 printf("ie%d: can't find shared memory\n", unit);
494 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
495 return 0;
496 }
497
498 if(!dvp->id_msize)
499 dvp->id_msize = sc->iosize;
500 else if (dvp->id_msize != sc->iosize) {
501 printf("ie%d: kernel configured msize %d doesn't match board configured msize %d\n",
502 unit, dvp->id_msize, sc->iosize);
503 outb(PORT + IE507_CTRL, EL_CTRL_NRST);
504 return 0;
505 }
506
507 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
508
509 /* Clear the interrupt latch just in case. */
510 outb(PORT + IE507_ICTRL, 1);
511
512 return 16;
513 }
514
515
516 static int ni_probe(dvp)
517 struct isa_device *dvp;
518 {
519 int unit = dvp->id_unit;
520 int boardtype, c;
521
522 ie_softc[unit].port = dvp->id_iobase;
523 ie_softc[unit].iomembot = dvp->id_maddr;
524 ie_softc[unit].iomem = 0;
525 ie_softc[unit].bus_use = 1;
526
527 boardtype = inb(PORT + IEATT_REVISION);
528 c = inb(PORT + IEATT_REVISION + 1);
529 boardtype = boardtype + (c << 8);
530 switch(boardtype) {
531 case 0x5500: /* This is the magic cookie for the NI5210 */
532 ie_softc[unit].hard_type = IE_NI5210;
533 ie_softc[unit].ie_reset_586 = sl_reset_586;
534 ie_softc[unit].ie_chan_attn = sl_chan_attn;
535 break;
536
537 /*
538 * Anything else is not recognized or cannot be used.
539 */
540 default:
541 return 0;
542 }
543
544 ie_softc[unit].hard_vers = 0;
545
546 /*
547 * Divine memory size on-board the card. Either 8 or 16k.
548 */
549 find_ie_mem_size(unit);
550
551 if(!ie_softc[unit].iosize) {
552 return 0;
553 }
554
555 if(!dvp->id_msize)
556 dvp->id_msize = ie_softc[unit].iosize;
557 else if (dvp->id_msize != ie_softc[unit].iosize) {
558 printf("ie%d: kernel configured msize %d doesn't match board configured msize %d\n",
559 unit, dvp->id_msize, ie_softc[unit].iosize);
560 return 0;
561 }
562
563 sl_read_ether(unit, ie_softc[unit].arpcom.ac_enaddr);
564
565 return 8;
566
567 }
568
569
570 static void
571 ee16_shutdown(howto, sc)
572 int howto;
573 void *sc;
574 {
575 struct ie_softc *ie = (struct ie_softc *)sc;
576 int unit = ie - &ie_softc[0];
577
578 ee16_reset_586(unit);
579 outb(PORT + IEE16_ECTRL, IEE16_RESET_ASIC);
580 outb(PORT + IEE16_ECTRL, 0);
581 }
582
583
584 /* Taken almost exactly from Rod's if_ix.c. */
585
586 int
587 ee16_probe(dvp)
588 struct isa_device *dvp;
589 {
590 struct ie_softc *sc = &ie_softc[dvp->id_unit];
591
592 int i;
593 int unit = dvp->id_unit;
594 u_short board_id, id_var1, id_var2, checksum = 0;
595 u_short eaddrtemp, irq;
596 u_short pg, adjust, decode, edecode;
597 u_char bart_config;
598 u_long bd_maddr;
599
600 short irq_translate[] = {0, IRQ9, IRQ3, IRQ4, IRQ5, IRQ10, IRQ11, 0};
601 char irq_encode[] = { 0, 0, 0, 2, 3, 4, 0, 0,
602 0, 1, 5, 6, 0, 0, 0, 0 };
603
604 /* Need this for part of the probe. */
605 sc->ie_reset_586 = ee16_reset_586;
606 sc->ie_chan_attn = ee16_chan_attn;
607
608 /* unsure if this is necessary */
609 sc->bus_use = 0;
610
611 /* reset any ee16 at the current iobase */
612 outb(dvp->id_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
613 outb(dvp->id_iobase + IEE16_ECTRL, 0);
614 DELAY(240);
615
616 /* now look for ee16. */
617 board_id = id_var1 = id_var2 = 0;
618 for (i=0; i<4 ; i++) {
619 id_var1 = inb(dvp->id_iobase + IEE16_ID_PORT);
620 id_var2 = ((id_var1 & 0x03) << 2);
621 board_id |= (( id_var1 >> 4) << id_var2);
622 }
623
624 if (board_id != IEE16_ID) {
625 printf("ie%d: unknown board_id: %x\n", unit, board_id);
626 return 0;
627 }
628
629 /* need sc->port for ee16_read_eeprom */
630 sc->port = dvp->id_iobase;
631 sc->hard_type = IE_EE16;
632
633 /*
634 * The shared RAM location on the EE16 is encoded into bits
635 * 3-7 of EEPROM location 6. We zero the upper byte, and
636 * shift the 5 bits right 3. The resulting number tells us
637 * the RAM location. Because the EE16 supports either 16k or 32k
638 * of shared RAM, we only worry about the 32k locations.
639 *
640 * NOTE: if a 64k EE16 exists, it should be added to this switch.
641 * then the ia->ia_msize would need to be set per case statement.
642 *
643 * value msize location
644 * ===== ===== ========
645 * 0x03 0x8000 0xCC000
646 * 0x06 0x8000 0xD0000
647 * 0x0C 0x8000 0xD4000
648 * 0x18 0x8000 0xD8000
649 *
650 */
651
652 bd_maddr = 0;
653 i = (ee16_read_eeprom(sc, 6) & 0x00ff ) >> 3;
654 switch(i) {
655 case 0x03:
656 bd_maddr = 0xCC000;
657 break;
658 case 0x06:
659 bd_maddr = 0xD0000;
660 break;
661 case 0x0c:
662 bd_maddr = 0xD4000;
663 break;
664 case 0x18:
665 bd_maddr = 0xD8000;
666 break;
667 default:
668 bd_maddr = 0 ;
669 break;
670 }
671 dvp->id_msize = 0x8000;
672 if (kvtop(dvp->id_maddr) != bd_maddr) {
673 printf("ie%d: kernel configured maddr %lx doesn't match board configured maddr %x\n",
674 unit, kvtop(dvp->id_maddr), bd_maddr);
675 }
676
677
678 sc->iomembot = dvp->id_maddr;
679 sc->iomem = 0; /* XXX some probes set this and some don't */
680 sc->iosize = dvp->id_msize;
681
682 /* need to put the 586 in RESET while we access the eeprom. */
683 outb( PORT + IEE16_ECTRL, IEE16_RESET_586);
684
685 /* read the eeprom and checksum it, should == IEE16_ID */
686 for(i = 0; i < 0x40; i++)
687 checksum += ee16_read_eeprom(sc, i);
688
689 if (checksum != IEE16_ID) {
690 printf("ie%d: invalid eeprom checksum: %x\n", unit, checksum);
691 return 0;
692 }
693
694 /*
695 * Size and test the memory on the board. The size of the memory
696 * can be one of 16k, 32k, 48k or 64k. It can be located in the
697 * address range 0xC0000 to 0xEFFFF on 16k boundaries.
698 *
699 * If the size does not match the passed in memory allocation size
700 * issue a warning, but continue with the minimum of the two sizes.
701 */
702
703 switch (dvp->id_msize) {
704 case 65536:
705 case 32768: /* XXX Only support 32k and 64k right now */
706 break;
707 case 16384:
708 case 49512:
709 default:
710 printf("ie%d: mapped memory size %d not supported\n", unit,
711 dvp->id_msize);
712 return 0;
713 break; /* NOTREACHED */
714 }
715
716 if ((kvtop(dvp->id_maddr) < 0xC0000) ||
717 (kvtop(dvp->id_maddr) + sc->iosize > 0xF0000)) {
718 printf("ie%d: mapped memory location %x out of range\n", unit,
719 dvp->id_maddr);
720 return 0;
721 }
722
723 pg = (kvtop(dvp->id_maddr) & 0x3C000) >> 14;
724 adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
725 decode = ((1 << (sc->iosize / 16384)) - 1) << pg;
726 edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
727
728 /* ZZZ This should be checked against eeprom location 6, low byte */
729 outb(PORT + IEE16_MEMDEC, decode & 0xFF);
730 /* ZZZ This should be checked against eeprom location 1, low byte */
731 outb(PORT + IEE16_MCTRL, adjust);
732 /* ZZZ Now if I could find this one I would have it made */
733 outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));
734 /* ZZZ I think this is location 6, high byte */
735 outb(PORT + IEE16_MECTRL, edecode); /*XXX disable Exxx */
736
737 (void)kvtop(dvp->id_maddr);
738
739 /*
740 * first prime the stupid bart DRAM controller so that it
741 * works, then zero out all of memory.
742 */
743 bzero(sc->iomembot, 32);
744 bzero(sc->iomembot, sc->iosize);
745
746 /*
747 * Get the encoded interrupt number from the EEPROM, check it
748 * against the passed in IRQ. Issue a warning if they do not
749 * match. Always use the passed in IRQ, not the one in the EEPROM.
750 */
751 irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
752 irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
753 irq = irq_translate[irq];
754 if (dvp->id_irq > 0) {
755 if (irq != dvp->id_irq) {
756 printf("ie%d: WARNING: board configured at irq %d, using %d\n",
757 dvp->id_unit, irq);
758 irq = dvp->id_unit;
759 }
760 } else {
761 dvp->id_irq = irq;
762 }
763 sc->irq_encoded = irq_encode[ffs(irq) - 1];
764
765 /*
766 * Get the hardware ethernet address from the EEPROM and
767 * save it in the softc for use by the 586 setup code.
768 */
769 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
770 sc->arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
771 sc->arpcom.ac_enaddr[0] = eaddrtemp >> 8;
772 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
773 sc->arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
774 sc->arpcom.ac_enaddr[2] = eaddrtemp >> 8;
775 eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
776 sc->arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
777 sc->arpcom.ac_enaddr[4] = eaddrtemp >> 8;
778
779 /* disable the board interrupts */
780 outb(PORT + IEE16_IRQ, sc->irq_encoded);
781
782 /* enable loopback to keep bad packets off the wire */
783 if(sc->hard_type == IE_EE16) {
784 bart_config = inb(PORT + IEE16_CONFIG);
785 bart_config |= IEE16_BART_LOOPBACK;
786 bart_config |= IEE16_BART_MCS16_TEST; /*inb doesn't get bit! */
787 outb(PORT + IEE16_CONFIG, bart_config);
788 bart_config = inb(PORT + IEE16_CONFIG);
789 }
790
791 /* take the board out of reset state */
792 outb(PORT + IEE16_ECTRL, 0);
793 DELAY(100);
794
795 if (!check_ie_present(unit, dvp->id_maddr, sc->iosize))
796 return 0;
797
798 return 16; /* return the number of I/O ports */
799 }
800
801 /*
802 * Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
803 */
804 int
805 ieattach(dvp)
806 struct isa_device *dvp;
807 {
808 int factor;
809 int unit = dvp->id_unit;
810 struct ie_softc *ie = &ie_softc[unit];
811 struct ifnet *ifp = &ie->arpcom.ac_if;
812 size_t allocsize;
813
814 /*
815 * based on the amount of memory we have,
816 * allocate our tx and rx resources.
817 */
818 factor = dvp->id_msize / 16384;
819 ie->nframes = factor * NFRAMES;
820 ie->nrxbufs = factor * NRXBUFS;
821 ie->ntxbufs = factor * NTXBUFS;
822
823 /*
824 * Since all of these guys are arrays of pointers, allocate as one
825 * big chunk and dole out accordingly.
826 */
827 allocsize = sizeof(void *) * (ie->nframes
828 + (ie->nrxbufs * 2)
829 + (ie->ntxbufs * 3));
830 ie->rframes = (volatile struct ie_recv_frame_desc **)malloc(allocsize,
831 M_DEVBUF,
832 M_NOWAIT);
833 if (ie->rframes == NULL)
834 return (0);
835 ie->rbuffs = (volatile struct ie_recv_buf_desc **)&ie->rframes[ie->nframes];
836 ie->cbuffs = (volatile u_char **)&ie->rbuffs[ie->nrxbufs];
837 ie->xmit_cmds = (volatile struct ie_xmit_cmd **)&ie->cbuffs[ie->nrxbufs];
838 ie->xmit_buffs = (volatile struct ie_xmit_buf **)&ie->xmit_cmds[ie->ntxbufs];
839 ie->xmit_cbuffs = (u_char **)&ie->xmit_buffs[ie->ntxbufs];
840
841 ifp->if_softc = ie;
842 ifp->if_unit = unit;
843 ifp->if_name = iedriver.name;
844 ifp->if_mtu = ETHERMTU;
845 printf("ie%d: <%s R%d> address %6D\n", unit,
846 ie_hardware_names[ie->hard_type],
847 ie->hard_vers + 1,
848 ie->arpcom.ac_enaddr, ":");
849
850 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
851 ifp->if_output = ether_output;
852 ifp->if_start = iestart;
853 ifp->if_ioctl = ieioctl;
854 ifp->if_type = IFT_ETHER;
855 ifp->if_addrlen = 6;
856 ifp->if_hdrlen = 14;
857
858 if (ie->hard_type == IE_EE16)
859 at_shutdown(ee16_shutdown, ie, SHUTDOWN_POST_SYNC);
860
861 #if NBPFILTER > 0
862 bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
863 #endif
864
865 if_attach(ifp);
866 ether_ifattach(ifp);
867 return 1;
868 }
869
870 /*
871 * What to do upon receipt of an interrupt.
872 */
873 void
874 ieintr(unit)
875 int unit;
876 {
877 register struct ie_softc *ie = &ie_softc[unit];
878 register u_short status;
879
880 /* Clear the interrupt latch on the 3C507. */
881 if (ie->hard_type == IE_3C507 && (inb(PORT + IE507_CTRL) & EL_CTRL_INTL))
882 outb(PORT + IE507_ICTRL, 1);
883
884 /* disable interrupts on the EE16. */
885 if (ie->hard_type == IE_EE16)
886 outb(PORT + IEE16_IRQ, ie->irq_encoded);
887
888 status = ie->scb->ie_status;
889
890 loop:
891
892 /* Don't ack interrupts which we didn't receive */
893 ie_ack(ie->scb, IE_ST_WHENCE & status, unit, ie->ie_chan_attn);
894
895 if(status & (IE_ST_RECV | IE_ST_RNR)) {
896 #ifdef DEBUG
897 in_ierint++;
898 if(ie_debug & IED_RINT)
899 printf("ie%d: rint\n", unit);
900 #endif
901 ierint(unit, ie);
902 #ifdef DEBUG
903 in_ierint--;
904 #endif
905 }
906
907 if(status & IE_ST_DONE) {
908 #ifdef DEBUG
909 in_ietint++;
910 if(ie_debug & IED_TINT)
911 printf("ie%d: tint\n", unit);
912 #endif
913 ietint(unit, ie);
914 #ifdef DEBUG
915 in_ietint--;
916 #endif
917 }
918
919 if(status & IE_ST_RNR) {
920 #ifdef DEBUG
921 if(ie_debug & IED_RNR)
922 printf("ie%d: rnr\n", unit);
923 #endif
924 iernr(unit, ie);
925 }
926
927 #ifdef DEBUG
928 if((status & IE_ST_ALLDONE)
929 && (ie_debug & IED_CNA))
930 printf("ie%d: cna\n", unit);
931 #endif
932
933 if ((status = ie->scb->ie_status) & IE_ST_WHENCE)
934 goto loop;
935
936 /* Clear the interrupt latch on the 3C507. */
937 if (ie->hard_type == IE_3C507)
938 outb(PORT + IE507_ICTRL, 1);
939
940 /* enable interrupts on the EE16. */
941 if (ie->hard_type == IE_EE16)
942 outb(PORT + IEE16_IRQ, ie->irq_encoded | IEE16_IRQ_ENABLE);
943
944 }
945
946 /*
947 * Process a received-frame interrupt.
948 */
949 static int
950 ierint(unit, ie)
951 int unit;
952 struct ie_softc *ie;
953 {
954 int i, status;
955 static int timesthru = 1024;
956
957 i = ie->rfhead;
958 while(1) {
959 status = ie->rframes[i]->ie_fd_status;
960
961 if((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
962 ie->arpcom.ac_if.if_ipackets++;
963 if(!--timesthru) {
964 ie->arpcom.ac_if.if_ierrors +=
965 ie->scb->ie_err_crc + ie->scb->ie_err_align +
966 ie->scb->ie_err_resource + ie->scb->ie_err_overrun;
967 ie->scb->ie_err_crc = 0;
968 ie->scb->ie_err_align = 0;
969 ie->scb->ie_err_resource = 0;
970 ie->scb->ie_err_overrun = 0;
971 timesthru = 1024;
972 }
973 ie_readframe(unit, ie, i);
974 } else {
975 if(status & IE_FD_RNR) {
976 if(!(ie->scb->ie_status & IE_RU_READY)) {
977 ie->rframes[0]->ie_fd_next = MK_16(MEM, ie->rbuffs[0]);
978 ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
979 command_and_wait(unit, IE_RU_START, 0, 0);
980 }
981 }
982 break;
983 }
984 i = (i + 1) % ie->nframes;
985 }
986 return 0;
987 }
988
989 /*
990 * Process a command-complete interrupt. These are only generated by
991 * the transmission of frames. This routine is deceptively simple, since
992 * most of the real work is done by iestart().
993 */
994 static int ietint(unit, ie)
995 int unit;
996 struct ie_softc *ie;
997 {
998 int status;
999 int i;
1000
1001 ie->arpcom.ac_if.if_timer = 0;
1002 ie->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
1003
1004 for(i = 0; i < ie->xmit_count; i++) {
1005 status = ie->xmit_cmds[i]->ie_xmit_status;
1006
1007 if(status & IE_XS_LATECOLL) {
1008 printf("ie%d: late collision\n", unit);
1009 ie->arpcom.ac_if.if_collisions++;
1010 ie->arpcom.ac_if.if_oerrors++;
1011 } else if(status & IE_XS_NOCARRIER) {
1012 printf("ie%d: no carrier\n", unit);
1013 ie->arpcom.ac_if.if_oerrors++;
1014 } else if(status & IE_XS_LOSTCTS) {
1015 printf("ie%d: lost CTS\n", unit);
1016 ie->arpcom.ac_if.if_oerrors++;
1017 } else if(status & IE_XS_UNDERRUN) {
1018 printf("ie%d: DMA underrun\n", unit);
1019 ie->arpcom.ac_if.if_oerrors++;
1020 } else if(status & IE_XS_EXCMAX) {
1021 printf("ie%d: too many collisions\n", unit);
1022 ie->arpcom.ac_if.if_collisions += 16;
1023 ie->arpcom.ac_if.if_oerrors++;
1024 } else {
1025 ie->arpcom.ac_if.if_opackets++;
1026 ie->arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL;
1027 }
1028 }
1029 ie->xmit_count = 0;
1030
1031 /*
1032 * If multicast addresses were added or deleted while we were transmitting,
1033 * ie_mc_reset() set the want_mcsetup flag indicating that we should do it.
1034 */
1035 if(ie->want_mcsetup) {
1036 mc_setup(unit, (caddr_t)ie->xmit_cbuffs[0], ie->scb);
1037 ie->want_mcsetup = 0;
1038 }
1039
1040 /* Wish I knew why this seems to be necessary... */
1041 ie->xmit_cmds[0]->ie_xmit_status |= IE_STAT_COMPL;
1042
1043 iestart(&ie->arpcom.ac_if);
1044 return 0; /* shouldn't be necessary */
1045 }
1046
1047 /*
1048 * Process a receiver-not-ready interrupt. I believe that we get these
1049 * when there aren't enough buffers to go around. For now (FIXME), we
1050 * just restart the receiver, and hope everything's ok.
1051 */
1052 static int iernr(unit, ie)
1053 int unit;
1054 struct ie_softc *ie;
1055 {
1056 #ifdef doesnt_work
1057 setup_rfa((caddr_t)ie->rframes[0], ie);
1058
1059 ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1060 command_and_wait(unit, IE_RU_START, 0, 0);
1061 #else
1062 /* This doesn't work either, but it doesn't hang either. */
1063 command_and_wait(unit, IE_RU_DISABLE, 0, 0); /* just in case */
1064 setup_rfa((caddr_t)ie->rframes[0], ie); /* ignore cast-qual */
1065
1066 ie->scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
1067 command_and_wait(unit, IE_RU_START, 0, 0); /* was ENABLE */
1068
1069 #endif
1070 ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
1071
1072 ie->arpcom.ac_if.if_ierrors++;
1073 return 0;
1074 }
1075
1076 /*
1077 * Compare two Ether/802 addresses for equality, inlined and
1078 * unrolled for speed. I'd love to have an inline assembler
1079 * version of this...
1080 */
1081 static __inline int ether_equal(u_char *one, u_char *two) {
1082 if(one[0] != two[0]) return 0;
1083 if(one[1] != two[1]) return 0;
1084 if(one[2] != two[2]) return 0;
1085 if(one[3] != two[3]) return 0;
1086 if(one[4] != two[4]) return 0;
1087 if(one[5] != two[5]) return 0;
1088 return 1;
1089 }
1090
1091 /*
1092 * Check for a valid address. to_bpf is filled in with one of the following:
1093 * 0 -> BPF doesn't get this packet
1094 * 1 -> BPF does get this packet
1095 * 2 -> BPF does get this packet, but we don't
1096 * Return value is true if the packet is for us, and false otherwise.
1097 *
1098 * This routine is a mess, but it's also critical that it be as fast
1099 * as possible. It could be made cleaner if we can assume that the
1100 * only client which will fiddle with IFF_PROMISC is BPF. This is
1101 * probably a good assumption, but we do not make it here. (Yet.)
1102 */
1103 static __inline int check_eh(struct ie_softc *ie,
1104 struct ether_header *eh,
1105 int *to_bpf) {
1106 int i;
1107
1108 switch(ie->promisc) {
1109 case IFF_ALLMULTI:
1110 /*
1111 * Receiving all multicasts, but no unicasts except those destined for us.
1112 */
1113 #if NBPFILTER > 0
1114 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0); /* BPF gets this packet if anybody cares */
1115 #endif
1116 if(eh->ether_dhost[0] & 1) {
1117 return 1;
1118 }
1119 if(ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr)) return 1;
1120 return 0;
1121
1122 case IFF_PROMISC:
1123 /*
1124 * Receiving all packets. These need to be passed on to BPF.
1125 */
1126 #if NBPFILTER > 0
1127 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0);
1128 #endif
1129 /* If for us, accept and hand up to BPF */
1130 if(ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr)) return 1;
1131
1132 #if NBPFILTER > 0
1133 if(*to_bpf) *to_bpf = 2; /* we don't need to see it */
1134 #endif
1135
1136 /*
1137 * Not a multicast, so BPF wants to see it but we don't.
1138 */
1139 if(!(eh->ether_dhost[0] & 1)) return 1;
1140
1141 /*
1142 * If it's one of our multicast groups, accept it and pass it
1143 * up.
1144 */
1145 for(i = 0; i < ie->mcast_count; i++) {
1146 if(ether_equal(eh->ether_dhost, (u_char *)&ie->mcast_addrs[i])) {
1147 #if NBPFILTER > 0
1148 if(*to_bpf) *to_bpf = 1;
1149 #endif
1150 return 1;
1151 }
1152 }
1153 return 1;
1154
1155 case IFF_ALLMULTI | IFF_PROMISC:
1156 /*
1157 * Acting as a multicast router, and BPF running at the same time.
1158 * Whew! (Hope this is a fast machine...)
1159 */
1160 #if NBPFILTER > 0
1161 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0);
1162 #endif
1163 /* We want to see multicasts. */
1164 if(eh->ether_dhost[0] & 1) return 1;
1165
1166 /* We want to see our own packets */
1167 if(ether_equal(eh->ether_dhost, ie->arpcom.ac_enaddr)) return 1;
1168
1169 /* Anything else goes to BPF but nothing else. */
1170 #if NBPFILTER > 0
1171 if(*to_bpf) *to_bpf = 2;
1172 #endif
1173 return 1;
1174
1175 default:
1176 /*
1177 * Only accept unicast packets destined for us, or multicasts
1178 * for groups that we belong to. For now, we assume that the
1179 * '586 will only return packets that we asked it for. This
1180 * isn't strictly true (it uses hashing for the multicast filter),
1181 * but it will do in this case, and we want to get out of here
1182 * as quickly as possible.
1183 */
1184 #if NBPFILTER > 0
1185 *to_bpf = (ie->arpcom.ac_if.if_bpf != 0);
1186 #endif
1187 return 1;
1188 }
1189 return 0;
1190 }
1191
1192 /*
1193 * We want to isolate the bits that have meaning... This assumes that
1194 * IE_RBUF_SIZE is an even power of two. If somehow the act_len exceeds
1195 * the size of the buffer, then we are screwed anyway.
1196 */
1197 static __inline int ie_buflen(struct ie_softc *ie, int head) {
1198 return (ie->rbuffs[head]->ie_rbd_actual
1199 & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
1200 }
1201
1202 static __inline int ie_packet_len(int unit, struct ie_softc *ie) {
1203 int i;
1204 int head = ie->rbhead;
1205 int acc = 0;
1206
1207 do {
1208 if(!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1209 #ifdef DEBUG
1210 print_rbd(ie->rbuffs[ie->rbhead]);
1211 #endif
1212 log(LOG_ERR, "ie%d: receive descriptors out of sync at %d\n",
1213 unit, ie->rbhead);
1214 iereset(unit);
1215 return -1;
1216 }
1217
1218 i = ie->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
1219
1220 acc += ie_buflen(ie, head);
1221 head = (head + 1) % ie->nrxbufs;
1222 } while(!i);
1223
1224 return acc;
1225 }
1226
1227 /*
1228 * Read data off the interface, and turn it into an mbuf chain.
1229 *
1230 * This code is DRAMATICALLY different from the previous version; this
1231 * version tries to allocate the entire mbuf chain up front, given the
1232 * length of the data available. This enables us to allocate mbuf
1233 * clusters in many situations where before we would have had a long
1234 * chain of partially-full mbufs. This should help to speed up the
1235 * operation considerably. (Provided that it works, of course.)
1236 */
1237 static __inline int ieget(unit, ie, mp, ehp, to_bpf)
1238 int unit;
1239 struct ie_softc *ie;
1240 struct mbuf **mp;
1241 struct ether_header *ehp;
1242 int *to_bpf;
1243 {
1244 struct mbuf *m, *top, **mymp;
1245 int i;
1246 int offset;
1247 int totlen, resid;
1248 int thismboff;
1249 int head;
1250
1251 totlen = ie_packet_len(unit, ie);
1252 if(totlen <= 0) return -1;
1253
1254 i = ie->rbhead;
1255
1256 /*
1257 * Snarf the Ethernet header.
1258 */
1259 bcopy((caddr_t)ie->cbuffs[i], (caddr_t)ehp, sizeof *ehp);
1260 /* ignore cast-qual warning here */
1261
1262 /*
1263 * As quickly as possible, check if this packet is for us.
1264 * If not, don't waste a single cycle copying the rest of the
1265 * packet in.
1266 * This is only a consideration when FILTER is defined; i.e., when
1267 * we are either running BPF or doing multicasting.
1268 */
1269 if(!check_eh(ie, ehp, to_bpf)) {
1270 ie_drop_packet_buffer(unit, ie);
1271 ie->arpcom.ac_if.if_ierrors--; /* just this case, it's not an error */
1272 return -1;
1273 }
1274 totlen -= (offset = sizeof *ehp);
1275
1276 MGETHDR(*mp, M_DONTWAIT, MT_DATA);
1277 if(!*mp) {
1278 ie_drop_packet_buffer(unit, ie);
1279 return -1;
1280 }
1281
1282 m = *mp;
1283 m->m_pkthdr.rcvif = &ie->arpcom.ac_if;
1284 m->m_len = MHLEN;
1285 resid = m->m_pkthdr.len = totlen;
1286 top = 0;
1287 mymp = ⊤
1288
1289 /*
1290 * This loop goes through and allocates mbufs for all the data we will
1291 * be copying in. It does not actually do the copying yet.
1292 */
1293 do { /* while(resid > 0) */
1294 /*
1295 * Try to allocate an mbuf to hold the data that we have. If we
1296 * already allocated one, just get another one and stick it on the
1297 * end (eventually). If we don't already have one, try to allocate
1298 * an mbuf cluster big enough to hold the whole packet, if we think it's
1299 * reasonable, or a single mbuf which may or may not be big enough.
1300 * Got that?
1301 */
1302 if(top) {
1303 MGET(m, M_DONTWAIT, MT_DATA);
1304 if(!m) {
1305 m_freem(top);
1306 ie_drop_packet_buffer(unit, ie);
1307 return -1;
1308 }
1309 m->m_len = MLEN;
1310 }
1311
1312 if(resid >= MINCLSIZE) {
1313 MCLGET(m, M_DONTWAIT);
1314 if(m->m_flags & M_EXT)
1315 m->m_len = min(resid, MCLBYTES);
1316 } else {
1317 if(resid < m->m_len) {
1318 if(!top && resid + max_linkhdr <= m->m_len)
1319 m->m_data += max_linkhdr;
1320 m->m_len = resid;
1321 }
1322 }
1323 resid -= m->m_len;
1324 *mymp = m;
1325 mymp = &m->m_next;
1326 } while(resid > 0);
1327
1328 resid = totlen;
1329 m = top;
1330 thismboff = 0;
1331 head = ie->rbhead;
1332
1333 /*
1334 * Now we take the mbuf chain (hopefully only one mbuf most of the
1335 * time) and stuff the data into it. There are no possible failures
1336 * at or after this point.
1337 */
1338 while(resid > 0) { /* while there's stuff left */
1339 int thislen = ie_buflen(ie, head) - offset;
1340
1341 /*
1342 * If too much data for the current mbuf, then fill the current one
1343 * up, go to the next one, and try again.
1344 */
1345 if(thislen > m->m_len - thismboff) {
1346 int newlen = m->m_len - thismboff;
1347 bcopy((caddr_t)(ie->cbuffs[head] + offset),
1348 mtod(m, caddr_t) + thismboff, (unsigned)newlen);
1349 /* ignore cast-qual warning */
1350 m = m->m_next;
1351 thismboff = 0; /* new mbuf, so no offset */
1352 offset += newlen; /* we are now this far into the packet */
1353 resid -= newlen; /* so there is this much left to get */
1354 continue;
1355 }
1356
1357 /*
1358 * If there is more than enough space in the mbuf to hold the
1359 * contents of this buffer, copy everything in, advance pointers,
1360 * and so on.
1361 */
1362 if(thislen < m->m_len - thismboff) {
1363 bcopy((caddr_t)(ie->cbuffs[head] + offset), /* ignore warning */
1364 mtod(m, caddr_t) + thismboff, (unsigned)thislen);
1365 thismboff += thislen; /* we are this far into the mbuf */
1366 resid -= thislen; /* and this much is left */
1367 goto nextbuf;
1368 }
1369
1370 /*
1371 * Otherwise, there is exactly enough space to put this buffer's
1372 * contents into the current mbuf. Do the combination of the above
1373 * actions.
1374 */
1375 bcopy((caddr_t)(ie->cbuffs[head] + offset), /* ignore warning */
1376 mtod(m, caddr_t) + thismboff, (unsigned)thislen);
1377 m = m->m_next;
1378 thismboff = 0; /* new mbuf, start at the beginning */
1379 resid -= thislen; /* and we are this far through */
1380
1381 /*
1382 * Advance all the pointers. We can get here from either of the
1383 * last two cases, but never the first.
1384 */
1385 nextbuf:
1386 offset = 0;
1387 ie->rbuffs[head]->ie_rbd_actual = 0;
1388 ie->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
1389 ie->rbhead = head = (head + 1) % ie->nrxbufs;
1390 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1391 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1392 }
1393
1394 /*
1395 * Unless something changed strangely while we were doing the copy,
1396 * we have now copied everything in from the shared memory.
1397 * This means that we are done.
1398 */
1399 return 0;
1400 }
1401
1402 /*
1403 * Read frame NUM from unit UNIT (pre-cached as IE).
1404 *
1405 * This routine reads the RFD at NUM, and copies in the buffers from
1406 * the list of RBD, then rotates the RBD and RFD lists so that the receiver
1407 * doesn't start complaining. Trailers are DROPPED---there's no point
1408 * in wasting time on confusing code to deal with them. Hopefully,
1409 * this machine will never ARP for trailers anyway.
1410 */
1411 static void ie_readframe(unit, ie, num)
1412 int unit;
1413 struct ie_softc *ie;
1414 int num; /* frame number to read */
1415 {
1416 struct ie_recv_frame_desc rfd;
1417 struct mbuf *m = 0;
1418 struct ether_header eh;
1419 #if NBPFILTER > 0
1420 int bpf_gets_it = 0;
1421 #endif
1422
1423 bcopy((caddr_t)(ie->rframes[num]), &rfd, sizeof(struct ie_recv_frame_desc));
1424
1425 /* Immediately advance the RFD list, since we we have copied ours now. */
1426 ie->rframes[num]->ie_fd_status = 0;
1427 ie->rframes[num]->ie_fd_last |= IE_FD_LAST;
1428 ie->rframes[ie->rftail]->ie_fd_last &= ~IE_FD_LAST;
1429 ie->rftail = (ie->rftail + 1) % ie->nframes;
1430 ie->rfhead = (ie->rfhead + 1) % ie->nframes;
1431
1432 if(rfd.ie_fd_status & IE_FD_OK) {
1433 if(
1434 #if NBPFILTER > 0
1435 ieget(unit, ie, &m, &eh, &bpf_gets_it)
1436 #else
1437 ieget(unit, ie, &m, &eh, (int *)0)
1438 #endif
1439 ) {
1440 ie->arpcom.ac_if.if_ierrors++; /* this counts as an error */
1441 return;
1442 }
1443 }
1444
1445 #ifdef DEBUG
1446 if(ie_debug & IED_READFRAME) {
1447 printf("ie%d: frame from ether %6D type %x\n", unit,
1448 eh.ether_shost, ":", (unsigned)eh.ether_type);
1449 }
1450 if(ntohs(eh.ether_type) > ETHERTYPE_TRAIL
1451 && ntohs(eh.ether_type) < (ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER))
1452 printf("received trailer!\n");
1453 #endif
1454
1455 if(!m) return;
1456
1457 if(last_not_for_us) {
1458 m_freem(last_not_for_us);
1459 last_not_for_us = 0;
1460 }
1461
1462 #if NBPFILTER > 0
1463 /*
1464 * Check for a BPF filter; if so, hand it up.
1465 * Note that we have to stick an extra mbuf up front, because
1466 * bpf_mtap expects to have the ether header at the front.
1467 * It doesn't matter that this results in an ill-formatted mbuf chain,
1468 * since BPF just looks at the data. (It doesn't try to free the mbuf,
1469 * tho' it will make a copy for tcpdump.)
1470 */
1471 if(bpf_gets_it) {
1472 struct mbuf m0;
1473 m0.m_len = sizeof eh;
1474 m0.m_data = (caddr_t)&eh;
1475 m0.m_next = m;
1476
1477 /* Pass it up */
1478 bpf_mtap(&ie->arpcom.ac_if, &m0);
1479 }
1480 /*
1481 * A signal passed up from the filtering code indicating that the
1482 * packet is intended for BPF but not for the protocol machinery.
1483 * We can save a few cycles by not handing it off to them.
1484 */
1485 if(bpf_gets_it == 2) {
1486 last_not_for_us = m;
1487 return;
1488 }
1489 #endif /* NBPFILTER > 0 */
1490 /*
1491 * In here there used to be code to check destination addresses upon
1492 * receipt of a packet. We have deleted that code, and replaced it
1493 * with code to check the address much earlier in the cycle, before
1494 * copying the data in; this saves us valuable cycles when operating
1495 * as a multicast router or when using BPF.
1496 */
1497
1498 /*
1499 * Finally pass this packet up to higher layers.
1500 */
1501 ether_input(&ie->arpcom.ac_if, &eh, m);
1502 }
1503
1504 static void ie_drop_packet_buffer(int unit, struct ie_softc *ie) {
1505 int i;
1506
1507 do {
1508 /*
1509 * This means we are somehow out of sync. So, we reset the
1510 * adapter.
1511 */
1512 if(!(ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
1513 #ifdef DEBUG
1514 print_rbd(ie->rbuffs[ie->rbhead]);
1515 #endif
1516 log(LOG_ERR, "ie%d: receive descriptors out of sync at %d\n",
1517 unit, ie->rbhead);
1518 iereset(unit);
1519 return;
1520 }
1521
1522 i = ie->rbuffs[ie->rbhead]->ie_rbd_actual & IE_RBD_LAST;
1523
1524 ie->rbuffs[ie->rbhead]->ie_rbd_length |= IE_RBD_LAST;
1525 ie->rbuffs[ie->rbhead]->ie_rbd_actual = 0;
1526 ie->rbhead = (ie->rbhead + 1) % ie->nrxbufs;
1527 ie->rbuffs[ie->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
1528 ie->rbtail = (ie->rbtail + 1) % ie->nrxbufs;
1529 } while(!i);
1530 }
1531
1532
1533 /*
1534 * Start transmission on an interface.
1535 */
1536 static void
1537 iestart(ifp)
1538 struct ifnet *ifp;
1539 {
1540 struct ie_softc *ie = ifp->if_softc;
1541 struct mbuf *m0, *m;
1542 unsigned char *buffer;
1543 u_short len;
1544 /* This is not really volatile, in this routine, but it makes gcc happy. */
1545 volatile u_short *bptr = &ie->scb->ie_command_list;
1546
1547 if(!(ifp->if_flags & IFF_RUNNING))
1548 return;
1549 if(ifp->if_flags & IFF_OACTIVE)
1550 return;
1551
1552 do {
1553 IF_DEQUEUE(&ie->arpcom.ac_if.if_snd, m);
1554 if(!m)
1555 break;
1556
1557 buffer = ie->xmit_cbuffs[ie->xmit_count];
1558 len = 0;
1559
1560 for(m0 = m; m && len < IE_BUF_LEN; m = m->m_next) {
1561 bcopy(mtod(m, caddr_t), buffer, m->m_len);
1562 buffer += m->m_len;
1563 len += m->m_len;
1564 }
1565
1566 m_freem(m0);
1567 len = max(len, ETHER_MIN_LEN);
1568
1569 #if NBPFILTER > 0
1570 /*
1571 * See if bpf is listening on this interface, let it see the packet
1572 * before we commit it to the wire.
1573 */
1574 if(ie->arpcom.ac_if.if_bpf)
1575 bpf_tap(&ie->arpcom.ac_if, ie->xmit_cbuffs[ie->xmit_count], len);
1576 #endif
1577
1578 ie->xmit_buffs[ie->xmit_count]->ie_xmit_flags = IE_XMIT_LAST | len;
1579 ie->xmit_buffs[ie->xmit_count]->ie_xmit_next = 0xffff;
1580 ie->xmit_buffs[ie->xmit_count]->ie_xmit_buf =
1581 MK_24(ie->iomem, ie->xmit_cbuffs[ie->xmit_count]);
1582
1583 ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_cmd = IE_CMD_XMIT;
1584 ie->xmit_cmds[ie->xmit_count]->ie_xmit_status = 0;
1585 ie->xmit_cmds[ie->xmit_count]->ie_xmit_desc =
1586 MK_16(ie->iomem, ie->xmit_buffs[ie->xmit_count]);
1587
1588 *bptr = MK_16(ie->iomem, ie->xmit_cmds[ie->xmit_count]);
1589 bptr = &ie->xmit_cmds[ie->xmit_count]->com.ie_cmd_link;
1590 ie->xmit_count++;
1591 } while (ie->xmit_count < ie->ntxbufs);
1592
1593 /*
1594 * If we queued up anything for transmission, send it.
1595 */
1596 if(ie->xmit_count) {
1597 ie->xmit_cmds[ie->xmit_count - 1]->com.ie_cmd_cmd |=
1598 IE_CMD_LAST | IE_CMD_INTR;
1599
1600 /*
1601 * By passing the command pointer as a null, we tell
1602 * command_and_wait() to pretend that this isn't an action
1603 * command. I wish I understood what was happening here.
1604 */
1605 command_and_wait(ifp->if_unit, IE_CU_START, 0, 0);
1606 ifp->if_flags |= IFF_OACTIVE;
1607 }
1608
1609 return;
1610 }
1611
1612 /*
1613 * Check to see if there's an 82586 out there.
1614 */
1615 static int
1616 check_ie_present(unit, where, size)
1617 int unit;
1618 caddr_t where;
1619 unsigned size;
1620 {
1621 volatile struct ie_sys_conf_ptr *scp;
1622 volatile struct ie_int_sys_conf_ptr *iscp;
1623 volatile struct ie_sys_ctl_block *scb;
1624 u_long realbase;
1625 int s;
1626
1627 s = splimp();
1628
1629 realbase = (u_long)where + size - (1 << 24);
1630
1631 scp = (volatile struct ie_sys_conf_ptr *)(realbase + IE_SCP_ADDR);
1632 bzero((char *)scp, sizeof *scp); /* ignore cast-qual */
1633
1634 /*
1635 * First we put the ISCP at the bottom of memory; this tests to make
1636 * sure that our idea of the size of memory is the same as the controller's.
1637 * This is NOT where the ISCP will be in normal operation.
1638 */
1639 iscp = (volatile struct ie_int_sys_conf_ptr *)where;
1640 bzero((char *)iscp, sizeof *iscp); /* ignore cast-qual */
1641
1642 scb = (volatile struct ie_sys_ctl_block *)where;
1643 bzero((char *)scb, sizeof *scb); /* ignore cast-qual */
1644
1645 scp->ie_bus_use = ie_softc[unit].bus_use; /* 8-bit or 16-bit */
1646 scp->ie_iscp_ptr = (caddr_t)((volatile caddr_t)iscp - /* ignore cast-qual */
1647 (volatile caddr_t)realbase);
1648
1649 iscp->ie_busy = 1;
1650 iscp->ie_scb_offset = MK_16(realbase, scb) + 256;
1651
1652 (*ie_softc[unit].ie_reset_586)(unit);
1653 (*ie_softc[unit].ie_chan_attn)(unit);
1654
1655 DELAY(100); /* wait a while... */
1656
1657 if(iscp->ie_busy) {
1658 splx(s);
1659 return 0;
1660 }
1661
1662 /*
1663 * Now relocate the ISCP to its real home, and reset the controller
1664 * again.
1665 */
1666 iscp = (void *)Align((caddr_t)(realbase + IE_SCP_ADDR -
1667 sizeof(struct ie_int_sys_conf_ptr)));
1668 bzero((char *)iscp, sizeof *iscp); /* ignore cast-qual */
1669
1670 scp->ie_iscp_ptr = (caddr_t)((caddr_t)iscp - (caddr_t)realbase);
1671 /* ignore cast-qual */
1672
1673 iscp->ie_busy = 1;
1674 iscp->ie_scb_offset = MK_16(realbase, scb);
1675
1676 (*ie_softc[unit].ie_reset_586)(unit);
1677 (*ie_softc[unit].ie_chan_attn)(unit);
1678
1679 DELAY(100);
1680
1681 if(iscp->ie_busy) {
1682 splx(s);
1683 return 0;
1684 }
1685
1686 ie_softc[unit].iosize = size;
1687 ie_softc[unit].iomem = (caddr_t)realbase;
1688
1689 ie_softc[unit].iscp = iscp;
1690 ie_softc[unit].scb = scb;
1691
1692 /*
1693 * Acknowledge any interrupts we may have caused...
1694 */
1695 ie_ack(scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
1696 splx(s);
1697
1698 return 1;
1699 }
1700
1701 /*
1702 * Divine the memory size of ie board UNIT.
1703 * Better hope there's nothing important hiding just below the ie card...
1704 */
1705 static void find_ie_mem_size(unit)
1706 int unit;
1707 {
1708 unsigned size;
1709
1710 ie_softc[unit].iosize = 0;
1711
1712 for(size = 65536; size >= 8192; size -= 8192) {
1713 if(check_ie_present(unit, ie_softc[unit].iomembot, size)) {
1714 return;
1715 }
1716 }
1717
1718 return;
1719 }
1720
1721 void el_reset_586(unit)
1722 int unit;
1723 {
1724 outb(PORT + IE507_CTRL, EL_CTRL_RESET);
1725 DELAY(100);
1726 outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
1727 DELAY(100);
1728 }
1729
1730 void sl_reset_586(unit)
1731 int unit;
1732 {
1733 outb(PORT + IEATT_RESET, 0);
1734 }
1735
1736 void
1737 ee16_reset_586(unit)
1738 int unit;
1739 {
1740 outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
1741 DELAY(100);
1742 outb(PORT + IEE16_ECTRL, 0);
1743 DELAY(100);
1744 }
1745
1746 void el_chan_attn(unit)
1747 int unit;
1748 {
1749 outb(PORT + IE507_ATTN, 1);
1750 }
1751
1752 void sl_chan_attn(unit)
1753 int unit;
1754 {
1755 outb(PORT + IEATT_ATTN, 0);
1756 }
1757
1758 void
1759 ee16_chan_attn(unit)
1760 int unit;
1761 {
1762 outb(PORT + IEE16_ATTN, 0);
1763 }
1764
1765 u_short
1766 ee16_read_eeprom(sc, location)
1767 struct ie_softc *sc;
1768 int location;
1769 {
1770 int ectrl, edata;
1771
1772 ectrl = inb(sc->port + IEE16_ECTRL);
1773 ectrl &= IEE16_ECTRL_MASK;
1774 ectrl |= IEE16_ECTRL_EECS;
1775 outb(sc->port + IEE16_ECTRL, ectrl);
1776
1777 ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
1778 ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
1779 edata = ee16_eeprom_inbits(sc);
1780 ectrl = inb(sc->port + IEE16_ECTRL);
1781 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
1782 outb(sc->port + IEE16_ECTRL, ectrl);
1783 ee16_eeprom_clock(sc, 1);
1784 ee16_eeprom_clock(sc, 0);
1785 return edata;
1786 }
1787
1788 void
1789 ee16_eeprom_outbits(sc, edata, count)
1790 struct ie_softc *sc;
1791 int edata, count;
1792 {
1793 int ectrl, i;
1794
1795 ectrl = inb(sc->port + IEE16_ECTRL);
1796 ectrl &= ~IEE16_RESET_ASIC;
1797 for (i = count - 1; i >= 0; i--) {
1798 ectrl &= ~IEE16_ECTRL_EEDI;
1799 if (edata & (1 << i)) {
1800 ectrl |= IEE16_ECTRL_EEDI;
1801 }
1802 outb(sc->port + IEE16_ECTRL, ectrl);
1803 DELAY(1); /* eeprom data must be setup for 0.4 uSec */
1804 ee16_eeprom_clock(sc, 1);
1805 ee16_eeprom_clock(sc, 0);
1806 }
1807 ectrl &= ~IEE16_ECTRL_EEDI;
1808 outb(sc->port + IEE16_ECTRL, ectrl);
1809 DELAY(1); /* eeprom data must be held for 0.4 uSec */
1810 }
1811
1812 int
1813 ee16_eeprom_inbits(sc)
1814 struct ie_softc *sc;
1815 {
1816 int ectrl, edata, i;
1817
1818 ectrl = inb(sc->port + IEE16_ECTRL);
1819 ectrl &= ~IEE16_RESET_ASIC;
1820 for (edata = 0, i = 0; i < 16; i++) {
1821 edata = edata << 1;
1822 ee16_eeprom_clock(sc, 1);
1823 ectrl = inb(sc->port + IEE16_ECTRL);
1824 if (ectrl & IEE16_ECTRL_EEDO) {
1825 edata |= 1;
1826 }
1827 ee16_eeprom_clock(sc, 0);
1828 }
1829 return (edata);
1830 }
1831
1832 void
1833 ee16_eeprom_clock(sc, state)
1834 struct ie_softc *sc;
1835 int state;
1836 {
1837 int ectrl;
1838
1839 ectrl = inb(sc->port + IEE16_ECTRL);
1840 ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
1841 if (state) {
1842 ectrl |= IEE16_ECTRL_EESK;
1843 }
1844 outb(sc->port + IEE16_ECTRL, ectrl);
1845 DELAY(9); /* EESK must be stable for 8.38 uSec */
1846 }
1847
1848 static __inline void
1849 ee16_interrupt_enable(sc)
1850 struct ie_softc *sc;
1851 {
1852 DELAY(100);
1853 outb(sc->port + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
1854 DELAY(100);
1855 }
1856
1857 void sl_read_ether(unit, addr)
1858 int unit;
1859 unsigned char addr[6];
1860 {
1861 int i;
1862
1863 for(i = 0; i < 6; i++)
1864 addr[i] = inb(PORT + i);
1865 }
1866
1867
1868 static void
1869 iereset(unit)
1870 int unit;
1871 {
1872 int s = splimp();
1873
1874 if(unit >= NIE) {
1875 splx(s);
1876 return;
1877 }
1878
1879 printf("ie%d: reset\n", unit);
1880 ie_softc[unit].arpcom.ac_if.if_flags &= ~IFF_UP;
1881 ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0);
1882
1883 /*
1884 * Stop i82586 dead in its tracks.
1885 */
1886 if(command_and_wait(unit, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
1887 printf("ie%d: abort commands timed out\n", unit);
1888
1889 if(command_and_wait(unit, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
1890 printf("ie%d: disable commands timed out\n", unit);
1891
1892 #ifdef notdef
1893 if(!check_ie_present(unit, ie_softc[unit].iomembot, ie_softc[unit].iosize))
1894 panic("ie disappeared!");
1895 #endif
1896
1897 ie_softc[unit].arpcom.ac_if.if_flags |= IFF_UP;
1898 ieioctl(&ie_softc[unit].arpcom.ac_if, SIOCSIFFLAGS, 0);
1899
1900 splx(s);
1901 return;
1902 }
1903
1904 /*
1905 * This is called if we time out.
1906 */
1907 static void
1908 chan_attn_timeout(rock)
1909 void *rock;
1910 {
1911 *(int *)rock = 1;
1912 }
1913
1914 /*
1915 * Send a command to the controller and wait for it to either
1916 * complete or be accepted, depending on the command. If the
1917 * command pointer is null, then pretend that the command is
1918 * not an action command. If the command pointer is not null,
1919 * and the command is an action command, wait for
1920 * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
1921 * to become true.
1922 */
1923 static int command_and_wait(unit, cmd, pcmd, mask)
1924 int unit;
1925 int cmd;
1926 volatile void *pcmd;
1927 int mask;
1928 {
1929 volatile struct ie_cmd_common *cc = pcmd;
1930 volatile int timedout = 0;
1931
1932 ie_softc[unit].scb->ie_command = (u_short)cmd;
1933
1934 if(IE_ACTION_COMMAND(cmd) && pcmd) {
1935 (*ie_softc[unit].ie_chan_attn)(unit);
1936
1937 /*
1938 * According to the packet driver, the minimum timeout should be
1939 * .369 seconds, which we round up to .37.
1940 */
1941 timeout(chan_attn_timeout, (caddr_t)&timedout, 37 * hz / 100);
1942 /* ignore cast-qual */
1943
1944 /*
1945 * Now spin-lock waiting for status. This is not a very nice
1946 * thing to do, but I haven't figured out how, or indeed if, we
1947 * can put the process waiting for action to sleep. (We may
1948 * be getting called through some other timeout running in the
1949 * kernel.)
1950 */
1951 while(1) {
1952 if((cc->ie_cmd_status & mask) || timedout)
1953 break;
1954 }
1955
1956 untimeout(chan_attn_timeout, (caddr_t)&timedout);
1957 /* ignore cast-qual */
1958
1959 return timedout;
1960 } else {
1961
1962 /*
1963 * Otherwise, just wait for the command to be accepted.
1964 */
1965 (*ie_softc[unit].ie_chan_attn)(unit);
1966
1967 while(ie_softc[unit].scb->ie_command)
1968 ; /* spin lock */
1969
1970 return 0;
1971 }
1972 }
1973
1974 /*
1975 * Run the time-domain reflectometer...
1976 */
1977 static void run_tdr(unit, cmd)
1978 int unit;
1979 struct ie_tdr_cmd *cmd;
1980 {
1981 int result;
1982
1983 cmd->com.ie_cmd_status = 0;
1984 cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
1985 cmd->com.ie_cmd_link = 0xffff;
1986 cmd->ie_tdr_time = 0;
1987
1988 ie_softc[unit].scb->ie_command_list = MK_16(MEM, cmd);
1989 cmd->ie_tdr_time = 0;
1990
1991 if(command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL))
1992 result = 0x2000;
1993 else
1994 result = cmd->ie_tdr_time;
1995
1996 ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit,
1997 ie_softc[unit].ie_chan_attn);
1998
1999 if(result & IE_TDR_SUCCESS)
2000 return;
2001
2002 if(result & IE_TDR_XCVR) {
2003 printf("ie%d: transceiver problem\n", unit);
2004 } else if(result & IE_TDR_OPEN) {
2005 printf("ie%d: TDR detected an open %d clocks away\n", unit,
2006 result & IE_TDR_TIME);
2007 } else if(result & IE_TDR_SHORT) {
2008 printf("ie%d: TDR detected a short %d clocks away\n", unit,
2009 result & IE_TDR_TIME);
2010 } else {
2011 printf("ie%d: TDR returned unknown status %x\n", unit, result);
2012 }
2013 }
2014
2015 static void start_receiver(unit)
2016 int unit;
2017 {
2018 int s = splimp();
2019
2020 ie_softc[unit].scb->ie_recv_list = MK_16(MEM, ie_softc[unit].rframes[0]);
2021 command_and_wait(unit, IE_RU_START, 0, 0);
2022
2023 ie_ack(ie_softc[unit].scb, IE_ST_WHENCE, unit, ie_softc[unit].ie_chan_attn);
2024
2025 splx(s);
2026 }
2027
2028 /*
2029 * Here is a helper routine for iernr() and ieinit(). This sets up
2030 * the RFA.
2031 */
2032 static caddr_t setup_rfa(caddr_t ptr, struct ie_softc *ie) {
2033 volatile struct ie_recv_frame_desc *rfd = (void *)ptr;
2034 volatile struct ie_recv_buf_desc *rbd;
2035 int i;
2036 int unit = ie - &ie_softc[0];
2037
2038 /* First lay them out */
2039 for(i = 0; i < ie->nframes; i++) {
2040 ie->rframes[i] = rfd;
2041 bzero((char *)rfd, sizeof *rfd); /* ignore cast-qual */
2042 rfd++;
2043 }
2044
2045 ptr = (caddr_t)Align((caddr_t)rfd); /* ignore cast-qual */
2046
2047 /* Now link them together */
2048 for(i = 0; i < ie->nframes; i++) {
2049 ie->rframes[i]->ie_fd_next =
2050 MK_16(MEM, ie->rframes[(i + 1) % ie->nframes]);
2051 }
2052
2053 /* Finally, set the EOL bit on the last one. */
2054 ie->rframes[ie->nframes - 1]->ie_fd_last |= IE_FD_LAST;
2055
2056 /*
2057 * Now lay out some buffers for the incoming frames. Note that
2058 * we set aside a bit of slop in each buffer, to make sure that
2059 * we have enough space to hold a single frame in every buffer.
2060 */
2061 rbd = (void *)ptr;
2062
2063 for(i = 0; i < ie->nrxbufs; i++) {
2064 ie->rbuffs[i] = rbd;
2065 bzero((char *)rbd, sizeof *rbd); /* ignore cast-qual */
2066 ptr = (caddr_t)Align(ptr + sizeof *rbd);
2067 rbd->ie_rbd_length = IE_RBUF_SIZE;
2068 rbd->ie_rbd_buffer = MK_24(MEM, ptr);
2069 ie->cbuffs[i] = (void *)ptr;
2070 ptr += IE_RBUF_SIZE;
2071 rbd = (void *)ptr;
2072 }
2073
2074 /* Now link them together */
2075 for(i = 0; i < ie->nrxbufs; i++) {
2076 ie->rbuffs[i]->ie_rbd_next = MK_16(MEM, ie->rbuffs[(i + 1) % ie->nrxbufs]);
2077 }
2078
2079 /* Tag EOF on the last one */
2080 ie->rbuffs[ie->nrxbufs - 1]->ie_rbd_length |= IE_RBD_LAST;
2081
2082 /* We use the head and tail pointers on receive to keep track of
2083 * the order in which RFDs and RBDs are used. */
2084 ie->rfhead = 0;
2085 ie->rftail = ie->nframes - 1;
2086 ie->rbhead = 0;
2087 ie->rbtail = ie->nrxbufs - 1;
2088
2089 ie->scb->ie_recv_list = MK_16(MEM, ie->rframes[0]);
2090 ie->rframes[0]->ie_fd_buf_desc = MK_16(MEM, ie->rbuffs[0]);
2091
2092 ptr = Align(ptr);
2093 return ptr;
2094 }
2095
2096 /*
2097 * Run the multicast setup command.
2098 * Call at splimp().
2099 */
2100 static int mc_setup(int unit, caddr_t ptr,
2101 volatile struct ie_sys_ctl_block *scb) {
2102 struct ie_softc *ie = &ie_softc[unit];
2103 volatile struct ie_mcast_cmd *cmd = (void *)ptr;
2104
2105 cmd->com.ie_cmd_status = 0;
2106 cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
2107 cmd->com.ie_cmd_link = 0xffff;
2108
2109 /* ignore cast-qual */
2110 bcopy((caddr_t)ie->mcast_addrs, (caddr_t)cmd->ie_mcast_addrs,
2111 ie->mcast_count * sizeof *ie->mcast_addrs);
2112
2113 cmd->ie_mcast_bytes = ie->mcast_count * 6; /* grrr... */
2114
2115 scb->ie_command_list = MK_16(MEM, cmd);
2116 if(command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2117 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
2118 printf("ie%d: multicast address setup command failed\n", unit);
2119 return 0;
2120 }
2121 return 1;
2122 }
2123
2124 /*
2125 * This routine takes the environment generated by check_ie_present()
2126 * and adds to it all the other structures we need to operate the adapter.
2127 * This includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands,
2128 * starting the receiver unit, and clearing interrupts.
2129 *
2130 * THIS ROUTINE MUST BE CALLED AT splimp() OR HIGHER.
2131 */
2132 static void
2133 ieinit(unit)
2134 int unit;
2135 {
2136 struct ie_softc *ie = &ie_softc[unit];
2137 volatile struct ie_sys_ctl_block *scb = ie->scb;
2138 caddr_t ptr;
2139 int i;
2140
2141 ptr = (caddr_t)Align((caddr_t)scb + sizeof *scb); /* ignore cast-qual */
2142
2143 /*
2144 * Send the configure command first.
2145 */
2146 {
2147 volatile struct ie_config_cmd *cmd = (void *)ptr;
2148
2149 ie_setup_config(cmd, ie->promisc, ie->hard_type == IE_STARLAN10);
2150 cmd->com.ie_cmd_status = 0;
2151 cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
2152 cmd->com.ie_cmd_link = 0xffff;
2153
2154 scb->ie_command_list = MK_16(MEM, cmd);
2155
2156 if(command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2157 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
2158 printf("ie%d: configure command failed\n", unit);
2159 return;
2160 }
2161 }
2162 /*
2163 * Now send the Individual Address Setup command.
2164 */
2165 {
2166 volatile struct ie_iasetup_cmd *cmd = (void *)ptr;
2167
2168 cmd->com.ie_cmd_status = 0;
2169 cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
2170 cmd->com.ie_cmd_link = 0xffff;
2171
2172 bcopy((char *)ie_softc[unit].arpcom.ac_enaddr, (char *)&cmd->ie_address,
2173 sizeof cmd->ie_address); /* ignore cast-qual */
2174
2175 scb->ie_command_list = MK_16(MEM, cmd);
2176 if(command_and_wait(unit, IE_CU_START, cmd, IE_STAT_COMPL)
2177 || !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
2178 printf("ie%d: individual address setup command failed\n", unit);
2179 return;
2180 }
2181 }
2182
2183 /*
2184 * Now run the time-domain reflectometer.
2185 */
2186 run_tdr(unit, (void *)ptr);
2187
2188 /*
2189 * Acknowledge any interrupts we have generated thus far.
2190 */
2191 ie_ack(ie->scb, IE_ST_WHENCE, unit, ie->ie_chan_attn);
2192
2193 /*
2194 * Set up the RFA.
2195 */
2196 ptr = setup_rfa(ptr, ie);
2197
2198 /*
2199 * Finally, the transmit command and buffer are the last little bit of work.
2200 */
2201
2202 /* transmit command buffers */
2203 for (i = 0; i < ie->ntxbufs; i++) {
2204 ie->xmit_cmds[i] = (void *)ptr;
2205 ptr += sizeof *ie->xmit_cmds[i];
2206 ptr = Align(ptr);
2207 ie->xmit_buffs[i] = (void *)ptr;
2208 ptr += sizeof *ie->xmit_buffs[i];
2209 ptr = Align(ptr);
2210 }
2211
2212 /* transmit buffers */
2213 for (i = 0; i < ie->ntxbufs - 1; i++) {
2214 ie->xmit_cbuffs[i] = (void *)ptr;
2215 ptr += IE_BUF_LEN;
2216 ptr = Align(ptr);
2217 }
2218 ie->xmit_cbuffs[ie->ntxbufs - 1] = (void *)ptr;
2219
2220 for (i = 1; i < ie->ntxbufs; i++) { /* ignore */
2221 bzero((caddr_t)ie->xmit_cmds[i], sizeof *ie->xmit_cmds[i]); /* cast-qual */
2222 bzero((caddr_t)ie->xmit_buffs[i], sizeof *ie->xmit_buffs[i]);/* warnings */
2223 } /* here */
2224
2225 /*
2226 * This must be coordinated with iestart() and ietint().
2227 */
2228 ie->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
2229
2230 /* take the ee16 out of loopback */
2231 if(ie->hard_type == IE_EE16) {
2232 u_int8_t bart_config;
2233
2234 bart_config = inb(PORT + IEE16_CONFIG);
2235 bart_config &= ~IEE16_BART_LOOPBACK;
2236 /* inb doesn't get bit! */
2237 bart_config |= IEE16_BART_MCS16_TEST;
2238 outb(PORT + IEE16_CONFIG, bart_config);
2239 ee16_interrupt_enable(ie);
2240 ee16_chan_attn(unit);
2241 }
2242
2243 ie->arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels we're here */
2244 start_receiver(unit);
2245
2246 return;
2247 }
2248
2249 static void ie_stop(unit)
2250 int unit;
2251 {
2252 command_and_wait(unit, IE_RU_DISABLE, 0, 0);
2253 }
2254
2255 static int
2256 ieioctl(ifp, command, data)
2257 struct ifnet *ifp;
2258 int command;
2259 caddr_t data;
2260 {
2261 struct ifaddr *ifa = (struct ifaddr *)data;
2262 struct ie_softc *ie = ifp->if_softc;
2263 struct ifreq *ifr = (struct ifreq *) data;
2264 int s, error = 0;
2265
2266 s = splimp();
2267
2268 switch(command) {
2269 case SIOCSIFADDR:
2270 ifp->if_flags |= IFF_UP;
2271
2272 switch(ifa->ifa_addr->sa_family) {
2273 #ifdef INET
2274 case AF_INET:
2275 ieinit(ifp->if_unit);
2276 arp_ifinit((struct arpcom *)ifp, ifa);
2277 break;
2278 #endif /* INET */
2279
2280 #ifdef IPX
2281 /* This magic copied from if_is.c; I don't use XNS, so I have no
2282 * way of telling if this actually works or not.
2283 */
2284 case AF_IPX:
2285 {
2286 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
2287
2288 if(ipx_nullhost(*ina)) {
2289 ina->x_host = *(union ipx_host *)(ie->arpcom.ac_enaddr);
2290 } else {
2291 ifp->if_flags &= ~IFF_RUNNING;
2292 bcopy((caddr_t)ina->x_host.c_host,
2293 (caddr_t)ie->arpcom.ac_enaddr,
2294 sizeof ie->arpcom.ac_enaddr);
2295 }
2296
2297 ieinit(ifp->if_unit);
2298 }
2299 break;
2300 #endif /* IPX */
2301
2302 #ifdef NS
2303 /* This magic copied from if_is.c; I don't use XNS, so I have no
2304 * way of telling if this actually works or not.
2305 */
2306 case AF_NS:
2307 {
2308 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
2309
2310 if(ns_nullhost(*ina)) {
2311 ina->x_host = *(union ns_host *)(ie->arpcom.ac_enaddr);
2312 } else {
2313 ifp->if_flags &= ~IFF_RUNNING;
2314 bcopy((caddr_t)ina->x_host.c_host,
2315 (caddr_t)ie->arpcom.ac_enaddr,
2316 sizeof ie->arpcom.ac_enaddr);
2317 }
2318
2319 ieinit(ifp->if_unit);
2320 }
2321 break;
2322 #endif /* NS */
2323
2324 default:
2325 ieinit(ifp->if_unit);
2326 break;
2327 }
2328 break;
2329
2330 case SIOCSIFFLAGS:
2331 /*
2332 * Note that this device doesn't have an "all multicast" mode, so we
2333 * must turn on promiscuous mode and do the filtering manually.
2334 */
2335 if((ifp->if_flags & IFF_UP) == 0 &&
2336 (ifp->if_flags & IFF_RUNNING)) {
2337 ifp->if_flags &= ~IFF_RUNNING;
2338 ie_stop(ifp->if_unit);
2339 } else if((ifp->if_flags & IFF_UP) &&
2340 (ifp->if_flags & IFF_RUNNING) == 0) {
2341 ie_softc[ifp->if_unit].promisc =
2342 ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2343 ieinit(ifp->if_unit);
2344 } else if(ie_softc[ifp->if_unit].promisc ^
2345 (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))) {
2346 ie_softc[ifp->if_unit].promisc =
2347 ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
2348 ieinit(ifp->if_unit);
2349 }
2350 break;
2351
2352 case SIOCADDMULTI:
2353 case SIOCDELMULTI:
2354 /*
2355 * Update multicast listeners
2356 */
2357 error = ((command == SIOCADDMULTI)
2358 ? ether_addmulti(ifr, &ie->arpcom)
2359 : ether_delmulti(ifr, &ie->arpcom));
2360
2361 if(error == ENETRESET) {
2362 /* reset multicast filtering */
2363 ie_mc_reset(ifp->if_unit);
2364 error = 0;
2365 }
2366 break;
2367
2368 case SIOCSIFMTU:
2369 /*
2370 * Set the interface MTU.
2371 */
2372 if (ifr->ifr_mtu > ETHERMTU) {
2373 error = EINVAL;
2374 } else {
2375 ifp->if_mtu = ifr->ifr_mtu;
2376 }
2377 break;
2378
2379 default:
2380 error = EINVAL;
2381 }
2382
2383 splx(s);
2384 return error;
2385 }
2386
2387 static void ie_mc_reset(int unit) {
2388 struct ie_softc *ie = &ie_softc[unit];
2389 struct ether_multi *enm;
2390 struct ether_multistep step;
2391
2392 /*
2393 * Step through the list of addresses.
2394 */
2395 ie->mcast_count = 0;
2396 ETHER_FIRST_MULTI(step, &ie->arpcom, enm);
2397 while(enm) {
2398 if(ie->mcast_count >= MAXMCAST
2399 || bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
2400 ie->arpcom.ac_if.if_flags |= IFF_ALLMULTI;
2401 ieioctl(&ie->arpcom.ac_if, SIOCSIFFLAGS, (void *)0);
2402 goto setflag;
2403 }
2404
2405 bcopy(enm->enm_addrlo, &(ie->mcast_addrs[ie->mcast_count]), 6);
2406 ie->mcast_count++;
2407 ETHER_NEXT_MULTI(step, enm);
2408 }
2409
2410 setflag:
2411 ie->want_mcsetup = 1;
2412 }
2413
2414
2415 #ifdef DEBUG
2416 void print_rbd(volatile struct ie_recv_buf_desc *rbd) {
2417 printf("RBD at %08lx:\n"
2418 "actual %04x, next %04x, buffer %08x\n"
2419 "length %04x, mbz %04x\n",
2420 (unsigned long)rbd,
2421 rbd->ie_rbd_actual, rbd->ie_rbd_next, rbd->ie_rbd_buffer,
2422 rbd->ie_rbd_length, rbd->mbz);
2423 }
2424 #endif /* DEBUG */
2425 #endif /* NIE > 0 */
2426
Cache object: b8e1f1b30d23aca9bf5a2c46064fb1e3
|