Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / acorn32 / podulebus / if_ie.c
blob74526ae80e89ef1b8a6aebfd0047521f825e40ea
1 /* $NetBSD: if_ie.c,v 1.26 2009/05/12 06:54:10 cegger Exp $ */
3 /*
4 * Copyright (c) 1995 Melvin Tang-Richardson.
5 * All rights reserved.
7 * This driver is a major hash up of src/sys/dev/isa/if_ie.c and
8 * src/sys/arch/acorn32/podulebus/kgdb_ie.c Please refer to copyright
9 * notices from them too.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by RiscBSD.
22 * 4. The name of the company nor the name of the author may be used to
23 * endorse or promote products derived from this software without specific
24 * prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
38 * RiscBSD kernel project
40 * if_ie.c
42 * Ether 1 podule driver
44 * Created : 26/06/95
48 * This driver is at it's last beta release. It should not cause
49 * any problems (Touch wood)
51 * If it passes field tests again. This will constitute the realse
52 * version.
55 #include <sys/cdefs.h>
56 __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.26 2009/05/12 06:54:10 cegger Exp $");
58 #define IGNORE_ETHER1_IDROM_CHECKSUM
60 /* Standard podule includes */
62 #include "opt_inet.h"
63 #include "opt_ns.h"
65 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/kernel.h>
69 #include <sys/conf.h>
70 #include <sys/malloc.h>
71 #include <sys/device.h>
72 #include <machine/io.h>
73 #include <machine/intr.h>
74 #include <arm/arm32/katelib.h>
75 #include <acorn32/podulebus/podulebus.h>
76 #include <dev/podulebus/podules.h>
78 /* Include for interface to the net and ethernet subsystems */
80 #include <sys/socket.h>
81 #include <sys/syslog.h>
82 #include <sys/ioctl.h>
83 #include <sys/mbuf.h>
85 #include <net/if.h>
86 #include <net/if_types.h>
87 #include <net/if_dl.h>
88 #include <net/if_ether.h>
90 #ifdef INET
91 #include <netinet/in.h>
92 #include <netinet/in_systm.h>
93 #include <netinet/in_var.h>
94 #include <netinet/ip.h>
95 #include <netinet/if_inarp.h>
96 #endif
98 #ifdef NS
99 #include <netns/ns.h>
100 #include <netns/ns_if.h>
101 #endif
103 /* Import our data structres */
105 #include "if_iereg.h"
107 /* BPF support */
109 #include "bpfilter.h"
110 #if NBPFILTER > 0
111 #include <net/bpf.h>
112 #include <net/bpfdesc.h>
113 #endif
115 /* Some useful defines and macros */
117 #define PODULE_IRQ_PENDING (1)
118 #define NFRAMES (16) /* number of frame to allow for receive */
119 #define NRXBUF (48) /* number of receive buffers to allocate */
120 #define IE_RXBUF_SIZE (256) /* receive buf size */
121 #define NTXBUF (2) /* number of transmit buffers to allocate */
122 #define IE_TXBUF_SIZE (1522) /* size of tx buffer */
124 #define PWriteShort(a,b) WriteWord(a,(b)<<16|(b))
126 #define xoffsetof(type, member) (offsetof(type, member) << 1)
128 /* Some data structres local to this file */
130 struct ie_softc {
131 struct device sc_dev;
132 int sc_podule_number;
133 podule_t *sc_podule;
134 irqhandler_t sc_ih;
135 int sc_flags;
136 #define IE_BROKEN 1
137 int sc_iobase;
138 int sc_fastbase;
139 int sc_rom;
140 int sc_ram;
141 int sc_control;
142 struct ethercom sc_ethercom;
143 int promisc;
144 int sc_irqmode;
146 u_long rframes[NFRAMES];
147 u_long rbuffs[NRXBUF];
148 u_long cbuffs[NRXBUF];
149 int rfhead, rftail, rbhead, rbtail;
151 u_long xmit_cmds[NTXBUF];
152 u_long xmit_buffs[NTXBUF];
153 u_long xmit_cbuffs[NTXBUF];
154 int xmit_count;
155 int xmit_free;
156 int xchead;
157 int xctail;
160 /* Function and data prototypes */
162 static void host2ie( struct ie_softc *sc, void *src, u_long dest, int size );
163 static void ie2host( struct ie_softc *sc, u_long src, void *dest, int size );
164 static void iezero( struct ie_softc *sc, u_long p, int size );
165 void iereset( struct ie_softc *sc );
166 void iewatchdog( struct ifnet *ifp );
167 int ieioctl( struct ifnet *ifp, u_long cmd, void *data );
168 void iestart( struct ifnet *ifp );
169 int iestop( struct ie_softc *sc );
170 int ieinit( struct ie_softc *sc );
171 int ieintr( void *arg );
172 void ietint( struct ie_softc *sc );
174 /* A whopper of a function */
175 static int command_and_wait( struct ie_softc *sc, u_short cmd,
176 struct ie_sys_ctl_block *pscb,
177 void *pcmd, int ocmd, int scmd, int mask );
179 int ieprobe(struct device *, struct cfdata *, void *);
180 void ieattach(struct device *, struct device *, void *);
182 static inline void ie_cli(struct ie_softc *);
183 static inline void ieattn(struct ie_softc *);
184 static inline void setpage(struct ie_softc *, u_long);
185 static void ie_ack(struct ie_softc *, u_short);
186 void PWriteShorts(char *, char *, int);
187 void ReadShorts(char *, char *, int);
188 static void run_tdr(struct ie_softc *);
189 u_long setup_rfa(struct ie_softc *, u_long);
190 static inline int ie_buflen(struct ie_softc *, int);
191 static inline int ie_packet_len(struct ie_softc *);
192 struct mbuf *ieget(struct ie_softc *, int *);
193 void ie_drop_packet_buffer(struct ie_softc *);
194 void ie_read_frame(struct ie_softc *, int num);
195 void ierint(struct ie_softc *);
196 void iexmit(struct ie_softc *);
197 static void start_receiver(struct ie_softc *);
201 * Our cfattach structure for the autoconfig system to chew on
204 CFATTACH_DECL(ie, sizeof(struct ie_softc),
205 ieprobe, ieattach, NULL, NULL);
207 /* Let's go! */
210 * Clear all pending interrupts from the i82586 chip
213 static inline void
214 ie_cli(struct ie_softc *sc)
216 WriteByte(sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI);
220 * Wake the i82586 chip up and get it to do something
223 static inline void
224 ieattn(struct ie_softc *sc)
226 WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN );
230 * Set the podule page register to bring a given address into view
233 static inline void
234 setpage(struct ie_softc *sc, u_long off)
236 WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) );
240 * Ack the i82586
243 static void
244 ie_ack(struct ie_softc *sc, u_short mask)
246 u_short stat;
247 int i;
248 setpage(sc, IE_IBASE + IE_SCB_OFF );
250 stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
251 (xoffsetof(struct ie_sys_ctl_block, ie_status)) );
253 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
254 (xoffsetof(struct ie_sys_ctl_block, ie_command)),
255 stat & mask );
257 ieattn(sc);
259 for ( i=4000; --i>=0; ) {
260 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
261 (xoffsetof(struct ie_sys_ctl_block, ie_command))) )
262 break;
263 delay(100);
266 if ( i<=0 )
267 printf ( "ie: command timed out\n" );
268 ie_cli(sc);
272 * This routine does the checksumming for the idrom
275 #ifndef IGNORE_ETHER1_IDROM_CHECKSUM
276 static u_long
277 crc32(u_char *p, int l)
279 u_long crc=-1;
280 int i, b;
281 while ( --l >= 0 ) {
282 b = *p++;
283 for ( i=8; --i >= 0; b>>=1 )
284 if ((b&1)^(crc>>31))
285 crc=(crc<<1)^0x4c11db7;
286 else
287 crc<<=1;
289 return crc;
291 #endif
294 * Probe for the ether1 card. return 1 on success 0 on failure
298 ieprobe(struct device *parent, struct cfdata *cf, void *aux)
300 struct podule_attach_args *pa = (void *)aux;
302 /* Look for a network slot interface */
304 return (pa->pa_product == PODULE_ETHER1);
308 * Attach our driver to the interfaces it uses
311 void ieattach ( struct device *parent, struct device *self, void *aux )
313 struct ie_softc *sc = (void *)self;
314 struct podule_attach_args *pa = (void *)aux;
315 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
316 int i;
317 char idrom[32];
318 u_int8_t hwaddr[ETHER_ADDR_LEN];
320 /* Check a few things about the attach args */
322 if (pa->pa_podule_number == -1)
323 panic("Podule has disappeared !");
325 sc->sc_podule_number = pa->pa_podule_number;
326 sc->sc_podule = pa->pa_podule;
327 podules[sc->sc_podule_number].attached = 1;
330 * MESS MESS MESS
332 * This needs a serious clean up. Alot of this code was in the probe function
333 * but required the softc structure. As a temporary measure until I rewrite it
334 * I have just bolted in the probe code here.
337 /* Index some podule areas */
338 sc->sc_iobase = sc->sc_podule->sync_base; /* OBSOLETE */
339 sc->sc_fastbase = sc->sc_podule->fast_base; /* OBSOLETE */
340 sc->sc_rom = sc->sc_podule->sync_base;
341 sc->sc_control = sc->sc_podule->fast_base;
342 sc->sc_ram = sc->sc_podule->fast_base + IE_MEMOFF;
344 /* Set the page mask to something know and neutral */
345 setpage(sc, IE_SCB_OFF);
347 /* Fetch the first part of the idrom */
348 for ( i=0; i<16; i++ )
349 idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
351 /* Verify the podulebus probe incase RiscOS lied */
352 if ( ReadByte ( sc->sc_rom + (3<<2) ) != 0x03 ) {
353 printf(": Ether1 ROM probablly broken. ECID corrupt\n");
354 sc->sc_flags |= IE_BROKEN;
355 return;
358 /* Reset the 82586 */
359 WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_RESET );
360 delay(1000);
361 WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), 0 );
362 delay(10000);
364 /* Clear pending interrupts */
365 ie_cli (sc);
367 /* Setup SCP */
369 struct ie_sys_conf_ptr scp;
370 bzero (&scp, sizeof(scp) );
371 scp.ie_iscp_ptr = (void *)IE_ISCP_ADDR;
372 host2ie(sc, &scp, IE_SCP_ADDR, sizeof (scp) );
375 /* Setup ISCP */
377 struct ie_int_sys_conf_ptr iscp;
378 bzero ( &iscp, sizeof(iscp) );
379 iscp.ie_busy = 1;
380 iscp.ie_base = (void *)IE_IBASE;
381 iscp.ie_scb_offset = IE_SCB_OFF;
382 host2ie(sc, &iscp, IE_ISCP_ADDR, sizeof(iscp) );
385 /* Initialise the control block */
386 iezero ( sc, IE_IBASE + IE_SCB_OFF, sizeof(struct ie_sys_ctl_block) );
387 ieattn(sc);
389 /* Wait for not busy */
390 setpage ( sc, IE_ISCP_ADDR );
391 for ( i=10000; --i>=0; ) {
392 if ( !ReadShort( sc->sc_ram + IE_COFF2POFF(IE_ISCP_ADDR) +
393 ( xoffsetof(struct ie_int_sys_conf_ptr, ie_busy)) ) )
394 break;
395 delay (10);
398 /* If the busy didn't go low, the i82586 is broken or too slow */
399 if ( i<=0 ) {
400 printf ( ": ether1 chipset didn't respond\n" );
401 sc->sc_flags |= IE_BROKEN;
402 return;
405 /* Ensure that the podule sends interrupts */
406 for ( i=1000; --i>=0 ; ) {
407 if ( ReadByte(sc->sc_rom + 0) & PODULE_IRQ_PENDING )
408 break;
409 delay (10);
412 /* If we didn't see the interrupt then the IRQ line is broken */
413 if ( i<=0 ) {
414 printf ( ": interrupt from chipset didn't reach host\n" );
415 sc->sc_flags |= IE_BROKEN;
416 return;
419 /* Ack our little test operation */
420 ie_ack(sc,IE_ST_WHENCE);
421 ie_cli (sc);
423 /* Get second part of idrom */
424 for ( i=16; i<32; i++ )
425 idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
427 /* This checksum always fails. For some reason the first 16 */
428 /* bytes are duplicated in the second 16 bytes, the checksum */
429 /* should be at location 28 it is clearly not */
431 /* It is possible that this ether1 card is buggered */
433 #ifndef IGNORE_ETHER1_IDROM_CHECKSUM
434 if ( crc32(idrom,28) != *(u_long *)(idrom+28) )
436 printf ( "ie: ether1 idrom failed checksum %08x!=%08x\n",
437 crc32(idrom,28), *(u_long *)(idrom+28));
438 for ( i=0; i<32; i+=8 ) {
439 printf ( "IDROM: %02x %02x %02x %02x %02x %02x %02x %02x\n",
440 idrom[0+i], idrom[1+i], idrom[2+i], idrom[3+i],
441 idrom[4+i], idrom[5+i], idrom[6+i], idrom[7+i] );
443 printf ( "ie: I'll ignore this fact for now!\n" );
445 #endif
447 /* Get our ethernet address. Do explicit copy */
448 for ( i=0; i<ETHER_ADDR_LEN; i++ )
449 hwaddr[i] = idrom[9+i];
451 /* Fill in my application form to attach to the inet system */
453 memcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ);
454 ifp->if_softc = sc;
455 ifp->if_start = iestart;
456 ifp->if_ioctl = ieioctl;
457 ifp->if_watchdog = iewatchdog;
458 ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS;
460 /* Signed, dated then sent */
461 if_attach (ifp);
462 ether_ifattach(ifp, hwaddr);
464 /* "Hmm," said nuts, "what if the attach fails" */
466 /* Write some pretty things on the annoucement line */
467 printf ( ": %s using %dk card ram",
468 ether_sprintf(hwaddr),
469 ((NRXBUF*IE_RXBUF_SIZE)+(NTXBUF*IE_TXBUF_SIZE))/1024 );
471 sc->sc_ih.ih_func = ieintr;
472 sc->sc_ih.ih_arg = sc;
473 sc->sc_ih.ih_level = IPL_NET;
474 sc->sc_ih.ih_name = "net: ie";
475 sc->sc_ih.ih_maskaddr = sc->sc_podule->irq_addr;
476 sc->sc_ih.ih_maskbits = sc->sc_podule->irq_mask;
478 if (irq_claim(sc->sc_podule->interrupt, &sc->sc_ih)) {
479 sc->sc_irqmode = 0;
480 printf(" POLLED");
481 panic("%s: Cannot install IRQ handler", sc->sc_dev.dv_xname);
482 } else {
483 sc->sc_irqmode = 1;
484 printf(" IRQ");
487 printf("\n");
492 * Oh no!! Where's my shorts!!! I'm sure I put them on this morning
495 void
496 PWriteShorts(char *src, char *dest, int cnt)
498 for (cnt /= 2; --cnt >= 0; ) {
499 PWriteShort(dest, *(u_short *)src);
500 src+=2;
501 dest+=4;
505 void
506 ReadShorts(char *src, char *dest, int cnt)
508 for (cnt /= 2; --cnt >= 0; ) {
509 *(u_short *)dest = ReadShort(src);
510 src+=4;
511 dest+=2;
516 * A bcopy or memcpy to adapter ram. It handles the page register for you
517 * so you dont have to worry about the ram windowing
520 static void
521 host2ie(struct ie_softc *sc, void *src, u_long dest, int size)
523 int cnt;
524 char *sptr = src;
526 #ifdef DIAGNOSTIC
527 if (size & 1)
528 panic("host2ie");
529 #endif
531 while (size > 0) {
532 cnt = IE_PAGESIZE - dest % IE_PAGESIZE;
533 if (cnt > size)
534 cnt = size;
535 setpage(sc, dest);
536 PWriteShorts(sptr, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt);
537 sptr+=cnt;
538 dest+=cnt;
539 size-=cnt;
543 static void
544 ie2host(struct ie_softc *sc, u_long src, void *dest, int size)
546 int cnt;
547 char *dptr = dest;
549 #ifdef DIAGNOSTIC
550 if (size & 1)
551 panic ( "ie2host" );
552 #endif
554 while (size > 0) {
555 cnt = IE_PAGESIZE - src % IE_PAGESIZE;
556 if (cnt > size)
557 cnt = size;
558 setpage(sc, src);
559 ReadShorts((char *)sc->sc_ram + IE_COFF2POFF(src), dptr, cnt);
560 src+=cnt;
561 dptr+=cnt;
562 size-=cnt;
567 * Like a bzero or memset 0 for adapter memory. It handles the page
568 * register so you dont have to worry about it
571 static void
572 iezero(struct ie_softc *sc, u_long p, int size)
574 int cnt;
576 while (size > 0) {
577 cnt = IE_PAGESIZE - p % IE_PAGESIZE;
578 if (cnt > size)
579 cnt=size;
580 setpage(sc, p);
581 memset((char *)sc->sc_ram + IE_COFF2POFF(p), 0, 2*cnt);
582 p += cnt;
583 size -= cnt;
588 * I/O Control interface to the kernel, entry point here
592 ieioctl(struct ifnet *ifp, unsigned long cmd, void *data)
594 struct ie_softc *sc = ifp->if_softc;
595 struct ifaddr *ifa = (struct ifaddr *)data;
596 int s;
597 int error=0;
599 s=splnet();
601 switch ( cmd )
603 case SIOCINITIFADDR:
604 ifp->if_flags |= IFF_UP;
605 switch (ifa->ifa_addr->sa_family ) {
606 #ifdef INET
607 case AF_INET:
608 ieinit(sc);
609 arp_ifinit(ifp, ifa );
610 break;
611 #endif
612 default:
613 ieinit(sc);
614 break;
616 break;
618 #define IZSET(a,b) ((a->if_flags&b)!=0)
619 #define IZCLR(a,b) ((a->if_flags&b)==0)
620 #define DOSET(a,b) (a->if_flags|=b)
621 #define DOCLR(a,b) (a->if_flags&=~b)
623 case SIOCSIFFLAGS:
624 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
625 return error;
626 sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI );
628 if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) )
630 /* Interface was marked down and its running so stop it */
631 iestop(sc);
632 DOCLR(ifp,IFF_RUNNING);
634 else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) )
636 /* Just marked up and we're not running so start it */
637 ieinit(sc);
639 else
641 /* else reset to invoke changes in other registers */
642 iestop(sc);
643 ieinit(sc);
646 default:
647 error = ether_ioctl(ifp, cmd, data);
648 break;
650 (void)splx(s);
651 return error;
655 * Reset the card. Completely.
658 void
659 iereset(struct ie_softc *sc)
661 struct ie_sys_ctl_block scb;
662 int s = splnet();
664 iestop(sc);
666 ie2host(sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb);
668 if (command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0))
669 printf("ie0: abort commands timed out\n");
671 if (command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0))
672 printf("ie0: abort commands timed out\n");
674 ieinit(sc);
676 (void)splx(s);
680 * Watchdog entry point. This is the entry for the kernel to call us
683 void
684 iewatchdog(struct ifnet *ifp)
686 struct ie_softc *sc = ifp->if_softc;
688 log(LOG_ERR, "%s: device timeout\n", device_xname(&sc->sc_dev));
689 ++ifp->if_oerrors;
690 iereset(sc);
694 * Start the time-domain-refloctometer running
697 static void
698 run_tdr(struct ie_softc *sc)
700 struct ie_sys_ctl_block scb;
701 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
702 struct ie_tdr_cmd cmd;
703 int result;
705 bzero ( &scb, sizeof(scb) );
706 bzero ( &cmd, sizeof(cmd) );
708 cmd.com.ie_cmd_status = 0;
709 cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
710 cmd.com.ie_cmd_link = 0xffff;
711 cmd.ie_tdr_time = 0;
713 scb.ie_command_list = (u_short)ptr;
715 result=0;
716 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
717 IE_STAT_COMPL) )
719 result = 0x10000;
721 else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
723 result = 0x10000;
726 if ( result==0 )
727 result = cmd.ie_tdr_time;
729 ie_ack ( sc, IE_ST_WHENCE );
731 if (result & IE_TDR_SUCCESS )
732 return;
734 /* Very messy. I'll tidy it later */
736 if ( result & 0x10000 )
738 printf ( "ie: TDR command failed\n" );
740 else if ( result & IE_TDR_XCVR )
742 printf ( "ie: tranceiver problem. Is it plugged in?\n" );
744 else if ( result & IE_TDR_OPEN )
746 if ((result & IE_TDR_TIME)>0)
747 printf ( "ie: TDR detected an open %d clocks away.\n",
748 result & IE_TDR_TIME );
750 else if ( result & IE_TDR_SHORT )
752 if ((result & IE_TDR_TIME)>0)
753 printf ( "ie: TDR detected a short %d clock away.\n",
754 result & IE_TDR_TIME );
756 else
758 printf ( "ie: TDR returned unknown status %x\n", result );
762 u_long
763 setup_rfa(struct ie_softc *sc, u_long ptr)
765 int i;
767 /* Receive frame descriptors */
768 struct ie_recv_frame_desc rfd;
769 memset( &rfd, 0, sizeof rfd );
770 for ( i=0; i<NFRAMES; i++ )
772 sc->rframes[i] = ptr;
773 rfd.ie_fd_next = ptr + sizeof rfd;
774 host2ie(sc, (char *)&rfd, ptr, sizeof rfd);
775 ptr += sizeof rfd;
777 rfd.ie_fd_next = sc->rframes[0];
778 rfd.ie_fd_last |= IE_FD_LAST;
779 host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd );
781 ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd );
782 rfd.ie_fd_buf_desc = (u_short) ptr;
783 host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd );
787 /* Receive frame descriptors */
788 struct ie_recv_buf_desc rbd;
789 memset(&rbd, 0, sizeof rbd);
790 for ( i=0; i<NRXBUF; i++ )
792 sc->rbuffs[i] = ptr;
793 rbd.ie_rbd_length = IE_RXBUF_SIZE;
794 rbd.ie_rbd_buffer = (void *)(ptr + sizeof rbd);
795 rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE);
796 host2ie(sc, &rbd, ptr, sizeof rbd);
797 ptr+=sizeof rbd;
799 sc->cbuffs[i] = ptr;
800 ptr+=IE_RXBUF_SIZE;
802 rbd.ie_rbd_next = sc->rbuffs[0];
803 rbd.ie_rbd_length |= IE_RBD_LAST;
804 host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd);
807 sc->rfhead = 0;
808 sc->rftail = NFRAMES-1;
809 sc->rbhead = 0;
810 sc->rbtail = NRXBUF-1;
813 struct ie_sys_ctl_block scb;
814 bzero ( &scb, sizeof scb );
815 scb.ie_recv_list = (u_short)sc->rframes[0];
816 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
818 return ptr;
821 static void
822 start_receiver(struct ie_softc *sc)
824 struct ie_sys_ctl_block scb;
825 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
826 scb.ie_recv_list = (u_short)sc->rframes[0];
827 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
828 ie_ack(sc, IE_ST_WHENCE );
832 * Take our configuration and update all the other data structures that
833 * require information from the driver.
835 * CALL AT SPLIMP OR HIGHER
839 ieinit(struct ie_softc *sc)
841 struct ifnet *ifp;
842 struct ie_sys_ctl_block scb;
843 struct ie_config_cmd cmd;
844 struct ie_iasetup_cmd iasetup_cmd;
845 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
846 int n;
848 ifp = &sc->sc_ethercom.ec_if;
850 bzero ( &scb, sizeof(scb) );
852 /* Send the configure command */
854 cmd.com.ie_cmd_status = 0;
855 cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
856 cmd.com.ie_cmd_link = 0xffff;
858 cmd.ie_config_count = 0x0c;
859 cmd.ie_fifo = 8;
860 cmd.ie_save_bad = 0x40;
861 cmd.ie_addr_len = 0x2e;
862 cmd.ie_priority = 0;
863 cmd.ie_ifs = 0x60;
864 cmd.ie_slot_low = 0;
865 cmd.ie_slot_high = 0xf2;
866 cmd.ie_promisc = 0; /* Hey nuts, look at this! */
867 cmd.ie_crs_cdt = 0;
868 cmd.ie_min_len = 64;
869 cmd.ie_junk = 0xff;
871 scb.ie_command_list = (u_short)ptr;
873 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
874 IE_STAT_COMPL) )
876 printf ( "%s: command failed: timeout\n", device_xname(&sc->sc_dev));
877 return 0;
880 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
882 printf ( "%s: command failed: !IE_STAT_OK\n", device_xname(&sc->sc_dev));
883 return 0;
886 /* Individual address setup command */
888 iasetup_cmd.com.ie_cmd_status = 0;
889 iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
890 iasetup_cmd.com.ie_cmd_link = 0xffff;
892 bcopy ( CLLADDR(ifp->if_sadl), (void *) &iasetup_cmd.ie_address,
893 sizeof (iasetup_cmd.ie_address) );
895 if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd,
896 IE_STAT_COMPL) )
898 printf ( "%s: iasetup failed : timeout\n", device_xname(&sc->sc_dev));
899 return 0;
902 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
904 printf ( "%s: iasetup failed : !IE_STAT_OK\n", device_xname(&sc->sc_dev));
905 return 0;
908 ie_ack ( sc, IE_ST_WHENCE );
910 /* Run the time-domain refloctometer */
911 run_tdr ( sc );
913 ie_ack ( sc, IE_ST_WHENCE );
915 /* meminit */
916 ptr = setup_rfa(sc, ptr);
918 ifp->if_flags |= IFF_RUNNING;
919 ifp->if_flags &= ~IFF_OACTIVE;
921 /* Setup transmit buffers */
923 for ( n=0; n<NTXBUF; n++ ) {
924 sc->xmit_cmds[n] = ptr;
925 iezero(sc, ptr, sizeof(struct ie_xmit_cmd) );
926 ptr += sizeof(struct ie_xmit_cmd);
928 sc->xmit_buffs[n] = ptr;
929 iezero(sc, ptr, sizeof(struct ie_xmit_buf));
930 ptr += sizeof(struct ie_xmit_buf);
933 for ( n=0; n<NTXBUF; n++ ) {
934 sc->xmit_cbuffs[n] = ptr;
935 ptr += IE_TXBUF_SIZE;
938 sc->xmit_free = NTXBUF;
939 sc->xchead = sc->xctail = 0;
942 struct ie_xmit_cmd xmcmd;
943 bzero ( &xmcmd, sizeof xmcmd );
944 xmcmd.ie_xmit_status = IE_STAT_COMPL;
945 host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd);
948 start_receiver (sc);
950 return 0;
954 iestop(struct ie_softc *sc)
956 struct ie_sys_ctl_block scb;
957 int s = splnet();
959 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
961 if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) )
962 printf ( "ie0: abort commands timed out\n" );
964 (void)splx(s);
965 return(0);
969 * Send a command to the card and awaits it's completion.
970 * Timeout if it's taking too long
973 /*CAW*/
975 static int
976 command_and_wait(struct ie_softc *sc, u_short cmd, struct ie_sys_ctl_block *pscb, void *pcmd, int ocmd, int scmd, int mask)
978 int i=0;
980 /* Copy the command to the card */
982 if ( pcmd )
983 host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */
985 /* Copy the scb to the card */
987 if ( pscb ) {
988 pscb->ie_command = cmd;
989 host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb);
991 else
993 setpage ( sc, IE_IBASE + IE_SCB_OFF );
994 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
995 (xoffsetof(struct ie_sys_ctl_block, ie_command)), cmd );
998 /* Prod the card to act on the newly loaded command */
999 ieattn(sc);
1001 /* Wait for the command to complete */
1002 if ( IE_ACTION_COMMAND(cmd) && pcmd )
1004 setpage(sc,ocmd);
1005 for ( i=4000; --i>=0; ) {
1006 if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) +
1007 (xoffsetof(struct ie_config_cmd, ie_config_status))) & mask)
1008 break;
1009 delay(100);
1012 else
1014 for ( i=4000; --i>=0; ) {
1015 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
1016 (xoffsetof(struct ie_sys_ctl_block, ie_command))) )
1017 break;
1018 delay(100);
1022 /* Update the host structures to reflect the state on the card */
1023 if ( pscb )
1024 ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb );
1025 if ( pcmd )
1026 ie2host(sc, ocmd, pcmd, scmd);
1028 return i < 0;
1031 #define READ_MEMBER(sc,type,member,ptr,dest) \
1032 setpage(sc, ptr); \
1033 dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) + \
1034 (xoffsetof(type, member)) );
1036 #define WRITE_MEMBER(sc,type,member,ptr,dest) \
1037 setpage(sc, ptr); \
1038 PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) + \
1039 (xoffsetof(type, member)), dest );
1041 static inline int
1042 ie_buflen(struct ie_softc *sc, int head)
1044 int actual;
1046 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1047 sc->rbuffs[head], actual );
1049 return(actual & (IE_RXBUF_SIZE | (IE_RXBUF_SIZE-1))) ;
1052 static inline int
1053 ie_packet_len(struct ie_softc *sc)
1055 int i;
1056 int actual;
1057 int head = sc->rbhead;
1058 int acc=0;
1060 do {
1061 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1062 sc->rbuffs[sc->rbhead], actual );
1063 if (!(actual&IE_RBD_USED))
1065 return (-1);
1068 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1069 sc->rbuffs[head], i );
1070 i = i & IE_RBD_LAST;
1072 acc += ie_buflen(sc, head);
1073 head = (head+1) % NRXBUF;
1074 } while (!i);
1076 return acc;
1079 struct mbuf *
1080 ieget(struct ie_softc *sc, int *to_bpf )
1082 struct mbuf *top, **mp, *m;
1083 int head;
1084 int resid, totlen, thisrboff, thismboff;
1085 int len;
1086 struct ether_header eh;
1088 totlen = ie_packet_len(sc);
1090 if ( totlen > ETHER_MAX_LEN )
1092 printf ( "ie: Gosh that packet was s-o-o-o big.\n" );
1093 return 0;
1096 if ( totlen<=0 )
1097 return 0;
1099 head = sc->rbhead;
1101 /* Read the ethernet header */
1102 ie2host ( sc, sc->cbuffs[head], (void *)&eh, sizeof eh );
1104 /* Check if the packet is for us */
1106 resid = totlen;
1108 MGETHDR ( m, M_DONTWAIT, MT_DATA );
1109 if ( m==0 )
1110 return 0;
1112 m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if;
1113 m->m_pkthdr.len = totlen;
1114 len = MHLEN;
1115 top = 0;
1116 mp = &top;
1119 * This loop goes through and allocates mbufs for all the data we will
1120 * be copying in. It does not actually do the copying yet.
1122 while (totlen > 0) {
1123 if (top) {
1124 MGET(m, M_DONTWAIT, MT_DATA);
1125 if (m == 0) {
1126 m_freem(top);
1127 return 0;
1129 len = MLEN;
1131 if (totlen >= MINCLSIZE) {
1132 MCLGET(m, M_DONTWAIT);
1133 if (m->m_flags & M_EXT)
1134 len = MCLBYTES;
1137 if (mp == &top) {
1138 void *newdata = (void *)
1139 ALIGN(m->m_data + sizeof(struct ether_header)) -
1140 sizeof(struct ether_header);
1141 len -= newdata - m->m_data;
1142 m->m_data = newdata;
1145 m->m_len = len = min(totlen, len);
1147 totlen -= len;
1148 *mp = m;
1149 mp = &m->m_next;
1152 m = top;
1153 thismboff = 0;
1156 * Copy the Ethernet header into the mbuf chain.
1158 memcpy(mtod(m, void *), &eh, sizeof(struct ether_header));
1159 thismboff = sizeof(struct ether_header);
1160 thisrboff = sizeof(struct ether_header);
1161 resid -= sizeof(struct ether_header);
1164 * Now we take the mbuf chain (hopefully only one mbuf most of the
1165 * time) and stuff the data into it. There are no possible failures at
1166 * or after this point.
1168 while (resid > 0) {
1169 int thisrblen = ie_buflen(sc, head) - thisrboff,
1170 thismblen = m->m_len - thismboff;
1171 len = min(thisrblen, thismblen);
1173 /* bcopy((void *)(sc->cbuffs[head] + thisrboff),
1174 mtod(m, void *) + thismboff, (u_int)len); */
1177 if ( len&1 )
1179 ie2host(sc, sc->cbuffs[head]+thisrboff,
1180 mtod(m, void *) + thismboff, (u_int)len+1);
1182 else
1184 ie2host(sc, sc->cbuffs[head]+thisrboff,
1185 mtod(m, void *) + thismboff, (u_int)len);
1188 resid -= len;
1190 if (len == thismblen) {
1191 m = m->m_next;
1192 thismboff = 0;
1193 } else
1194 thismboff += len;
1196 if (len == thisrblen) {
1197 head = (head + 1) % NRXBUF;
1198 thisrboff = 0;
1199 } else
1200 thisrboff += len;
1204 return top;
1207 void
1208 ie_drop_packet_buffer(struct ie_softc *sc)
1210 int i, actual, last;
1212 do {
1213 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1214 sc->rbuffs[sc->rbhead], actual );
1215 if (!(actual&IE_RBD_USED))
1217 iereset(sc);
1218 return;
1221 i = actual & IE_RBD_LAST;
1223 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1224 sc->rbuffs[sc->rbhead], last );
1225 last |= IE_RBD_LAST;
1226 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1227 sc->rbuffs[sc->rbhead], last );
1229 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual,
1230 sc->rbuffs[sc->rbhead], 0 );
1232 sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF;
1234 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1235 sc->rbuffs[sc->rbtail], last );
1236 last &= ~IE_RBD_LAST;
1237 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1238 sc->rbuffs[sc->rbtail], last );
1240 sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF;
1241 } while (!i);
1244 void
1245 ie_read_frame(struct ie_softc *sc, int num)
1247 int status;
1248 struct ie_recv_frame_desc rfd;
1249 struct mbuf *m=0;
1250 struct ifnet *ifp;
1251 int last;
1253 ifp = &sc->sc_ethercom.ec_if;
1255 ie2host(sc, sc->rframes[num], &rfd, sizeof rfd );
1256 status = rfd.ie_fd_status;
1258 /* Advance the RFD list, since we're done with this descriptor */
1260 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
1261 sc->rframes[num], 0 );
1263 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1264 sc->rframes[num], last );
1265 last |= IE_FD_LAST;
1266 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1267 sc->rframes[num], last );
1269 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1270 sc->rframes[sc->rftail], last );
1271 last &= ~IE_FD_LAST;
1272 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1273 sc->rframes[sc->rftail], last );
1275 sc->rftail = ( sc->rftail + 1 ) % NFRAMES;
1276 sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES;
1278 if ( status & IE_FD_OK ) {
1279 m = ieget(sc, 0);
1280 ie_drop_packet_buffer(sc);
1283 if ( m==0 ) {
1284 ifp->if_ierrors++;
1285 return;
1288 ifp->if_ipackets++;
1290 #if NBPFILTER > 0
1291 if ( ifp->if_bpf ) {
1292 bpf_mtap(ifp->if_bpf, m );
1294 #endif
1296 (*ifp->if_input)(ifp, m);
1299 void
1300 ierint(struct ie_softc *sc)
1302 int i;
1303 int times_thru = 1024;
1304 struct ie_sys_ctl_block scb;
1305 int status;
1306 int safety_catch = 0;
1308 i = sc->rfhead;
1309 for (;;) {
1311 if ( (safety_catch++)>100 )
1313 printf ( "ie: ierint safety catch tripped\n" );
1314 iereset(sc);
1315 return;
1318 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
1319 sc->rframes[i],status);
1321 if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) {
1322 if ( !--times_thru ) {
1323 printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" );
1324 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
1325 sc->sc_ethercom.ec_if.if_ierrors += scb.ie_err_crc +
1326 scb.ie_err_align +
1327 scb.ie_err_resource +
1328 scb.ie_err_overrun;
1329 scb.ie_err_crc = scb.ie_err_align = 0;
1330 scb.ie_err_resource = scb.ie_err_overrun = 0;
1331 host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) );
1333 ie_read_frame(sc, i);
1334 } else {
1335 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
1337 if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) )
1339 WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc,
1340 sc->rframes[0], sc->rbuffs[0] );
1342 scb.ie_recv_list = sc->rframes[0];
1343 host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) );
1344 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
1346 break;
1348 i = (i + 1) % NFRAMES;
1352 static int in_intr = 0;
1355 ieintr(void *arg)
1357 struct ie_softc *sc = arg;
1358 u_short status;
1359 int safety_catch = 0;
1360 static int safety_net = 0;
1362 if (in_intr == 1)
1363 panic ( "ie: INTERRUPT REENTERED\n" );
1365 /* Clear the interrrupt */
1366 ie_cli (sc);
1368 setpage(sc, IE_IBASE + IE_SCB_OFF );
1369 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
1370 (xoffsetof(struct ie_sys_ctl_block, ie_status)) );
1372 status = status & IE_ST_WHENCE;
1374 if (status == 0) {
1375 in_intr = 0;
1376 return(0);
1379 loop:
1381 ie_ack(sc, status);
1383 if (status & (IE_ST_FR | IE_ST_RNR))
1384 ierint(sc);
1386 if (status & IE_ST_CX)
1387 ietint(sc);
1389 if (status & IE_ST_RNR) {
1390 printf ( "ie: receiver not ready\n" );
1391 sc->sc_ethercom.ec_if.if_ierrors++;
1392 iereset(sc);
1395 setpage(sc, IE_IBASE + IE_SCB_OFF );
1396 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
1397 (xoffsetof(struct ie_sys_ctl_block, ie_status)) );
1398 status = status & IE_ST_WHENCE;
1400 ie_cli(sc);
1402 if (status == 0) {
1403 in_intr = 0;
1404 return(0);
1407 /* This is prehaps a little over cautious */
1408 if ( safety_catch++ > 10 )
1410 printf ( "ie: Interrupt couldn't be cleared\n" );
1411 delay ( 1000 );
1412 ie_cli(sc);
1413 if ( safety_net++ > 50 )
1415 /* printf ( "ie: safety net catches driver, shutting down\n" );
1416 disable_irq ( IRQ_PODULE );*/
1418 in_intr = 0;
1419 return(0);
1422 goto loop;
1425 void
1426 iexmit(struct ie_softc *sc)
1428 /* int actual;*/
1429 struct ie_sys_ctl_block scb;
1431 struct ie_xmit_cmd xc;
1432 struct ie_xmit_buf xb;
1434 ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb );
1435 xb.ie_xmit_flags |= IE_XMIT_LAST;
1436 xb.ie_xmit_next = 0xffff;
1437 xb.ie_xmit_buf = (void *)sc->xmit_cbuffs[sc->xctail];
1438 host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb );
1440 bzero ( &xc, sizeof xc );
1441 xc.com.ie_cmd_link = 0xffff;
1442 xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
1443 xc.ie_xmit_status = 0x0000;
1444 xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail];
1445 host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc );
1447 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
1448 scb.ie_command_list = sc->xmit_cmds[sc->xctail];
1449 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
1451 command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail]
1452 , sizeof xc, IE_STAT_COMPL);
1454 sc->sc_ethercom.ec_if.if_timer = 5;
1457 * Start sending all the queued buffers.
1460 void
1461 iestart(struct ifnet *ifp)
1463 struct ie_softc *sc = ifp->if_softc;
1464 struct mbuf *m0, *m;
1465 u_char *buffer;
1466 u_short len;
1467 char txbuf[IE_TXBUF_SIZE];
1468 int safety_catch = 0;
1470 if ((ifp->if_flags & IFF_OACTIVE) != 0)
1471 return;
1473 for (;;) {
1474 if ( (safety_catch++)>100 )
1476 printf ( "ie: iestart safety catch tripped\n" );
1477 iereset(sc);
1478 return;
1480 if (sc->xmit_free == 0) {
1481 ifp->if_flags |= IFF_OACTIVE;
1482 break;
1485 IF_DEQUEUE(&ifp->if_snd, m);
1486 if (!m)
1487 break;
1489 /* TODO: Write directly to the card */
1490 len = 0;
1491 /* buffer = sc->xmit_cbuffs[sc->xchead]; */
1492 buffer = txbuf;
1494 for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE;
1495 m = m->m_next) {
1496 memcpy(buffer, mtod(m, void *), m->m_len);
1497 buffer += m->m_len;
1498 len += m->m_len;
1501 #if NBPFILTER > 0
1502 if ( ifp->if_bpf )
1503 bpf_mtap(ifp->if_bpf, m0);
1504 #endif
1506 m_freem(m0);
1507 if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
1508 memset(buffer, 0, ETHER_MIN_LEN - ETHER_CRC_LEN - len);
1509 len = ETHER_MIN_LEN - ETHER_CRC_LEN;
1510 buffer += ETHER_MIN_LEN - ETHER_CRC_LEN;
1513 /* When we write directly to the card we dont need this */
1514 if (len&1)
1515 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 );
1516 else
1517 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len );
1519 /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */
1521 WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags,
1522 sc->xmit_buffs[sc->xchead], len)
1524 /* Start the first packet transmitting. */
1525 if (sc->xmit_free == NTXBUF)
1526 iexmit(sc);
1528 sc->xchead = (sc->xchead + 1) % NTXBUF;
1529 sc->xmit_free--;
1533 void
1534 ietint(struct ie_softc *sc)
1536 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1538 int status;
1540 ifp->if_timer=0;
1541 ifp->if_flags &= ~IFF_OACTIVE;
1543 READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status,
1544 sc->xmit_cmds[sc->xctail], status );
1546 if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) )
1547 printf ( "ietint: command still busy!\n" );
1549 if ( status & IE_STAT_OK ) {
1550 ifp->if_opackets++;
1551 ifp->if_collisions += status & IE_XS_MAXCOLL;
1552 } else {
1553 ifp->if_oerrors++;
1554 if ( status & IE_STAT_ABORT )
1555 printf ( "ie: send aborted\n" );
1556 if ( status & IE_XS_LATECOLL )
1557 printf ( "ie: late collision\n" );
1558 if ( status & IE_XS_NOCARRIER )
1559 printf ( "ie: no carrier\n" );
1560 if ( status & IE_XS_LOSTCTS )
1561 printf ( "ie: lost CTS\n" );
1562 if ( status & IE_XS_UNDERRUN )
1563 printf ( "ie: DMA underrun\n" );
1564 if ( status & IE_XS_EXCMAX )
1565 printf ( "ie: too many collisions\n" );
1566 ifp->if_collisions+=16;
1568 /* Done with the buffer */
1569 sc->xmit_free++;
1570 sc->xctail = (sc->xctail + 1 ) % NTXBUF;
1572 /* Start the next packet transmitting, if any */
1573 if ( sc->xmit_free<NTXBUF )
1574 iexmit(sc);
1576 iestart(ifp);
1579 /* End of if_ie.c */