sc);
sc, sc->sc_dev.dv_xname);
struct mbuf *ieget __P((struct ie_softc *,    struct ether_header *, int *));void iememinit __P((void *, struct ie_softc *));static int mc_setup __P((struct ie_softc *, void *));static void mc_reset __P((struct ie_softc *));#ifdef IEDEBUGvoid print_rbd __P((volatile struct ie_recv_buf_desc *));int in_ierint = 0;int in_ietint = 0;#endifint ieprobe __P((struct device *, void *, void *));void ieattach __P((struct device *, struct device *, void *));struct cfdriver iecd = {	NULL, "ie", ieprobe, ieattach, DV_IFNET, sizeof(struct ie_softc)};#define MK_24(base, ptr) ((caddr_t)((u_long)ptr - (u_long)base))#define MK_16(base, ptr) ((u_short)(u_long)MK_24(base, ptr))#define PORT	sc->sc_iobase#define MEM 	sc->sc_maddr/* * Here are a few useful functions.  We could have done these as macros, but * since we have the inline facility, it makes sense to use that instead. */static inline voidie_setup_config(cmd, promiscuous, manchester)	volatile struct ie_config_cmd *cmd;	int promiscuous, manchester;{	cmd->ie_config_count = 0x0c;	cmd->ie_fifo = 8;	cmd->ie_save_bad = 0x40;	cmd->ie_addr_len = 0x2e;	cmd->ie_priority = 0;	cmd->ie_ifs = 0x60;	cmd->ie_slot_low = 0;	cmd->ie_slot_high = 0xf2;	cmd->ie_promisc = promiscuous | manchester << 2;	cmd->ie_crs_cdt = 0;	cmd->ie_min_len = 64;	cmd->ie_junk = 0xff;}static inline voidie_ack(sc, mask)	struct ie_softc *sc;	u_int mask;{	volatile struct ie_sys_ctl_block *scb = sc->scb;	scb->ie_command = scb->ie_status & mask;	(sc->chan_attn)(sc);	while (scb->ie_command)		;		/* Spin Lock */}intieprobe(parent, match, aux)	struct device *parent;	void *match, *aux;{	struct ie_softc *sc = match;	struct isa_attach_args *ia = aux;	if (sl_probe(sc, ia))		return 1;	if (el_probe(sc, ia))		return 1;	if (ee16_probe(sc, ia))		return 1;	return 0;}intsl_probe(sc, ia)	struct ie_softc *sc;	struct isa_attach_args *ia;{	u_char c;	sc->sc_iobase = ia->ia_iobase;	/* Need this for part of the probe. */	sc->reset_586 = sl_reset_586;	sc->chan_attn = sl_chan_attn;	c = inb(PORT + IEATT_REVISION);	switch (SL_BOARD(c)) {	case SL10_BOARD:		sc->hard_type = IE_STARLAN10;		break;	case EN100_BOARD:		sc->hard_type = IE_EN100;		break;	case SLFIBER_BOARD:		sc->hard_type = IE_SLFIBER;		break;	default:		/* Anything else is not recognized or cannot be used. */#ifdef DIAGNOSTIC		printf("%s: unknown AT&T board type code %d\n",		    sc->sc_dev.dv_xname, SL_BOARD(c));#endif		return 0;	}	sc->hard_vers = SL_REV(c);	if (ia->ia_irq == IRQUNK || ia->ia_maddr == MADDRUNK) {		printf("%s: %s does not have soft configuration\n",		    sc->sc_dev.dv_xname, ie_hardware_names[sc->hard_type]);		return 0;	}	/*	 * Divine memory size on-board the card.  Ususally 16k.	 */	sc->sc_maddr = ISA_HOLE_VADDR(ia->ia_maddr);	ie_find_mem_size(sc);	if (!sc->sc_msize) {		printf("%s: can't find shared memory\n", sc->sc_dev.dv_xname);		return 0;	}	if (!ia->ia_msize)		ia->ia_msize = sc->sc_msize;	else if (ia->ia_msize != sc->sc_msize) {		printf("%s: msize mismatch; kernel configured %d != board configured %d\n",		    sc->sc_dev.dv_xname, ia->ia_msize, sc->sc_msize);		return 0;	}	slel_get_address(sc);	ia->ia_iosize = 16;	return 1;}intel_probe(sc, ia)	struct ie_softc *sc;	struct isa_attach_args *ia;{	u_char c;	int i;	u_char signature[] = "*3COM*";	sc->sc_iobase = ia->ia_iobase;	/* Need this for part of the probe. */	sc->reset_586 = el_reset_586;	sc->chan_attn = el_chan_attn;	/* Reset and put card in CONFIG state without changing address. */	elink_reset();	elink_idseq(ELINK_507_POLY);	elink_idseq(ELINK_507_POLY);	outb(ELINK_ID_PORT, 0xff);	/* Check for 3COM signature before proceeding. */	outb(PORT + IE507_CTRL, inb(PORT + IE507_CTRL) & 0xfc);	/* XXX */	for (i = 0; i < 6; i++)		if (inb(PORT + i) != signature[i])			return 0;	c = inb(PORT + IE507_MADDR);	if (c & 0x20) {		printf("%s: can't map 3C507 RAM in high memory\n",		    sc->sc_dev.dv_xname);		return 0;	}	/* Go to RUN state. */	outb(ELINK_ID_PORT, 0x00);	elink_idseq(ELINK_507_POLY);	outb(ELINK_ID_PORT, 0x00);	/* Set bank 2 for version info and read BCD version byte. */	outb(PORT + IE507_CTRL, EL_CTRL_NRST | EL_CTRL_BNK2);	i = inb(PORT + 3);	sc->hard_type = IE_3C507;	sc->hard_vers = 10*(i / 16) + (i % 16) - 1;	i = inb(PORT + IE507_IRQ) & 0x0f;	if (ia->ia_irq != IRQUNK) {		if (ia->ia_irq != i) {			printf("%s: irq mismatch; kernel configured %d != board configured %d\n",			    sc->sc_dev.dv_xname, ia->ia_irq, i);			return 0;		}	} else		ia->ia_irq = i;	i = ((inb(PORT + IE507_MADDR) & 0x1c) << 12) + 0xc0000;	if (ia->ia_maddr != MADDRUNK) {		if (ia->ia_maddr != i) {			printf("%s: maddr mismatch; kernel configured %x != board configured %x\n",			    sc->sc_dev.dv_xname, ia->ia_maddr, i);			return 0;		}	} else		ia->ia_maddr = i;	outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);	/*	 * Divine memory size on-board the card.	 */	sc->sc_maddr = ISA_HOLE_VADDR(ia->ia_maddr);	ie_find_mem_size(sc);	if (!sc->sc_msize) {		printf("%s: can't find shared memory\n", sc->sc_dev.dv_xname);		outb(PORT + IE507_CTRL, EL_CTRL_NRST);		return 0;	}	if (!ia->ia_msize)		ia->ia_msize = sc->sc_msize;	else if (ia->ia_msize != sc->sc_msize) {		printf("%s: msize mismatch; kernel configured %d != board configured %d\n",		    sc->sc_dev.dv_xname, ia->ia_msize, sc->sc_msize);		outb(PORT + IE507_CTRL, EL_CTRL_NRST);		return 0;	}	slel_get_address(sc);	/* Clear the interrupt latch just in case. */	outb(PORT + IE507_ICTRL, 1);	ia->ia_iosize = 16;	return 1;}/* Taken almost exactly from Rod's if_ix.c. */intee16_probe(sc, ia)	struct ie_softc *sc;	struct isa_attach_args *ia;{	int i;	int cnt_id;	u_short board_id, id_var1, id_var2, checksum = 0;	u_short eaddrtemp, irq;        u_short pg, adjust, decode, edecode;        u_char lock_bit;	u_char c;	u_char	bart_config;	short	irq_translate[] = {0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0};	/* Need this for part of the probe. */	sc->reset_586 = ee16_reset_586;	sc->chan_attn = ee16_chan_attn;	/* reset any ee16 at the current iobase */	outb(ia->ia_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);	outb(ia->ia_iobase + IEE16_ECTRL, 0);	delay(240);	/* now look for ee16. */	board_id = id_var1 = id_var2 = 0;	for (i=0; i<4 ; i++) {		id_var1 = inb(ia->ia_iobase + IEE16_ID_PORT);		id_var2 = ((id_var1 & 0x03) << 2);		board_id |= (( id_var1 >> 4)  << id_var2);		}	if (board_id != IEE16_ID)		return 0;			/* need sc->sc_iobase for ee16_read_eeprom */	sc->sc_iobase = ia->ia_iobase;	sc->hard_type = IE_EE16;	/*	 * If ia->maddr == MADDRUNK, use value in eeprom location 6.	 *	 * The shared RAM location on the EE16 is encoded into bits	 * 3-7 of EEPROM location 6.  We zero the upper byte, and 	 * shift the 5 bits right 3.  The resulting number tells us	 * the RAM location.  Because the EE16 supports either 16k or 32k	 * of shared RAM, we only worry about the 32k locations. 	 *	 * NOTE: if a 64k EE16 exists, it should be added to this switch.	 *       then the ia->ia_msize would need to be set per case statement.	 *	 *	value	msize	location	 *	=====	=====	========	 *	0x03	0x8000	0xCC000	 *	0x06	0x8000	0xD0000	 *	0x0C	0x8000	0xD4000	 *	0x18	0x8000	0xD8000	 *	 */ 	if ((ia->ia_maddr == MADDRUNK) || (ia->ia_msize == 0)) {		i = (ee16_read_eeprom(sc, 6) & 0x00ff ) >> 3;		switch(i) {			case 0x03:				ia->ia_maddr = 0xCC000;				break;			case 0x06:				ia->ia_maddr = 0xD0000;				break;			case 0x0c:				ia->ia_maddr = 0xD4000;				break;			case 0x18:				ia->ia_maddr = 0xD8000;				break;			default:				return 0 ;				break; /* NOTREACHED */		}		ia->ia_msize = 0x8000; 	}	/* need to set these after checking for MADDRUNK */	sc->sc_maddr = ISA_HOLE_VADDR(ia->ia_maddr);	sc->sc_msize = ia->ia_msize; 	/* need to put the 586 in RESET, and leave it */	outb( PORT + IEE16_ECTRL, IEE16_RESET_586);  	/* read the eeprom and checksum it, should == IEE16_ID */	for(i=0 ; i< 0x40 ; i++)		checksum += ee16_read_eeprom(sc, i);	if (checksum != IEE16_ID)		return 0;		/*	 * Size and test the memory on the board.  The size of the memory	 * can be one of 16k, 32k, 48k or 64k.  It can be located in the	 * address range 0xC0000 to 0xEFFFF on 16k boundaries. 	 *	 * If the size does not match the passed in memory allocation size	 * issue a warning, but continue with the minimum of the two sizes.	 */	switch (ia->ia_msize) {		case 65536:		case 32768: /* XXX Only support 32k and 64k right now */			break;		case 16384:		case 49512:		default:			printf("ieprobe mapped memory size out of range\n");			return 0;			break; /* NOTREACHED */	}	if ((kvtop(sc->sc_maddr) < 0xC0000) ||	    (kvtop(sc->sc_maddr) + sc->sc_msize > 0xF0000)) {		printf("ieprobe mapped memory address out of range\n");		return 0;	}	pg = (kvtop(sc->sc_maddr) & 0x3C000) >> 14;	adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;	decode = ((1 << (sc->sc_msize / 16384)) - 1) << pg;	edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);	/* ZZZ This should be checked against eeprom location 6, low byte */	outb(PORT + IEE16_MEMDEC, decode & 0xFF);	/* ZZZ This should be checked against eeprom location 1, low byte */	outb(PORT + IEE16_MCTRL, adjust);	/* ZZZ Now if I could find this one I would have it made */	outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));	/* ZZZ I think this is location 6, high byte */	outb(PORT + IEE16_MECTRL, edecode); /*XXX disable Exxx */	/*	 * first prime the stupid bart DRAM controller so that it	 * works, then zero out all of memory.	 */	bzero(sc->sc_maddr, 32);	bzero(sc->sc_maddr, sc->sc_msize);	/*	 * Get the encoded interrupt number from the EEPROM, check it	 * against the passed in IRQ.  Issue a warning if they do not	 * match, and fail the probe.  If irq is 'IRQUNK' then we	 * use the EEPROM irq, and continue.	 */	irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);	irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;	sc->irq_encoded = irq;	irq = irq_translate[irq];	if (ia->ia_irq != IRQUNK) {		if (irq != ia->ia_irq) {#ifdef DIAGNOSTIC			printf("\nie%d: fatal: board IRQ %d does not match kernel\n", sc->sc_dev.dv_unit, irq);#endif /* DIAGNOSTIC */			return 0; 	/* _must_ match or probe fails */		}	} else		ia->ia_irq = irq;	/*	 * Get the hardware ethernet address from the EEPROM and	 * save it in the softc for use by the 586 setup code.	 */	eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);	sc->sc_arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;	sc->sc_arpcom.ac_enaddr[0] = eaddrtemp >> 8;	eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);	sc->sc_arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;	sc->sc_arpcom.ac_enaddr[2] = eaddrtemp >> 8;	eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);	sc->sc_arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;	sc->sc_arpcom.ac_enaddr[4] = eaddrtemp >> 8;	/* disable the board interrupts */	outb(PORT + IEE16_IRQ, sc->irq_encoded);	/* enable loopback to keep bad packets off the wire */	if(sc->hard_type == IE_EE16) {		bart_config = inb(PORT + IEE16_CONFIG);		bart_config |= IEE16_BART_LOOPBACK;		bart_config |= IEE16_BART_MCS16_TEST; /* inb doesn't get bit! */		outb(PORT + IEE16_CONFIG, bart_config);		bart_config = inb(PORT + IEE16_CONFIG);	}	outb(PORT + IEE16_ECTRL, 0);	delay(100);	if (!check_ie_present(sc, sc->sc_maddr, sc->sc_msize))		return 0;	ia->ia_iosize = 16;	/* the number of I/O ports */	return 1;		/* found */}/* * Taken almost exactly from Bill's if_is.c, then modified beyond recognition. */voidieattach(parent, self, aux)	struct device *parent, *self;	void *aux;{	struct ie_softc *sc = (void *)self;	struct isa_attach_args *ia = aux;	struct ifnet *ifp = &sc->sc_arpcom.ac_if;	ifp->if_unit = sc->sc_dev.dv_unit;	ifp->if_name = iecd.cd_name;	ifp->if_start = iestart;	ifp->if_ioctl = ieioctl;	ifp->if_watchdog = iewatchdog;	ifp->if_flags =	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;	/* Attach the interface. */	if_attach(ifp);	ether_ifattach(ifp);	printf(": address %s, type %s R%d\n",	    ether_sprintf(sc->sc_arpcom.ac_enaddr),	    ie_hardware_names[sc->hard_type], sc->hard_vers + 1);#if NBPFILTER > 0	bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,	    sizeof(struct ether_header));#endif	sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_NET, ieintr,	    sc);}/* * Device timeout/watchdog routine.  Entered if the device neglects to generate * an interrupt after a transmit has been started on it. */voidiewatchdog(unit)	int unit;{	struct ie_softc *sc = iecd.cd_devs[unit];	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);	++sc->sc_arpcom.ac_if.if_oerrors;	iereset(sc);}/* * What to do upon receipt of an interrupt. */intieintr(arg)	void *arg;{	struct ie_softc *sc = arg;	register u_short status;	/* Clear the interrupt latch on the 3C507. */	if (sc->hard_type == IE_3C507)		outb(PORT + IE507_ICTRL, 1);	/* disable interrupts on the EE16. */	if (sc->hard_type == IE_EE16)		outb(PORT + IEE16_IRQ, sc->irq_encoded);	status = sc->scb->ie_status & IE_ST_WHENCE;	if (status == 0)		return 0;loop:	/* Ack interrupts FIRST in case we receive more during the ISR. */	ie_ack(sc, status);	if (status & (IE_ST_FR | IE_ST_RNR)) {#ifdef IEDEBUG		in_ierint++;		if (sc->sc_debug & IED_RINT)			printf("%s: rint\n", sc->sc_dev.dv_xname);#endif		ierint(sc);#ifdef IEDEBUG		in_ierint--;#endif	}	if (status & IE_ST_CX) {#ifdef IEDEBUG		in_ietint++;		if (sc->sc_debug & IED_TINT)			printf("%s: tint\n", sc->sc_dev.dv_xname);#endif		ietint(sc);#ifdef IEDEBUG		in_ietint--;#endif	}	if (status & IE_ST_RNR) {		printf("%s: receiver not ready\n", sc->sc_dev.dv_xname);		sc->sc_arpcom.ac_if.if_ierrors++;		iereset(sc);	}#ifdef IEDEBUG	if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA))		printf("%s: cna\n", sc->sc_dev.dv_xname);#endif	/* Clear the interrupt latch on the 3C507. */	if (sc->hard_type == IE_3C507)		outb(PORT + IE507_ICTRL, 1);	status = sc->scb->ie_status & IE_ST_WHENCE;	if (status == 0) {		/* enable interrupts on the EE16. */		if (sc->hard_type == IE_EE16)		    outb(PORT + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);		return 1;	}	goto loop;}/* * Process a received-frame interrupt. */voidierint(sc)	struct ie_softc *sc;{	volatile struct ie_sys_ctl_block *scb = sc->scb;	int i, status;	static int timesthru = 1024;	i = sc->rfhead;	for (;;) {		status = sc->rframes[i]->ie_fd_status;		if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {			if (!--timesthru) {				sc->sc_arpcom.ac_if.if_ierrors +=				    scb->ie_err_crc + scb->ie_err_align +				    scb->ie_err_resource + scb->ie_err_overrun;				scb->ie_err_crc = scb->ie_err_align =				    scb->ie_err_resource = scb->ie_err_overrun =				    0;				timesthru = 1024;			}			ie_readframe(sc, i);		} else {			if ((status & IE_FD_RNR) != 0 &&			    (scb->ie_status & IE_RU_READY) == 0) {				sc->rframes[0]->ie_fd_buf_desc =						MK_16(MEM, sc->rbuffs[0]);				scb->ie_recv_list = MK_16(MEM, sc->rframes[0]);				command_and_wait(sc, IE_RU_START, 0, 0);			}			break;		}		i = (i + 1) % NFRAMES;	}}/* * Process a command-complete interrupt.  These are only generated by the * transmission of frames.  This routine is deceptively simple, since most of * the real work is done by iestart(). */voidietint(sc)	struct ie_softc *sc;{	struct ifnet *ifp = &sc->sc_arpcom.ac_if;	int status;	ifp->if_timer = 0;	ifp->if_flags &= ~IFF_OACTIVE;	status = sc->xmit_cmds[sc->xctail]->ie_xmit_status;	if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY))		printf("ietint: command still busy!\n");	if (status & IE_STAT_OK) {		ifp->if_opackets++;		ifp->if_collisions += status & IE_XS_MAXCOLL;	} else {		ifp->if_oerrors++;		/*		 * XXX		 * Check SQE and DEFERRED?		 * What if more than one bit is set?		 */		if (status & IE_STAT_ABORT)			printf("%s: send aborted\n", sc->sc_dev.dv_xname);		else if (status & IE_XS_LATECOLL)			printf("%s: late collision\n", sc->sc_dev.dv_xname);		else if (status & IE_XS_NOCARRIER)			printf("%s: no carrier\n", sc->sc_dev.dv_xname);		else if (status & IE_XS_LOSTCTS)			printf("%s: lost CTS\n", sc->sc_dev.dv_xname);		else if (status & IE_XS_UNDERRUN)			printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);		else if (status & IE_XS_EXCMAX) {			printf("%s: too many collisions\n", sc->sc_dev.dv_xname);			ifp->if_collisions += 16;		}	}	/*	 * If multicast addresses were added or deleted while transmitting,	 * mc_reset() set the want_mcsetup flag indicating that we should do	 * it.	 */	if (sc->want_mcsetup) {		mc_setup(sc, (caddr_t)sc->xmit_cbuffs[sc->xctail]);		sc->want_mcsetup = 0;	}	/* Done with the buffer. */	sc->xmit_busy--;	sc->xctail = (sc->xctail + 1) % NTXBUF;	/* Start the next packet, if any, transmitting. */	if (sc->xmit_busy > 0)		iexmit(sc);	iestart(ifp);}/* * Compare two Ether/802 addresses for equality, inlined and unrolled for * speed.  I'd love to have an inline assembler version of this... */static inline intether_equal(one, two)	u_char *one, *two;{	if (one[0] != two[0] || one[1] != two[1] || one[2] != two[2] ||	    one[3] != two[3] || one[4] != two[4] || one[5] != two[5])		return 0;	return 1;}/* * Check for a valid address.  to_bpf is filled in with one of the following: *   0 -> BPF doesn't get this packet *   1 -> BPF does get this packet *   2 -> BPF does get this packet, but we don't * Return value is true if the packet is for us, and false otherwise. * * This routine is a mess, but it's also critical that it be as fast * as possible.  It could be made cleaner if we can assume that the * only client which will fiddle with IFF_PROMISC is BPF.  This is * probably a good assumption, but we do not make it here.  (Yet.) */static inline intcheck_eh(sc, eh, to_bpf)	struct ie_softc *sc;	struct ether_header *eh;	int *to_bpf;{	int i;	switch (sc->promisc) {	case IFF_ALLMULTI:		/*		 * Receiving all multicasts, but no unicasts except those		 * destined for us.		 */#if NBPFILTER > 0		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0); /* BPF gets this packet if anybody cares */#endif		if (eh->ether_dhost[0] & 1)			return 1;		if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))			return 1;		return 0;	case IFF_PROMISC:		/*		 * Receiving all packets.  These need to be passed on to BPF.		 */#if NBPFILTER > 0		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);#endif		/* If for us, accept and hand up to BPF */		if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))			return 1;#if NBPFILTER > 0		if (*to_bpf)			*to_bpf = 2; /* we don't need to see it */#endif		/*		 * Not a multicast, so BPF wants to see it but we don't.		 */		if (!(eh->ether_dhost[0] & 1))			return 1;		/*		 * If it's one of our multicast groups, accept it and pass it		 * up.		 */		for (i = 0; i < sc->mcast_count; i++) {			if (ether_equal(eh->ether_dhost, (u_char *)&sc->mcast_addrs[i])) {#if NBPFILTER > 0				if (*to_bpf)					*to_bpf = 1;#endif				return 1;			}		}		return 1;	case IFF_ALLMULTI | IFF_PROMISC:		/*		 * Acting as a multicast router, and BPF running at the same		 * time.  Whew!  (Hope this is a fast machine...)		 */#if NBPFILTER > 0		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);#endif		/* We want to see multicasts. */		if (eh->ether_dhost[0] & 1)			return 1;		/* We want to see our own packets */		if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))			return 1;		/* Anything else goes to BPF but nothing else. */#if NBPFILTER > 0		if (*to_bpf)			*to_bpf = 2;#endif		return 1;	case 0:		/*		 * Only accept unicast packets destined for us, or multicasts		 * for groups that we belong to.  For now, we assume that the		 * '586 will only return packets that we asked it for.  This		 * isn't strictly true (it uses hashing for the multicast		 * filter), but it will do in this case, and we want to get out		 * of here as quickly as possible.		 */#if NBPFILTER > 0		*to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);#endif		return 1;	}#ifdef DIAGNOSTIC	panic("check_eh: impossible");#endif}/* * We want to isolate the bits that have meaning...  This assumes that * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds * the size of the buffer, then we are screwed anyway. */static inline intie_buflen(sc, head)	struct ie_softc *sc;	int head;{	return (sc->rbuffs[head]->ie_rbd_actual	    & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));}static inline intie_packet_len(sc)	struct ie_softc *sc;{	int i;	int head = sc->rbhead;	int acc = 0;	do {		if (!(sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED))			return -1;		i = sc->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;		acc += ie_buflen(sc, head);		head = (head + 1) % NRXBUF;	} while (!i);	return acc;}/* * Setup all necessary artifacts for an XMIT command, and then pass the XMIT * command to the chip to be executed.  On the way, if we have a BPF listener * also give him a copy. */voidiexmit(sc)	struct ie_softc *sc;{#ifdef IEDEBUG	if (sc->sc_debug & IED_XMIT)		printf("%s: xmit buffer %d\n", sc->sc_dev.dv_xname,		    sc->xctail);#endif#if NBPFILTER > 0	/*	 * If BPF is listening on this interface, let it see the packet before	 * we push it on the wire.	 */	if (sc->sc_arpcom.ac_if.if_bpf)		bpf_tap(sc->sc_arpcom.ac_if.if_bpf,		    sc->xmit_cbuffs[sc->xctail],		    sc->xmit_buffs[sc->xctail]->ie_xmit_flags);#endif	sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST;	sc->xmit_buffs[sc->xctail]->ie_xmit_next = 0xffff;	sc->xmit_buffs[sc->xctail]->ie_xmit_buf =	    MK_24(MEM, sc->xmit_cbuffs[sc->xctail]);	sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = 0xffff;	sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd =	    IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;	sc->xmit_cmds[sc->xctail]->ie_xmit_status = 0;	sc->xmit_cmds[sc->xctail]->ie_xmit_desc =	    MK_16(MEM, sc->xmit_buffs[sc->xctail]);	sc->scb->ie_command_list = MK_16(MEM, sc->xmit_cmds[sc->xctail]);	command_and_wait(sc, IE_CU_START, 0, 0);	sc->sc_arpcom.ac_if.if_timer = 5;}/* * Read data off the interface, and turn it into an mbuf chain. * * This code is DRAMATICALLY different from the previous version; this version * tries to allocate the entire mbuf chain up front, given the length of the * data available.  This enables us to allocate mbuf clusters in many * situations where before we would have had a long chain of partially-full * mbufs.  This should help to speed up the operation considerably.  (Provided * that it works, of course.) */struct mbuf *ieget(sc, ehp, to_bpf)	struct ie_softc *sc;	struct ether_header *ehp;	int *to_bpf;{	struct mbuf *top, **mp, *m;	int len, totlen, resid;	int thisrboff, thismboff;	int head;	totlen = ie_packet_len(sc);	if (totlen <= 0)		return 0;	head = sc->rbhead;	/*	 * Snarf the Ethernet header.	 */	bcopy((caddr_t)sc->cbuffs[head], (caddr_t)ehp, sizeof *ehp);	/*	 * As quickly as possible, check if this packet is for us.	 * If not, don't waste a single cycle copying the rest of the	 * packet in.	 * This is only a consideration when FILTER is defined; i.e., when	 * we are either running BPF or doing multicasting.	 */	if (!check_eh(sc, ehp, to_bpf)) {		sc->sc_arpcom.ac_if.if_ierrors--; /* just this case, it's not an error */		return 0;	}	resid = totlen -= (thisrboff = sizeof *ehp);	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == 0)		return 0;	m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;	m->m_pkthdr.len = totlen;	len = MHLEN;	top = 0;	mp = &top;	/*	 * This loop goes through and allocates mbufs for all the data we will	 * be copying in.  It does not actually do the copying yet.	 */	while (totlen > 0) {		if (top) {			MGET(m, M_DONTWAIT, MT_DATA);			if (m == 0) {				m_freem(top);				return 0;			}			len = MLEN;		}		if (totlen >= MINCLSIZE) {			MCLGET(m, M_DONTWAIT);			if (m->m_flags & M_EXT)				len = MCLBYTES;		}		m->m_len = len = min(totlen, len);		totlen -= len;		*mp = m;		mp = &m->m_next;	}	m = top;	thismboff = 0;	/*	 * Now we take the mbuf chain (hopefully only one mbuf most of the	 * time) and stuff the data into it.  There are no possible failures at	 * or after this point.	 */	while (resid > 0) {		int thisrblen = ie_buflen(sc, head) - thisrboff,		    thismblen = m->m_len - thismboff;		len = min(thisrblen, thismblen);		bcopy((caddr_t)(sc->cbuffs[head] + thisrboff),		    mtod(m, caddr_t) + thismboff, (u_int)len);		resid -= len;		if (len == thismblen) {			m = m->m_next;			thismboff = 0;		} else			thismboff += len;		if (len == thisrblen) {			head = (head + 1) % NRXBUF;			thisrboff = 0;		} else			thisrboff += len;	}	/*	 * Unless something changed strangely while we were doing the copy, we	 * have now copied everything in from the shared memory.	 * This means that we are done.	 */	return top;}