1 /* $NetBSD: if_ie.c,v 1.53 2022/09/17 18:58:49 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1995 Melvin Tang-Richardson.
5 * All rights reserved.
6 *
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.
10 *
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.
25 *
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.
37 *
38 * RiscBSD kernel project
39 *
40 * if_ie.c
41 *
42 * Ether 1 podule driver
43 *
44 * Created : 26/06/95
45 */
46
47 /*
48 * This driver is at its last beta release. It should not cause
49 * any problems (Touch wood)
50 *
51 * If it passes field tests again. This will constitute the realse
52 * version.
53 */
54
55 #include <sys/cdefs.h>
56 __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.53 2022/09/17 18:58:49 thorpej Exp $");
57
58 #define IGNORE_ETHER1_IDROM_CHECKSUM
59
60 /* Standard podule includes */
61
62 #include "opt_inet.h"
63 #include "opt_ns.h"
64
65 #include <sys/param.h>
66
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 <acorn32/podulebus/podulebus.h>
75 #include <dev/podulebus/podules.h>
76
77 /* Include for interface to the net and ethernet subsystems */
78
79 #include <sys/socket.h>
80 #include <sys/syslog.h>
81 #include <sys/ioctl.h>
82 #include <sys/mbuf.h>
83
84 #include <net/if.h>
85 #include <net/if_types.h>
86 #include <net/if_dl.h>
87 #include <net/if_ether.h>
88
89 #ifdef INET
90 #include <netinet/in.h>
91 #include <netinet/in_systm.h>
92 #include <netinet/in_var.h>
93 #include <netinet/ip.h>
94 #include <netinet/if_inarp.h>
95 #endif
96
97 /* Import our data structures */
98
99 #include "if_iereg.h"
100
101 /* BPF support */
102
103 #include <net/bpf.h>
104
105 /* Some useful defines and macros */
106
107 #define PODULE_IRQ_PENDING (1)
108 #define NFRAMES (16) /* number of frame to allow for receive */
109 #define NRXBUF (48) /* number of receive buffers to allocate */
110 #define IE_RXBUF_SIZE (256) /* receive buf size */
111 #define NTXBUF (2) /* number of transmit buffers to allocate */
112 #define IE_TXBUF_SIZE (1522) /* size of tx buffer */
113
114 #define PWriteShort(a,b) WriteWord(a,(b)<<16|(b))
115
116 #define xoffsetof(type, member) (offsetof(type, member) << 1)
117
118 /* Some data structures local to this file */
119
120 struct ie_softc {
121 device_t sc_dev;
122 int sc_podule_number;
123 podule_t *sc_podule;
124 irqhandler_t sc_ih;
125 int sc_flags;
126 #define IE_BROKEN 1
127 int sc_iobase;
128 int sc_fastbase;
129 int sc_rom;
130 int sc_ram;
131 int sc_control;
132 struct ethercom sc_ethercom;
133 u_short promisc;
134 int sc_irqmode;
135
136 u_long rframes[NFRAMES];
137 u_long rbuffs[NRXBUF];
138 u_long cbuffs[NRXBUF];
139 int rfhead, rftail, rbhead, rbtail;
140
141 u_long xmit_cmds[NTXBUF];
142 u_long xmit_buffs[NTXBUF];
143 u_long xmit_cbuffs[NTXBUF];
144 int xmit_count;
145 int xmit_free;
146 int xchead;
147 int xctail;
148 };
149
150 /* Function and data prototypes */
151
152 static void host2ie( struct ie_softc *sc, void *src, u_long dest, int size );
153 static void ie2host( struct ie_softc *sc, u_long src, void *dest, int size );
154 static void iezero( struct ie_softc *sc, u_long p, int size );
155 void iereset( struct ie_softc *sc );
156 void iewatchdog( struct ifnet *ifp );
157 int ieioctl( struct ifnet *ifp, u_long cmd, void *data );
158 void iestart( struct ifnet *ifp );
159 int iestop( struct ie_softc *sc );
160 int ieinit( struct ie_softc *sc );
161 int ieintr( void *arg );
162 void ietint( struct ie_softc *sc );
163
164 /* A whopper of a function */
165 static int command_and_wait( struct ie_softc *sc, u_short cmd,
166 struct ie_sys_ctl_block *pscb,
167 void *pcmd, int ocmd, int scmd, int mask );
168
169 int ieprobe(device_t, cfdata_t, void *);
170 void ieattach(device_t, device_t, void *);
171
172 static inline void ie_cli(struct ie_softc *);
173 static inline void ieattn(struct ie_softc *);
174 static inline void setpage(struct ie_softc *, u_long);
175 static void ie_ack(struct ie_softc *, u_short);
176 void PWriteShorts(char *, char *, int);
177 void ReadShorts(char *, char *, int);
178 static void run_tdr(struct ie_softc *);
179 u_long setup_rfa(struct ie_softc *, u_long);
180 static inline int ie_buflen(struct ie_softc *, int);
181 static inline int ie_packet_len(struct ie_softc *);
182 struct mbuf *ieget(struct ie_softc *, int *);
183 void ie_drop_packet_buffer(struct ie_softc *);
184 void ie_read_frame(struct ie_softc *, int num);
185 void ierint(struct ie_softc *);
186 void iexmit(struct ie_softc *);
187 static void start_receiver(struct ie_softc *);
188
189
190 /*
191 * Our cfattach structure for the autoconfig system to chew on
192 */
193
194 CFATTACH_DECL_NEW(ie, sizeof(struct ie_softc),
195 ieprobe, ieattach, NULL, NULL);
196
197 /* Let's go! */
198
199 /*
200 * Clear all pending interrupts from the i82586 chip
201 */
202
203 static inline void
ie_cli(struct ie_softc * sc)204 ie_cli(struct ie_softc *sc)
205 {
206 WriteByte(sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI);
207 }
208
209 /*
210 * Wake the i82586 chip up and get it to do something
211 */
212
213 static inline void
ieattn(struct ie_softc * sc)214 ieattn(struct ie_softc *sc)
215 {
216 WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN );
217 }
218
219 /*
220 * Set the podule page register to bring a given address into view
221 */
222
223 static inline void
setpage(struct ie_softc * sc,u_long off)224 setpage(struct ie_softc *sc, u_long off)
225 {
226 WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) );
227 }
228
229 /*
230 * Ack the i82586
231 */
232
233 static void
ie_ack(struct ie_softc * sc,u_short mask)234 ie_ack(struct ie_softc *sc, u_short mask)
235 {
236 u_short stat;
237 int i;
238 setpage(sc, IE_IBASE + IE_SCB_OFF );
239
240 stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
241 (xoffsetof(struct ie_sys_ctl_block, ie_status)) );
242
243 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
244 (xoffsetof(struct ie_sys_ctl_block, ie_command)),
245 stat & mask );
246
247 ieattn(sc);
248
249 for ( i=4000; --i>=0; ) {
250 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
251 (xoffsetof(struct ie_sys_ctl_block, ie_command))) )
252 break;
253 delay(100);
254 }
255
256 if ( i<=0 )
257 printf ( "ie: command timed out\n" );
258 ie_cli(sc);
259 }
260
261 /*
262 * This routine does the checksumming for the idrom
263 */
264
265 #ifndef IGNORE_ETHER1_IDROM_CHECKSUM
266 static u_long
crc32(u_char * p,int l)267 crc32(u_char *p, int l)
268 {
269 u_long crc=-1;
270 int i, b;
271 while ( --l >= 0 ) {
272 b = *p++;
273 for ( i=8; --i >= 0; b>>=1 )
274 if ((b&1)^(crc>>31))
275 crc=(crc<<1)^0x4c11db7;
276 else
277 crc<<=1;
278 }
279 return crc;
280 }
281 #endif
282
283 /*
284 * Probe for the ether1 card. return 1 on success 0 on failure
285 */
286
287 int
ieprobe(device_t parent,cfdata_t cf,void * aux)288 ieprobe(device_t parent, cfdata_t cf, void *aux)
289 {
290 struct podule_attach_args *pa = aux;
291
292 /* Look for a network slot interface */
293
294 return (pa->pa_product == PODULE_ETHER1);
295 }
296
297 /*
298 * Attach our driver to the interfaces it uses
299 */
300
301 void
ieattach(device_t parent,device_t self,void * aux)302 ieattach(device_t parent, device_t self, void *aux)
303 {
304 struct ie_softc *sc = device_private(self);
305 struct podule_attach_args *pa = aux;
306 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
307 int i;
308 char idrom[32];
309 uint8_t hwaddr[ETHER_ADDR_LEN];
310
311 /* Check a few things about the attach args */
312
313 if (pa->pa_podule_number == -1)
314 panic("Podule has disappeared !");
315
316 sc->sc_dev = self;
317 sc->sc_podule_number = pa->pa_podule_number;
318 sc->sc_podule = pa->pa_podule;
319 podules[sc->sc_podule_number].attached = 1;
320
321 /*
322 * MESS MESS MESS
323 *
324 * This needs a serious clean up. Alot of this code was in the probe function
325 * but required the softc structure. As a temporary measure until I rewrite it
326 * I have just bolted in the probe code here.
327 */
328
329 /* Index some podule areas */
330 sc->sc_iobase = sc->sc_podule->sync_base; /* OBSOLETE */
331 sc->sc_fastbase = sc->sc_podule->fast_base; /* OBSOLETE */
332 sc->sc_rom = sc->sc_podule->sync_base;
333 sc->sc_control = sc->sc_podule->fast_base;
334 sc->sc_ram = sc->sc_podule->fast_base + IE_MEMOFF;
335
336 /* Set the page mask to something know and neutral */
337 setpage(sc, IE_SCB_OFF);
338
339 /* Fetch the first part of the idrom */
340 for ( i=0; i<16; i++ )
341 idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
342
343 /* Verify the podulebus probe incase RiscOS lied */
344 if ( ReadByte ( sc->sc_rom + (3<<2) ) != 0x03 ) {
345 printf(": Ether1 ROM probably broken. ECID corrupt\n");
346 sc->sc_flags |= IE_BROKEN;
347 return;
348 }
349
350 /* Reset the 82586 */
351 WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_RESET );
352 delay(1000);
353 WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), 0 );
354 delay(10000);
355
356 /* Clear pending interrupts */
357 ie_cli (sc);
358
359 /* Setup SCP */
360 {
361 struct ie_sys_conf_ptr scp;
362 bzero (&scp, sizeof(scp) );
363 scp.ie_iscp_ptr = (void *)IE_ISCP_ADDR;
364 host2ie(sc, &scp, IE_SCP_ADDR, sizeof (scp) );
365 }
366
367 /* Setup ISCP */
368 {
369 struct ie_int_sys_conf_ptr iscp;
370 bzero ( &iscp, sizeof(iscp) );
371 iscp.ie_busy = 1;
372 iscp.ie_base = (void *)IE_IBASE;
373 iscp.ie_scb_offset = IE_SCB_OFF;
374 host2ie(sc, &iscp, IE_ISCP_ADDR, sizeof(iscp) );
375 }
376
377 /* Initialise the control block */
378 iezero ( sc, IE_IBASE + IE_SCB_OFF, sizeof(struct ie_sys_ctl_block) );
379 ieattn(sc);
380
381 /* Wait for not busy */
382 setpage ( sc, IE_ISCP_ADDR );
383 for ( i=10000; --i>=0; ) {
384 if ( !ReadShort( sc->sc_ram + IE_COFF2POFF(IE_ISCP_ADDR) +
385 ( xoffsetof(struct ie_int_sys_conf_ptr, ie_busy)) ) )
386 break;
387 delay (10);
388 }
389
390 /* If the busy didn't go low, the i82586 is broken or too slow */
391 if ( i<=0 ) {
392 printf ( ": ether1 chipset didn't respond\n" );
393 sc->sc_flags |= IE_BROKEN;
394 return;
395 }
396
397 /* Ensure that the podule sends interrupts */
398 for ( i=1000; --i>=0 ; ) {
399 if ( ReadByte(sc->sc_rom + 0) & PODULE_IRQ_PENDING )
400 break;
401 delay (10);
402 }
403
404 /* If we didn't see the interrupt then the IRQ line is broken */
405 if ( i<=0 ) {
406 printf ( ": interrupt from chipset didn't reach host\n" );
407 sc->sc_flags |= IE_BROKEN;
408 return;
409 }
410
411 /* Ack our little test operation */
412 ie_ack(sc,IE_ST_WHENCE);
413 ie_cli (sc);
414
415 /* Get second part of idrom */
416 for ( i=16; i<32; i++ )
417 idrom[i] = ReadByte ( sc->sc_rom + (i<<2) );
418
419 /* This checksum always fails. For some reason the first 16 */
420 /* bytes are duplicated in the second 16 bytes, the checksum */
421 /* should be at location 28 it is clearly not */
422
423 /* It is possible that this ether1 card is buggered */
424
425 #ifndef IGNORE_ETHER1_IDROM_CHECKSUM
426 if ( crc32(idrom,28) != *(u_long *)(idrom+28) )
427 {
428 printf ( "ie: ether1 idrom failed checksum %08x!=%08x\n",
429 crc32(idrom,28), *(u_long *)(idrom+28));
430 for ( i=0; i<32; i+=8 ) {
431 printf ( "IDROM: %02x %02x %02x %02x %02x %02x %02x %02x\n",
432 idrom[0+i], idrom[1+i], idrom[2+i], idrom[3+i],
433 idrom[4+i], idrom[5+i], idrom[6+i], idrom[7+i] );
434 }
435 printf ( "ie: I'll ignore this fact for now!\n" );
436 }
437 #endif
438
439 /* Get our ethernet address. Do explicit copy */
440 for ( i=0; i<ETHER_ADDR_LEN; i++ )
441 hwaddr[i] = idrom[9+i];
442
443 /* Fill in my application form to attach to the inet system */
444
445 memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
446 ifp->if_softc = sc;
447 ifp->if_start = iestart;
448 ifp->if_ioctl = ieioctl;
449 ifp->if_watchdog = iewatchdog;
450 ifp->if_flags = IFF_BROADCAST;
451
452 /* Signed, dated then sent */
453 if_attach (ifp);
454 if_deferred_start_init(ifp, NULL);
455 ether_ifattach(ifp, hwaddr);
456
457 /* "Hmm," said nuts, "what if the attach fails" */
458
459 /* Write some pretty things on the announcement line */
460 printf ( ": %s using %dk card ram",
461 ether_sprintf(hwaddr),
462 ((NRXBUF*IE_RXBUF_SIZE)+(NTXBUF*IE_TXBUF_SIZE))/1024 );
463
464 sc->sc_ih.ih_func = ieintr;
465 sc->sc_ih.ih_arg = sc;
466 sc->sc_ih.ih_level = IPL_NET;
467 sc->sc_ih.ih_name = "net: ie";
468 sc->sc_ih.ih_maskaddr = sc->sc_podule->irq_addr;
469 sc->sc_ih.ih_maskbits = sc->sc_podule->irq_mask;
470
471 if (irq_claim(sc->sc_podule->interrupt, &sc->sc_ih)) {
472 sc->sc_irqmode = 0;
473 printf(" POLLED");
474 panic("%s: Cannot install IRQ handler", device_xname(sc->sc_dev));
475 } else {
476 sc->sc_irqmode = 1;
477 printf(" IRQ");
478 }
479
480 printf("\n");
481 }
482
483
484 /*
485 * Oh no!! Where's my shorts!!! I'm sure I put them on this morning
486 */
487
488 void
PWriteShorts(char * src,char * dest,int cnt)489 PWriteShorts(char *src, char *dest, int cnt)
490 {
491 for (cnt /= 2; --cnt >= 0; ) {
492 PWriteShort(dest, *(u_short *)src);
493 src+=2;
494 dest+=4;
495 }
496 }
497
498 void
ReadShorts(char * src,char * dest,int cnt)499 ReadShorts(char *src, char *dest, int cnt)
500 {
501 for (cnt /= 2; --cnt >= 0; ) {
502 *(u_short *)dest = ReadShort(src);
503 src+=4;
504 dest+=2;
505 }
506 }
507
508 /*
509 * A bcopy or memcpy to adapter ram. It handles the page register for you
510 * so you dont have to worry about the ram windowing
511 */
512
513 static void
host2ie(struct ie_softc * sc,void * src,u_long dest,int size)514 host2ie(struct ie_softc *sc, void *src, u_long dest, int size)
515 {
516 int cnt;
517 char *sptr = src;
518
519 #ifdef DIAGNOSTIC
520 if (size & 1)
521 panic("host2ie");
522 #endif
523
524 while (size > 0) {
525 cnt = IE_PAGESIZE - dest % IE_PAGESIZE;
526 if (cnt > size)
527 cnt = size;
528 setpage(sc, dest);
529 PWriteShorts(sptr, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt);
530 sptr+=cnt;
531 dest+=cnt;
532 size-=cnt;
533 }
534 }
535
536 static void
ie2host(struct ie_softc * sc,u_long src,void * dest,int size)537 ie2host(struct ie_softc *sc, u_long src, void *dest, int size)
538 {
539 int cnt;
540 char *dptr = dest;
541
542 #ifdef DIAGNOSTIC
543 if (size & 1)
544 panic ( "ie2host" );
545 #endif
546
547 while (size > 0) {
548 cnt = IE_PAGESIZE - src % IE_PAGESIZE;
549 if (cnt > size)
550 cnt = size;
551 setpage(sc, src);
552 ReadShorts((char *)sc->sc_ram + IE_COFF2POFF(src), dptr, cnt);
553 src+=cnt;
554 dptr+=cnt;
555 size-=cnt;
556 }
557 }
558
559 /*
560 * Like a bzero or memset 0 for adapter memory. It handles the page
561 * register so you dont have to worry about it
562 */
563
564 static void
iezero(struct ie_softc * sc,u_long p,int size)565 iezero(struct ie_softc *sc, u_long p, int size)
566 {
567 int cnt;
568
569 while (size > 0) {
570 cnt = IE_PAGESIZE - p % IE_PAGESIZE;
571 if (cnt > size)
572 cnt=size;
573 setpage(sc, p);
574 memset((char *)sc->sc_ram + IE_COFF2POFF(p), 0, 2*cnt);
575 p += cnt;
576 size -= cnt;
577 }
578 }
579
580 /*
581 * I/O Control interface to the kernel, entry point here
582 */
583
584 int
ieioctl(struct ifnet * ifp,unsigned long cmd,void * data)585 ieioctl(struct ifnet *ifp, unsigned long cmd, void *data)
586 {
587 struct ie_softc *sc = ifp->if_softc;
588 struct ifaddr *ifa = (struct ifaddr *)data;
589 int s;
590 int error=0;
591
592 s=splnet();
593
594 switch ( cmd )
595 {
596 case SIOCINITIFADDR:
597 ifp->if_flags |= IFF_UP;
598 switch (ifa->ifa_addr->sa_family ) {
599 #ifdef INET
600 case AF_INET:
601 ieinit(sc);
602 arp_ifinit(ifp, ifa );
603 break;
604 #endif
605 default:
606 ieinit(sc);
607 break;
608 }
609 break;
610
611 #define IZSET(a,b) ((a->if_flags&b)!=0)
612 #define IZCLR(a,b) ((a->if_flags&b)==0)
613 #define DOSET(a,b) (a->if_flags|=b)
614 #define DOCLR(a,b) (a->if_flags&=~b)
615
616 case SIOCSIFFLAGS:
617 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
618 break;
619 sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI );
620
621 if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) )
622 {
623 /* Interface was marked down and its running so stop it */
624 iestop(sc);
625 DOCLR(ifp,IFF_RUNNING);
626 }
627 else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) )
628 {
629 /* Just marked up and we're not running so start it */
630 ieinit(sc);
631 }
632 else
633 {
634 /* else reset to invoke changes in other registers */
635 iestop(sc);
636 ieinit(sc);
637 }
638
639 default:
640 error = ether_ioctl(ifp, cmd, data);
641 break;
642 }
643 (void)splx(s);
644 return error;
645 }
646
647 /*
648 * Reset the card. Completely.
649 */
650
651 void
iereset(struct ie_softc * sc)652 iereset(struct ie_softc *sc)
653 {
654 struct ie_sys_ctl_block scb;
655 int s = splnet();
656
657 iestop(sc);
658
659 ie2host(sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb);
660
661 if (command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0))
662 printf("ie0: abort commands timed out\n");
663
664 if (command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0))
665 printf("ie0: abort commands timed out\n");
666
667 ieinit(sc);
668
669 (void)splx(s);
670 }
671
672 /*
673 * Watchdog entry point. This is the entry for the kernel to call us
674 */
675
676 void
iewatchdog(struct ifnet * ifp)677 iewatchdog(struct ifnet *ifp)
678 {
679 struct ie_softc *sc = ifp->if_softc;
680
681 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev));
682 if_statinc(ifp, if_oerrors);
683 iereset(sc);
684 }
685
686 /*
687 * Start the time-domain-refloctometer running
688 */
689
690 static void
run_tdr(struct ie_softc * sc)691 run_tdr(struct ie_softc *sc)
692 {
693 struct ie_sys_ctl_block scb;
694 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
695 struct ie_tdr_cmd cmd;
696 int result;
697
698 bzero ( &scb, sizeof(scb) );
699 bzero ( &cmd, sizeof(cmd) );
700
701 cmd.com.ie_cmd_status = 0;
702 cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
703 cmd.com.ie_cmd_link = 0xffff;
704 cmd.ie_tdr_time = 0;
705
706 scb.ie_command_list = (u_short)ptr;
707
708 result=0;
709 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
710 IE_STAT_COMPL) )
711 {
712 result = 0x10000;
713 }
714 else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
715 {
716 result = 0x10000;
717 }
718
719 if ( result==0 )
720 result = cmd.ie_tdr_time;
721
722 ie_ack ( sc, IE_ST_WHENCE );
723
724 if (result & IE_TDR_SUCCESS )
725 return;
726
727 /* Very messy. I'll tidy it later */
728
729 if ( result & 0x10000 )
730 {
731 printf ( "ie: TDR command failed\n" );
732 }
733 else if ( result & IE_TDR_XCVR )
734 {
735 printf ( "ie: tranceiver problem. Is it plugged in?\n" );
736 }
737 else if ( result & IE_TDR_OPEN )
738 {
739 if ((result & IE_TDR_TIME)>0)
740 printf ( "ie: TDR detected an open %d clocks away.\n",
741 result & IE_TDR_TIME );
742 }
743 else if ( result & IE_TDR_SHORT )
744 {
745 if ((result & IE_TDR_TIME)>0)
746 printf ( "ie: TDR detected a short %d clock away.\n",
747 result & IE_TDR_TIME );
748 }
749 else
750 {
751 printf ( "ie: TDR returned unknown status %x\n", result );
752 }
753 }
754
755 u_long
setup_rfa(struct ie_softc * sc,u_long ptr)756 setup_rfa(struct ie_softc *sc, u_long ptr)
757 {
758 int i;
759 {
760 /* Receive frame descriptors */
761 struct ie_recv_frame_desc rfd;
762 memset( &rfd, 0, sizeof rfd );
763 for ( i=0; i<NFRAMES; i++ )
764 {
765 sc->rframes[i] = ptr;
766 rfd.ie_fd_next = ptr + sizeof rfd;
767 host2ie(sc, (char *)&rfd, ptr, sizeof rfd);
768 ptr += sizeof rfd;
769 }
770 rfd.ie_fd_next = sc->rframes[0];
771 rfd.ie_fd_last |= IE_FD_LAST;
772 host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd );
773
774 ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd );
775 rfd.ie_fd_buf_desc = (u_short) ptr;
776 host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd );
777 }
778
779 {
780 /* Receive frame descriptors */
781 struct ie_recv_buf_desc rbd;
782 memset(&rbd, 0, sizeof rbd);
783 for ( i=0; i<NRXBUF; i++ )
784 {
785 sc->rbuffs[i] = ptr;
786 rbd.ie_rbd_length = IE_RXBUF_SIZE;
787 rbd.ie_rbd_buffer = (void *)(ptr + sizeof rbd);
788 rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE);
789 host2ie(sc, &rbd, ptr, sizeof rbd);
790 ptr+=sizeof rbd;
791
792 sc->cbuffs[i] = ptr;
793 ptr+=IE_RXBUF_SIZE;
794 }
795 rbd.ie_rbd_next = sc->rbuffs[0];
796 rbd.ie_rbd_length |= IE_RBD_LAST;
797 host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd);
798 }
799
800 sc->rfhead = 0;
801 sc->rftail = NFRAMES-1;
802 sc->rbhead = 0;
803 sc->rbtail = NRXBUF-1;
804
805 {
806 struct ie_sys_ctl_block scb;
807 bzero ( &scb, sizeof scb );
808 scb.ie_recv_list = (u_short)sc->rframes[0];
809 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
810 }
811 return ptr;
812 }
813
814 static void
start_receiver(struct ie_softc * sc)815 start_receiver(struct ie_softc *sc)
816 {
817 struct ie_sys_ctl_block scb;
818 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
819 scb.ie_recv_list = (u_short)sc->rframes[0];
820 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
821 ie_ack(sc, IE_ST_WHENCE );
822 }
823
824 /*
825 * Take our configuration and update all the other data structures that
826 * require information from the driver.
827 *
828 * CALL AT SPLIMP OR HIGHER
829 */
830
831 int
ieinit(struct ie_softc * sc)832 ieinit(struct ie_softc *sc)
833 {
834 struct ifnet *ifp;
835 struct ie_sys_ctl_block scb;
836 struct ie_config_cmd cmd;
837 struct ie_iasetup_cmd iasetup_cmd;
838 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb;
839 int n;
840
841 ifp = &sc->sc_ethercom.ec_if;
842
843 bzero ( &scb, sizeof(scb) );
844
845 /* Send the configure command */
846
847 cmd.com.ie_cmd_status = 0;
848 cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
849 cmd.com.ie_cmd_link = 0xffff;
850
851 cmd.ie_config_count = 0x0c;
852 cmd.ie_fifo = 8;
853 cmd.ie_save_bad = 0x40;
854 cmd.ie_addr_len = 0x2e;
855 cmd.ie_priority = 0;
856 cmd.ie_ifs = 0x60;
857 cmd.ie_slot_low = 0;
858 cmd.ie_slot_high = 0xf2;
859 cmd.ie_promisc = 0; /* Hey nuts, look at this! */
860 cmd.ie_crs_cdt = 0;
861 cmd.ie_min_len = 64;
862 cmd.ie_junk = 0xff;
863
864 scb.ie_command_list = (u_short)ptr;
865
866 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd,
867 IE_STAT_COMPL) )
868 {
869 printf ( "%s: command failed: timeout\n", device_xname(sc->sc_dev));
870 return 0;
871 }
872
873 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
874 {
875 printf ( "%s: command failed: !IE_STAT_OK\n", device_xname(sc->sc_dev));
876 return 0;
877 }
878
879 /* Individual address setup command */
880
881 iasetup_cmd.com.ie_cmd_status = 0;
882 iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
883 iasetup_cmd.com.ie_cmd_link = 0xffff;
884
885 bcopy ( CLLADDR(ifp->if_sadl), (void *) &iasetup_cmd.ie_address,
886 sizeof (iasetup_cmd.ie_address) );
887
888 if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd,
889 IE_STAT_COMPL) )
890 {
891 printf ( "%s: iasetup failed : timeout\n", device_xname(sc->sc_dev));
892 return 0;
893 }
894
895 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) )
896 {
897 printf ( "%s: iasetup failed : !IE_STAT_OK\n", device_xname(sc->sc_dev));
898 return 0;
899 }
900
901 ie_ack ( sc, IE_ST_WHENCE );
902
903 /* Run the time-domain refloctometer */
904 run_tdr ( sc );
905
906 ie_ack ( sc, IE_ST_WHENCE );
907
908 /* meminit */
909 ptr = setup_rfa(sc, ptr);
910
911 ifp->if_flags |= IFF_RUNNING;
912
913 /* Setup transmit buffers */
914
915 for ( n=0; n<NTXBUF; n++ ) {
916 sc->xmit_cmds[n] = ptr;
917 iezero(sc, ptr, sizeof(struct ie_xmit_cmd) );
918 ptr += sizeof(struct ie_xmit_cmd);
919
920 sc->xmit_buffs[n] = ptr;
921 iezero(sc, ptr, sizeof(struct ie_xmit_buf));
922 ptr += sizeof(struct ie_xmit_buf);
923 }
924
925 for ( n=0; n<NTXBUF; n++ ) {
926 sc->xmit_cbuffs[n] = ptr;
927 ptr += IE_TXBUF_SIZE;
928 }
929
930 sc->xmit_free = NTXBUF;
931 sc->xchead = sc->xctail = 0;
932
933 {
934 struct ie_xmit_cmd xmcmd;
935 bzero ( &xmcmd, sizeof xmcmd );
936 xmcmd.ie_xmit_status = IE_STAT_COMPL;
937 host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd);
938 }
939
940 start_receiver (sc);
941
942 return 0;
943 }
944
945 int
iestop(struct ie_softc * sc)946 iestop(struct ie_softc *sc)
947 {
948 struct ie_sys_ctl_block scb;
949 int s = splnet();
950
951 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
952
953 if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) )
954 printf ( "ie0: abort commands timed out\n" );
955
956 (void)splx(s);
957 return(0);
958 }
959
960 /*
961 * Send a command to the card and await its completion.
962 * Timeout if it's taking too long
963 */
964
965 /*CAW*/
966
967 static int
command_and_wait(struct ie_softc * sc,u_short cmd,struct ie_sys_ctl_block * pscb,void * pcmd,int ocmd,int scmd,int mask)968 command_and_wait(struct ie_softc *sc, u_short cmd, struct ie_sys_ctl_block *pscb, void *pcmd, int ocmd, int scmd, int mask)
969 {
970 int i=0;
971
972 /* Copy the command to the card */
973
974 if ( pcmd )
975 host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */
976
977 /* Copy the scb to the card */
978
979 if ( pscb ) {
980 pscb->ie_command = cmd;
981 host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb);
982 }
983 else
984 {
985 setpage ( sc, IE_IBASE + IE_SCB_OFF );
986 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
987 (xoffsetof(struct ie_sys_ctl_block, ie_command)), cmd );
988 }
989
990 /* Prod the card to act on the newly loaded command */
991 ieattn(sc);
992
993 /* Wait for the command to complete */
994 if ( IE_ACTION_COMMAND(cmd) && pcmd )
995 {
996 setpage(sc,ocmd);
997 for ( i=4000; --i>=0; ) {
998 if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) +
999 (xoffsetof(struct ie_config_cmd, ie_config_status))) & mask)
1000 break;
1001 delay(100);
1002 }
1003 }
1004 else
1005 {
1006 for ( i=4000; --i>=0; ) {
1007 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
1008 (xoffsetof(struct ie_sys_ctl_block, ie_command))) )
1009 break;
1010 delay(100);
1011 }
1012 }
1013
1014 /* Update the host structures to reflect the state on the card */
1015 if ( pscb )
1016 ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb );
1017 if ( pcmd )
1018 ie2host(sc, ocmd, pcmd, scmd);
1019
1020 return i < 0;
1021 }
1022
1023 #define READ_MEMBER(sc,type,member,ptr,dest) \
1024 setpage(sc, ptr); \
1025 dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) + \
1026 (xoffsetof(type, member)) );
1027
1028 #define WRITE_MEMBER(sc,type,member,ptr,dest) \
1029 setpage(sc, ptr); \
1030 PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) + \
1031 (xoffsetof(type, member)), dest );
1032
1033 static inline int
ie_buflen(struct ie_softc * sc,int head)1034 ie_buflen(struct ie_softc *sc, int head)
1035 {
1036 int actual;
1037
1038 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1039 sc->rbuffs[head], actual );
1040
1041 return(actual & (IE_RXBUF_SIZE | (IE_RXBUF_SIZE-1))) ;
1042 }
1043
1044 static inline int
ie_packet_len(struct ie_softc * sc)1045 ie_packet_len(struct ie_softc *sc)
1046 {
1047 int i;
1048 int actual;
1049 int head = sc->rbhead;
1050 int acc=0;
1051
1052 do {
1053 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1054 sc->rbuffs[sc->rbhead], actual );
1055 if (!(actual&IE_RBD_USED))
1056 {
1057 return (-1);
1058 }
1059
1060 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1061 sc->rbuffs[head], i );
1062 i = i & IE_RBD_LAST;
1063
1064 acc += ie_buflen(sc, head);
1065 head = (head+1) % NRXBUF;
1066 } while (!i);
1067
1068 return acc;
1069 }
1070
1071 struct mbuf *
ieget(struct ie_softc * sc,int * to_bpf)1072 ieget(struct ie_softc *sc, int *to_bpf )
1073 {
1074 struct mbuf *top, **mp, *m;
1075 int head;
1076 int resid, totlen, thisrboff, thismboff;
1077 int len;
1078 struct ether_header eh;
1079
1080 totlen = ie_packet_len(sc);
1081
1082 if ( totlen > ETHER_MAX_LEN )
1083 {
1084 printf ( "ie: Gosh that packet was s-o-o-o big.\n" );
1085 return 0;
1086 }
1087
1088 if ( totlen<=0 )
1089 return 0;
1090
1091 head = sc->rbhead;
1092
1093 /* Read the ethernet header */
1094 ie2host ( sc, sc->cbuffs[head], (void *)&eh, sizeof eh );
1095
1096 /* Check if the packet is for us */
1097
1098 resid = totlen;
1099
1100 MGETHDR ( m, M_DONTWAIT, MT_DATA );
1101 if ( m==0 )
1102 return 0;
1103
1104 m_set_rcvif(m, &sc->sc_ethercom.ec_if);
1105 m->m_pkthdr.len = totlen;
1106 len = MHLEN;
1107 top = 0;
1108 mp = ⊤
1109
1110 /*
1111 * This loop goes through and allocates mbufs for all the data we will
1112 * be copying in. It does not actually do the copying yet.
1113 */
1114 while (totlen > 0) {
1115 if (top) {
1116 MGET(m, M_DONTWAIT, MT_DATA);
1117 if (m == 0) {
1118 m_freem(top);
1119 return 0;
1120 }
1121 len = MLEN;
1122 }
1123 if (totlen >= MINCLSIZE) {
1124 MCLGET(m, M_DONTWAIT);
1125 if (m->m_flags & M_EXT)
1126 len = MCLBYTES;
1127 }
1128
1129 if (mp == &top) {
1130 void *newdata = (void *)
1131 ALIGN(m->m_data + sizeof(struct ether_header)) -
1132 sizeof(struct ether_header);
1133 len -= newdata - m->m_data;
1134 m->m_data = newdata;
1135 }
1136
1137 m->m_len = len = min(totlen, len);
1138
1139 totlen -= len;
1140 *mp = m;
1141 mp = &m->m_next;
1142 }
1143
1144 m = top;
1145 thismboff = 0;
1146
1147 /*
1148 * Copy the Ethernet header into the mbuf chain.
1149 */
1150 memcpy(mtod(m, void *), &eh, sizeof(struct ether_header));
1151 thismboff = sizeof(struct ether_header);
1152 thisrboff = sizeof(struct ether_header);
1153 resid -= sizeof(struct ether_header);
1154
1155 /*
1156 * Now we take the mbuf chain (hopefully only one mbuf most of the
1157 * time) and stuff the data into it. There are no possible failures at
1158 * or after this point.
1159 */
1160 while (resid > 0) {
1161 int thisrblen = ie_buflen(sc, head) - thisrboff,
1162 thismblen = m->m_len - thismboff;
1163 len = min(thisrblen, thismblen);
1164
1165 /* bcopy((void *)(sc->cbuffs[head] + thisrboff),
1166 mtod(m, void *) + thismboff, (u_int)len); */
1167
1168
1169 if ( len&1 )
1170 {
1171 ie2host(sc, sc->cbuffs[head]+thisrboff,
1172 mtod(m, void *) + thismboff, (u_int)len+1);
1173 }
1174 else
1175 {
1176 ie2host(sc, sc->cbuffs[head]+thisrboff,
1177 mtod(m, void *) + thismboff, (u_int)len);
1178 }
1179
1180 resid -= len;
1181
1182 if (len == thismblen) {
1183 m = m->m_next;
1184 thismboff = 0;
1185 } else
1186 thismboff += len;
1187
1188 if (len == thisrblen) {
1189 head = (head + 1) % NRXBUF;
1190 thisrboff = 0;
1191 } else
1192 thisrboff += len;
1193 }
1194
1195
1196 return top;
1197 }
1198
1199 void
ie_drop_packet_buffer(struct ie_softc * sc)1200 ie_drop_packet_buffer(struct ie_softc *sc)
1201 {
1202 int i, actual, last;
1203
1204 do {
1205 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual,
1206 sc->rbuffs[sc->rbhead], actual );
1207 if (!(actual&IE_RBD_USED))
1208 {
1209 iereset(sc);
1210 return;
1211 }
1212
1213 i = actual & IE_RBD_LAST;
1214
1215 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1216 sc->rbuffs[sc->rbhead], last );
1217 last |= IE_RBD_LAST;
1218 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1219 sc->rbuffs[sc->rbhead], last );
1220
1221 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual,
1222 sc->rbuffs[sc->rbhead], 0 );
1223
1224 sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF;
1225
1226 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1227 sc->rbuffs[sc->rbtail], last );
1228 last &= ~IE_RBD_LAST;
1229 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length,
1230 sc->rbuffs[sc->rbtail], last );
1231
1232 sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF;
1233 } while (!i);
1234 }
1235
1236 void
ie_read_frame(struct ie_softc * sc,int num)1237 ie_read_frame(struct ie_softc *sc, int num)
1238 {
1239 int status;
1240 struct ie_recv_frame_desc rfd;
1241 struct mbuf *m=0;
1242 struct ifnet *ifp;
1243 int last;
1244
1245 ifp = &sc->sc_ethercom.ec_if;
1246
1247 ie2host(sc, sc->rframes[num], &rfd, sizeof rfd );
1248 status = rfd.ie_fd_status;
1249
1250 /* Advance the RFD list, since we're done with this descriptor */
1251
1252 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
1253 sc->rframes[num], 0 );
1254
1255 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1256 sc->rframes[num], last );
1257 last |= IE_FD_LAST;
1258 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1259 sc->rframes[num], last );
1260
1261 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1262 sc->rframes[sc->rftail], last );
1263 last &= ~IE_FD_LAST;
1264 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last,
1265 sc->rframes[sc->rftail], last );
1266
1267 sc->rftail = ( sc->rftail + 1 ) % NFRAMES;
1268 sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES;
1269
1270 if ( status & IE_FD_OK ) {
1271 m = ieget(sc, 0);
1272 ie_drop_packet_buffer(sc);
1273 }
1274
1275 if ( m==0 ) {
1276 if_statinc(ifp, if_ierrors);
1277 return;
1278 }
1279
1280 if_percpuq_enqueue(ifp->if_percpuq, m);
1281 }
1282
1283 void
ierint(struct ie_softc * sc)1284 ierint(struct ie_softc *sc)
1285 {
1286 int i;
1287 int times_thru = 1024;
1288 struct ie_sys_ctl_block scb;
1289 int status;
1290 int safety_catch = 0;
1291
1292 i = sc->rfhead;
1293 for (;;) {
1294
1295 if ( (safety_catch++)>100 )
1296 {
1297 printf ( "ie: ierint safety catch tripped\n" );
1298 iereset(sc);
1299 return;
1300 }
1301
1302 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status,
1303 sc->rframes[i],status);
1304
1305 if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) {
1306 if ( !--times_thru ) {
1307 printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" );
1308 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
1309 sc->sc_ethercom.ec_if.if_ierrors += scb.ie_err_crc +
1310 scb.ie_err_align +
1311 scb.ie_err_resource +
1312 scb.ie_err_overrun;
1313 scb.ie_err_crc = scb.ie_err_align = 0;
1314 scb.ie_err_resource = scb.ie_err_overrun = 0;
1315 host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) );
1316 }
1317 ie_read_frame(sc, i);
1318 } else {
1319 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
1320
1321 if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) )
1322 {
1323 WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc,
1324 sc->rframes[0], sc->rbuffs[0] );
1325
1326 scb.ie_recv_list = sc->rframes[0];
1327 host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) );
1328 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0);
1329 }
1330 break;
1331 }
1332 i = (i + 1) % NFRAMES;
1333 }
1334 }
1335
1336 static int in_intr = 0;
1337
1338 int
ieintr(void * arg)1339 ieintr(void *arg)
1340 {
1341 struct ie_softc *sc = arg;
1342 u_short status;
1343 int safety_catch = 0;
1344 static int safety_net = 0;
1345
1346 if (in_intr == 1)
1347 panic ( "ie: INTERRUPT REENTERED\n" );
1348
1349 /* Clear the interrrupt */
1350 ie_cli (sc);
1351
1352 setpage(sc, IE_IBASE + IE_SCB_OFF );
1353 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
1354 (xoffsetof(struct ie_sys_ctl_block, ie_status)) );
1355
1356 status = status & IE_ST_WHENCE;
1357
1358 if (status == 0) {
1359 in_intr = 0;
1360 return(0);
1361 }
1362
1363 loop:
1364
1365 ie_ack(sc, status);
1366
1367 if (status & (IE_ST_FR | IE_ST_RNR))
1368 ierint(sc);
1369
1370 if (status & IE_ST_CX)
1371 ietint(sc);
1372
1373 if (status & IE_ST_RNR) {
1374 printf ( "ie: receiver not ready\n" );
1375 sc->sc_ethercom.ec_if.if_ierrors++;
1376 iereset(sc);
1377 }
1378
1379 setpage(sc, IE_IBASE + IE_SCB_OFF );
1380 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) +
1381 (xoffsetof(struct ie_sys_ctl_block, ie_status)) );
1382 status = status & IE_ST_WHENCE;
1383
1384 ie_cli(sc);
1385
1386 if (status == 0) {
1387 in_intr = 0;
1388 return(0);
1389 }
1390
1391 /* This is prehaps a little over cautious */
1392 if ( safety_catch++ > 10 )
1393 {
1394 printf ( "ie: Interrupt couldn't be cleared\n" );
1395 delay ( 1000 );
1396 ie_cli(sc);
1397 if ( safety_net++ > 50 )
1398 {
1399 /* printf ( "ie: safety net catches driver, shutting down\n" );
1400 disable_irq ( IRQ_PODULE );*/
1401 }
1402 in_intr = 0;
1403 return(0);
1404 }
1405
1406 goto loop;
1407 }
1408
1409 void
iexmit(struct ie_softc * sc)1410 iexmit(struct ie_softc *sc)
1411 {
1412 /* int actual;*/
1413 struct ie_sys_ctl_block scb;
1414
1415 struct ie_xmit_cmd xc;
1416 struct ie_xmit_buf xb;
1417
1418 ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb );
1419 xb.ie_xmit_flags |= IE_XMIT_LAST;
1420 xb.ie_xmit_next = 0xffff;
1421 xb.ie_xmit_buf = (void *)sc->xmit_cbuffs[sc->xctail];
1422 host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb );
1423
1424 bzero ( &xc, sizeof xc );
1425 xc.com.ie_cmd_link = 0xffff;
1426 xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
1427 xc.ie_xmit_status = 0x0000;
1428 xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail];
1429 host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc );
1430
1431 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb );
1432 scb.ie_command_list = sc->xmit_cmds[sc->xctail];
1433 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb );
1434
1435 command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail]
1436 , sizeof xc, IE_STAT_COMPL);
1437
1438 sc->sc_ethercom.ec_if.if_timer = 5;
1439 }
1440 /*
1441 * Start sending all the queued buffers.
1442 */
1443
1444 void
iestart(struct ifnet * ifp)1445 iestart(struct ifnet *ifp)
1446 {
1447 struct ie_softc *sc = ifp->if_softc;
1448 struct mbuf *m0, *m;
1449 u_char *buffer;
1450 u_short len;
1451 char txbuf[IE_TXBUF_SIZE];
1452 int safety_catch = 0;
1453
1454 while (sc->xmit_free != 0) {
1455 if ( (safety_catch++)>100 )
1456 {
1457 printf ( "ie: iestart safety catch tripped\n" );
1458 iereset(sc);
1459 return;
1460 }
1461
1462 IF_DEQUEUE(&ifp->if_snd, m);
1463 if (!m)
1464 break;
1465
1466 /* TODO: Write directly to the card */
1467 len = 0;
1468 /* buffer = sc->xmit_cbuffs[sc->xchead]; */
1469 buffer = txbuf;
1470
1471 for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE;
1472 m = m->m_next) {
1473 memcpy(buffer, mtod(m, void *), m->m_len);
1474 buffer += m->m_len;
1475 len += m->m_len;
1476 }
1477
1478 bpf_mtap(ifp, m0, BPF_D_OUT);
1479
1480 m_freem(m0);
1481 if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
1482 memset(buffer, 0, ETHER_MIN_LEN - ETHER_CRC_LEN - len);
1483 len = ETHER_MIN_LEN - ETHER_CRC_LEN;
1484 buffer += ETHER_MIN_LEN - ETHER_CRC_LEN;
1485 }
1486
1487 /* When we write directly to the card we dont need this */
1488 if (len&1)
1489 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 );
1490 else
1491 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len );
1492
1493 /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */
1494
1495 WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags,
1496 sc->xmit_buffs[sc->xchead], len)
1497
1498 /* Start the first packet transmitting. */
1499 if (sc->xmit_free == NTXBUF)
1500 iexmit(sc);
1501
1502 sc->xchead = (sc->xchead + 1) % NTXBUF;
1503 sc->xmit_free--;
1504 }
1505 }
1506
1507 void
ietint(struct ie_softc * sc)1508 ietint(struct ie_softc *sc)
1509 {
1510 struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1511
1512 int status;
1513
1514 ifp->if_timer=0;
1515
1516 READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status,
1517 sc->xmit_cmds[sc->xctail], status );
1518
1519 if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) )
1520 printf ( "ietint: command still busy!\n" );
1521
1522 if ( status & IE_STAT_OK ) {
1523 if_statinc(ifp, if_opackets);
1524 if_statadd(ifp, if_collisions, status & IE_XS_MAXCOLL);
1525 } else {
1526 if_statinc(ifp, if_oerrors);
1527 if ( status & IE_STAT_ABORT )
1528 printf ( "ie: send aborted\n" );
1529 if ( status & IE_XS_LATECOLL )
1530 printf ( "ie: late collision\n" );
1531 if ( status & IE_XS_NOCARRIER )
1532 printf ( "ie: no carrier\n" );
1533 if ( status & IE_XS_LOSTCTS )
1534 printf ( "ie: lost CTS\n" );
1535 if ( status & IE_XS_UNDERRUN )
1536 printf ( "ie: DMA underrun\n" );
1537 if ( status & IE_XS_EXCMAX )
1538 printf ( "ie: too many collisions\n" );
1539 if_statadd(ifp, if_collisions, 16);
1540 }
1541 /* Done with the buffer */
1542 sc->xmit_free++;
1543 sc->xctail = (sc->xctail + 1 ) % NTXBUF;
1544
1545 /* Start the next packet transmitting, if any */
1546 if ( sc->xmit_free<NTXBUF )
1547 iexmit(sc);
1548
1549 if_schedule_deferred_start(ifp);
1550 }
1551
1552 /* End of if_ie.c */
1553