|
|
1.1 root 1: /*
2: * Copyright (c) 1985 by Sun Microsystems, Inc.
3: */
4:
5: #include "ie.h"
6: #if NIE > 0
7: /*
8: * Sun Intel Ethernet Controller interface
9: */
10:
11: #include "../h/param.h"
12: #include "../h/systm.h"
13: #include "../machine/pte.h"
14: #include "../h/map.h"
15: #include "../h/buf.h"
16: #include "../h/vmmac.h"
17: #include "../h/conf.h"
18: #include "../h/ttyio.h"
19: #include "../h/enio.h"
20: #include "../h/ttyld.h"
21: #include "../h/stream.h"
22: #include "../h/ethernet.h"
23:
24: #include "../sundev/mbvar.h"
25: #include "../sundev/iereg.h"
26: #include "../sundev/iem.h"
27: #include "../sundev/ieob.h"
28:
29: /* controller types */
30: #define IE_MB 1 /* Multibus */
31: #define IE_OB 2 /* Onboard I/O */
32:
33: #define IEOBMEMDFT (40*1024) /* default memory allocated for obie */
34: #define CBCACHESIZ (80) /* size of control block cache */
35: #define OVFLWARNMASK (3) /* overflow count mask before warning */
36: #define NPOOL_RBD 50
37: #define NTRANSBUF 4 /* NUmber of transmit buffers */
38:
39: int ieprobe(), ieattach(), iepoll();
40: struct mb_device *ieinfo[NIE];
41: struct mb_driver iedriver = {
42: ieprobe, 0, ieattach, 0, 0, iepoll,
43: /* take the larger of the two devices */
44: sizeof (struct mie_device), "ie", ieinfo,
45: };
46:
47: int iebark(), iedog();
48: caddr_t from_ieaddr();
49: ieoff_t to_ieoff();
50: caddr_t from_ieoff();
51: ieaddr_t to_ieaddr();
52: long escbget(), escbput();
53: ieint_t to_ieint();
54: #define from_ieint to_ieint
55:
56: #define iepages(x) (((x) + IEPAGSIZ-1)>>IEPAGSHIFT)
57:
58: int iecbcsmall;
59: int iecbclarge;
60:
61: /*
62: * Ethernet software status per interface.
63: */
64: struct ie_softc {
65: /* Added by D.A.K for version 9 compatability */
66: char myetheradr[6];
67: char attached; /* Non zero when ie has been attached */
68: int state;
69: int collisions;
70: int ierrors, oerrors;
71: int ipackets, opackets;
72: struct ietfd *es_tfd[NTRANSBUF]; /* transmit TFD */
73: struct ietbd *es_tbd[NTRANSBUF]; /* transmit TBD */
74: caddr_t es_tbuffer[NTRANSBUF]; /* transmit buffer */
75: int es_tfree; /* transmitter bit map */
76: /* Supplied by SUN */
77: struct mie_device *es_mie; /* Multibus board registers */
78: struct obie_device *es_obie; /* On-board registers */
79: caddr_t es_memspace; /* + chip addr = kernel addr */
80: int es_paddr; /* starting page number for board */
81: int es_vmemsize; /* size of multibus mem port */
82: caddr_t es_base; /* our addr of control block base */
83: struct map *es_cbmap; /* rmap for control blocks */
84: struct map *es_memmap; /* rmap for memory */
85: struct map *es_pgmap; /* rmap for 1K page (ND) memory
86: accessed thru if_memmap */
87: struct iescb *es_scb; /* SCB ptr */
88: struct iescp *es_scp; /* SCP ptr */
89: struct iecb *es_cbhead; /* CBL head */
90: struct iecb *es_cbtail; /* CBL tail */
91: struct ierfd *es_rfdhead; /* head of RFD list */
92: struct ierfd *es_rfdtail; /* tail of RFD list */
93: struct ierbd *es_rbdhead; /* head of RBD list */
94: struct ierbd *es_rbdtail; /* tail of RBD list */
95: struct ieipack *es_iepavail; /* standby input packets */
96: time_t es_latest; /* latest packet arrival time */
97: int es_obmem; /* total IE_OB main memory */
98: char es_type; /* type of controller */
99: char es_simple; /* doing simple flag */
100: u_int es_runotready; /* RU was not ready counter */
101: u_int es_xmiturun; /* xmit DMA underrun counter */
102: u_int es_dogreset; /* iedog reset counter */
103: u_int es_ieheart; /* heartbeat counter */
104: u_int es_iedefer; /* deferred transmission counter */
105: struct ieierr {
106: u_int crc;
107: u_int aln;
108: u_int rsc;
109: u_int ovr;
110: } es_ierr; /* input error counters */
111: int es_cbsize; /* control block area size */
112: int es_cbc_lo; /* small block cache pointer */
113: int es_cbc_hi; /* large block cache pointer */
114: u_int es_cbc_ovfl; /* overflow counter */
115: int es_cbcbusy; /* cache is loaded */
116: long es_cbcache[CBCACHESIZ]; /* control block cache */
117: } ie_softc[NIE];
118:
119: #define NIECHAN (CHANS_PER_UNIT * NIE)
120: struct iechan {
121: int unit;
122: int packets;
123: struct queue *ieq;
124: int type;
125: } iechan[NIECHAN];
126:
127: int nodev(), ieopen(), ieclose(), ieput(), iesrv();
128: static struct qinit ierinit = { nodev, NULL, ieopen, ieclose, 0, 0 };
129: static struct qinit iewinit = { ieput, NULL, ieopen, ieclose, 1514, 0 };
130: /* 1514 bytes is minimum highwater mark to send 1514 byte packets */
131: struct streamtab iesinfo = { &ierinit, &iewinit };
132:
133: #define IEMAPSIZ 100
134: struct map iecbmap[NIE][IEMAPSIZ];
135: struct map iememmap[NIE][IEMAPSIZ];
136: struct map iepgmap[NIE][IEMAPSIZ];
137: #define escballoc(es, type, cached) (type *)escbget(es, sizeof(type), cached)
138: #define escbfree(es, ptr) escbput(es, sizeof(*ptr), (long)ptr);
139: #define escbpin(es, len, addr) rmget(es->es_cbmap, (int)len, (int)addr)
140: #define esmemalloc(es, len) rmalloc(es->es_memmap, (long)len)
141: #define esmemfree(es, len, ptr) rmfree(es->es_memmap, (long)len, (long)ptr)
142: #define esmempin(es, len, addr) rmget(es->es_memmap, (int)len, (int)addr)
143:
144: /*
145: * fixed header size for page alignment of received data buffers
146: * this is sizeof(struct ndpack) for ND. (doesn't include ether header)
147: */
148: #define OPTHDRSIZ 48
149: #define IPACKOVH 8 /* struct ieipack header overhead */
150: struct ieipack {
151: struct ieipack *iep_next; /* next in list; MUST BE FIRST FIELD */
152: struct ie_softc *iep_es; /* assoc ie_softc */
153: char iep_data[1500]; /* the packet */
154: };
155:
156: #define IEDELAY 400000 /* delay period (in ms) before giving up */
157: #define IEKLUDGE 20 /* delay period (in ms) to make chip work */
158:
159: /*
160: * Probe for device.
161: */
162: ieprobe(reg, unit)
163: caddr_t reg;
164: {
165: register short *sp;
166: struct ie_softc *es = &ie_softc[unit];
167:
168: if ((getkpgmap(reg) & PGT_MASK) == PGT_OBIO) {
169: register struct obie_device *obie = (struct obie_device *)reg;
170:
171: /* onboard Ethernet */
172: if (pokec(reg, 0))
173: return (0);
174: if (peekc(reg) == -1)
175: return (0);
176: if (obie->obie_noreset)
177: return (0);
178: es->es_type = IE_OB;
179: } else {
180: register struct mie_device *mie = (struct mie_device *)reg;
181:
182: /* Multibus Ethernet */
183: sp = (short *)mie;
184: if (poke(sp, 0))
185: return (0);
186: sp = &mie->mie_prom[0];
187: if (poke(sp, 0x6789))
188: return (0);
189: if (peek(sp) == 0x6789)
190: return (0);
191: es->es_type = IE_MB;
192: }
193: return (1);
194: }
195:
196: /*
197: * Interface exists; make available by filling in network interface
198: * record. System will initialize the interface when it is ready
199: * to accept packets.
200: */
201: ieattach(md)
202: struct mb_device *md;
203: {
204: struct ie_softc *es = &ie_softc[md->md_unit];
205:
206: if (md->md_intr) /* set up vectored interrupts */
207: *(md->md_intr->v_vptr) = (int)es;
208:
209: if (es->es_type == IE_OB) {
210: es->es_obie = (struct obie_device *)md->md_addr;
211: es->es_obmem = IEOBMEMDFT;
212: } else {
213: es->es_mie = (struct mie_device *)md->md_addr;
214: /*
215: * magic thru config used to artificially restrict
216: * the amount of MBMEM used, as there is only 1 Mb
217: * available, making it a scarce resource.
218: */
219: switch (md->md_flags) {
220: case 0:
221: default:
222: es->es_vmemsize = 256*1024;
223: break;
224: case 1:
225: es->es_vmemsize = 128*1024;
226: break;
227: case 2:
228: es->es_vmemsize = 64*1024;
229: break;
230: }
231: }
232: iechipreset(es);
233: localetheraddr(NULL, es->myetheradr);
234: ieinit(md->md_unit);
235: es->attached = 1;
236: }
237:
238: /* ARGSUSED */
239: ieopen(q, dev)
240: register struct queue *q;
241: register dev_t dev;
242: {
243: register struct iechan *ied;
244: register struct ie_softc *es;
245: register unit;
246:
247: dev = minor(dev);
248: unit = dev / CHANS_PER_UNIT;
249:
250: if (dev >= NIECHAN)
251: return(0);
252: if (unit >= NIE)
253: return(0);
254:
255: es = &ie_softc[unit];
256: if(!es->attached)
257: return(0);
258: ied = &iechan[dev];
259: if (ied->ieq)
260: return(0);
261:
262: ied->unit = unit;
263: ied->ieq = q;
264: q->ptr = (caddr_t)ied;
265: q->flag |= QBIGB | QDELIM;
266: WR(q)->ptr = (caddr_t)ied;
267: WR(q)->flag |= QBIGB|QDELIM;
268: return(1);
269: }
270:
271: ieclose(q)
272: register struct queue *q;
273: {
274: register struct iechan *ied;
275:
276: ied = (struct iechan *)q->ptr;
277: flushq(WR(q), 1);
278: ied->ieq = NULL;
279: }
280:
281: ieput(q, bp)
282: register struct queue *q;
283: register struct block *bp;
284: {
285: register struct iechan *ied;
286: register struct ie_softc *es;
287: register unit, s;
288:
289: ied = (struct iechan *)q->ptr;
290: unit = ied->unit;
291: es = &ie_softc[unit];
292:
293: switch(bp->type) {
294:
295: case M_IOCTL:
296: ieioctl(q, bp);
297: return;
298:
299: case M_DATA:
300: putq(q, bp);
301: return;
302:
303: case M_DELIM:
304: break;
305:
306: default:
307: freeb(bp);
308: return;
309: }
310:
311: putq(q, bp);
312: s = splie();
313: ied->packets++;
314: if (es->es_tfree)
315: iestartout(unit);
316: splx(s);
317: }
318:
319: /*
320: * Process an ioctl request.
321: */
322: ieioctl(q, bp)
323: register struct queue *q;
324: register struct block *bp;
325: {
326: register struct iechan *ied;
327: register struct ie_softc *es;
328: register u_char *msg;
329: int unit, cmd;
330:
331: ied = (struct iechan *)q->ptr;
332: unit = ied->unit;
333: es = &ie_softc[unit];
334: cmd = ((union stmsg *)(bp->rptr))->ioc1.com;
335: msg = (u_char *)&((union stmsg *)(bp->rptr))->ioc1.sb;
336:
337: bp->type = M_IOCACK;
338: switch (cmd) {
339: case ENIOADDR: /* get my Ethernet address */
340: bcopy(es->myetheradr, (int *)msg, 6);
341: break;
342:
343: case ENIOTYPE:
344: ied->type = *(int *)msg;
345: break;
346:
347: default:
348: bp->type = M_IOCNAK;
349: break;
350: }
351: qreply(q, bp);
352: }
353:
354: /*
355: * Unresponsive chip alarm. Scheduled by iedog; chip has some number
356: * of seconds to execute a nop, else alarm goes off.
357: */
358: iebark(es)
359: struct ie_softc *es;
360: {
361: int unit = es - ie_softc;
362:
363: printf("ie%d: iebark reset\n", unit);
364: ieinit(unit);
365: }
366:
367: /*
368: * Watchdog (deadman) timer routine, invoked every 10 seconds.
369: */
370: iedog(es)
371: struct ie_softc *es;
372: {
373: int unit = es - ie_softc;
374: int s = splie();
375: struct iecb *cb;
376: int fatal = 0;
377:
378: /* poll for bus error on obie */
379: if (es->es_type == IE_OB)
380: if (es->es_obie->obie_buserr) {
381: printf("ie%d: obie buserr reset\n", unit);
382: fatal = 1;
383: goto reset;
384: }
385:
386: /* ensure cu ok with a nop */
387: cb = escballoc(es, struct iecb, 1);
388: if (cb == NULL)
389: goto reset;
390: bzero((caddr_t)cb, sizeof (struct iecb));
391: cb->ie_cmd = IE_NOP;
392: iedocb(es, cb);
393: iecustart(es);
394: /* some number of seconds delay before iebark */
395: timeout(iebark, (caddr_t)es, hz<<2);
396:
397: /* ensure ru ok with recent reception */
398: if (es->es_latest + 90 < time) {
399: /* restart timeout period */
400: es->es_latest = time;
401: goto reset;
402: }
403:
404: timeout(iedog, (caddr_t)es, 10*hz);
405: goto exit;
406: reset:
407: es->es_dogreset++;
408: ieinit(unit);
409: if (fatal)
410: panic("iedog");
411: /* FALL THRU */
412: exit:
413: (void) splx(s);
414: }
415:
416: /*
417: * Unconditionally restart the interface from ground zero.
418: */
419: ieinit(unit)
420: int unit;
421: {
422: struct ie_softc *es = &ie_softc[unit];
423: int s = splie();
424:
425: iechipreset(es);
426: untimeout(iebark, (caddr_t)es);
427: untimeout(iedog, (caddr_t)es);
428:
429: iedomaps(es);
430: if (!iechipinit(es))
431: goto exit;
432: iedoaddr(es);
433: /*
434: * Hang out receive buffers and start any pending writes.
435: */
436: ierustart(es);
437: iesplice(es);
438: iestartout(unit);
439: timeout(iedog, (caddr_t)es, 10*hz);
440: es->es_latest = time;
441: exit:
442: (void) splx(s);
443: }
444:
445: /*
446: * Handle Polling Ethernet interrupts
447: */
448: iepoll()
449: {
450: register struct ie_softc *es;
451: register int found = 0;
452:
453: for (es = ie_softc; es < &ie_softc[NIE]; es++) {
454: switch (es->es_type) {
455: case IE_MB:
456: if (es->es_mie->mie_pie && es->es_mie->mie_pe) {
457: ieparity(es);
458: return (1);
459: }
460: if (es->es_mie->mie_ie == 0)
461: continue;
462: if (es->es_mie->mie_intr)
463: found = 1;
464: break;
465: case IE_OB:
466: if (es->es_obie->obie_buserr)
467: panic("ie: bus error");
468: if (es->es_obie->obie_ie == 0)
469: continue;
470: if (es->es_obie->obie_intr)
471: found = 1;
472: break;
473: default: /* not present */
474: continue;
475: }
476: /*
477: * Since the 82586 can take away an interrupt
478: * request after presenting it to the processsor
479: * (to facilitate an update of a new interrupt
480: * condition in the scb), we also have to check
481: * the scb to see if it indicates an interrupt
482: * condition from the chip.
483: */
484: if (found == 0) {
485: register struct iescb *scb = es->es_scb;
486:
487: if (scb->ie_cx || scb->ie_fr ||
488: scb->ie_cnr || scb->ie_rnr)
489: found = 1;
490: }
491: if (found) {
492: ieintr(es);
493: break;
494: }
495: }
496: return (found);
497: }
498:
499: /*
500: * Handle Ethernet interrupts
501: */
502: ieintr(es)
503: register struct ie_softc *es;
504: {
505: register struct iescb *scb;
506: register int cmd, unit;
507:
508: unit = es - ie_softc;
509: scb = es->es_scb;
510: iechkcca(scb);
511: if (scb->ie_cmd != 0) {
512: register struct mb_device *md;
513:
514: printf("ie%d: lost synch\n", unit);
515: iestat(es);
516: if (unit >= NIE || (md = ieinfo[unit]) == 0 ||
517: md->md_alive == 0)
518: return;
519: ieinit(unit);
520: return;
521: }
522: cmd = 0;
523: /*
524: * This can be done faster with something like:
525: * cmd = (*(short *)scb->ie_cx) &
526: * (IECMD_ACK_CX|IECMD_ACK_FR|IECMD_ACK_CNR|IECMD_ACK_RNR);
527: */
528:
529: if (scb->ie_cx)
530: cmd |= IECMD_ACK_CX;
531: if (scb->ie_fr)
532: cmd |= IECMD_ACK_FR;
533: if (scb->ie_cnr)
534: cmd |= IECMD_ACK_CNR;
535: if (scb->ie_rnr)
536: cmd |= IECMD_ACK_RNR;
537: if (cmd == 0) {
538: printf("ie%d: spurious intr\n", unit);
539: cmd = IECMD_ACK_CX+IECMD_ACK_FR+IECMD_ACK_CNR+IECMD_ACK_RNR;
540: }
541: scb->ie_cmd = cmd;
542: ieca(es);
543:
544: if (cmd & (IECMD_ACK_RNR|IECMD_ACK_FR))
545: ierecv(es);
546: if (cmd & (IECMD_ACK_CNR|IECMD_ACK_CX))
547: iecbdone(es);
548:
549: if (es->es_cbhead && scb->ie_cus == IECUS_IDLE) {
550: iechkcca(scb);
551: if (es->es_cbhead && scb->ie_cus == IECUS_IDLE &&
552: !scb->ie_cx && !scb->ie_cnr)
553: printf("ie%d: CU out of synch\n", unit);
554: }
555: }
556:
557: /*
558: * Tell the chip its ethernet address
559: */
560: iedoaddr(es)
561: register struct ie_softc *es;
562: {
563: register struct ieiaddr *iad;
564:
565: iad = escballoc(es, struct ieiaddr, 1);
566: if (iad == 0)
567: panic("iedoaddr: iad");
568: bzero((caddr_t)iad, sizeof (struct ieiaddr));
569: iad->ieia_cb.ie_cmd = IE_IADDR;
570: bcopy(es->myetheradr, iad->ieia_addr, sizeof(es->myetheradr));
571: iesimple(es, &iad->ieia_cb);
572: escbfree(es, iad);
573: }
574:
575: /*
576: * Move info from driver toward protocol interface
577: */
578: ieread(es, rfd)
579: register struct ie_softc *es;
580: register struct ierfd *rfd;
581: {
582: int unit = es - ie_softc;
583: register struct etherpup *header;
584: register struct ierbd *rbd;
585: register struct iechan *ied;
586: register struct queue *q;
587: register struct block *bp;
588: register len, min, i;
589: register u_char *p;
590: short type;
591:
592: if (!rfd->ierfd_ok) {
593: es->ierrors++;
594: printf("ie%d: receive error\n", unit);
595: return;
596: }
597: if (rfd->ierfd_rbd == IENORBD) {
598: printf("ie%d: runt packet\n", unit);
599: es->ierrors++;
600: return;
601: }
602: rbd = (struct ierbd *)from_ieoff(es, (ieoff_t)rfd->ierfd_rbd);
603: if (!rbd->ierbd_eof) { /* length > 1500 */
604: printf("ie%d: giant packet\n", unit);
605: es->ierrors++;
606: return;
607: }
608: /*
609: * Pull packet off interface.
610: */
611: header = (struct etherpup *)rfd->ierfd_dhost;
612: type = header->type;
613: ied = &iechan[unit * CHANS_PER_UNIT];
614: for (i = 0; i < CHANS_PER_UNIT; i++, ied++)
615: if (ied->ieq && ied->type == type)
616: break;
617: if (i >= CHANS_PER_UNIT)
618: return;
619: q = ied->ieq;
620: if (q->next->flag & QFULL) {
621: es->ierrors++;
622: return;
623: }
624: len = (rbd->ierbd_cnthi << 8) + rbd->ierbd_cntlo;
625:
626: /*
627: * Splice in the ethernet header
628: * Assumes allocb will return a block at least as big as etherpup.
629: */
630: bp = allocb(len + sizeof(struct etherpup));
631: *(struct etherpup *)bp->wptr = *header;
632: bp->wptr += sizeof(struct etherpup);
633:
634: /*
635: * Now copy the data
636: */
637: p = (u_char *)from_ieaddr(es, rbd->ierbd_buf);
638: i = MIN(((bp->lim - bp->base) - sizeof(struct etherpup)), len);
639: for(;;) {
640: len -= i;
641: while (i-- > 0)
642: *bp->wptr++ = *p++;
643: (*q->next->qinfo->putp)(q->next, bp);
644: if (len <= 0)
645: break;
646: bp = allocb(len);
647: i = MIN((bp->lim - bp->base), len);
648: }
649: if (putctl(q->next, M_DELIM))
650: es->ipackets++;
651: else
652: printf("ierint no DELIM bp\n");
653: }
654:
655: /*
656: * Process completed input packets
657: * and recycle resources;
658: * only called from interrupt level by ieintr
659: */
660: ierecv(es)
661: register struct ie_softc *es;
662: {
663: register struct ierfd *rfd, *nrfd;
664: register struct ierbd *rbd, *nrbd;
665: register struct iescb *scb = es->es_scb;
666: int eof, e;
667:
668: es->es_latest = time; /* latch arrival time */
669:
670: rfd = es->es_rfdhead;
671: if (rfd == NULL) /* not initialized */
672: return;
673: top:
674: while (rfd && rfd->ierfd_done) {
675: ieread(es, rfd);
676: if (rfd->ierfd_rbd != IENORBD) {
677: rbd = (struct ierbd *)from_ieoff(es,
678: (ieoff_t)rfd->ierfd_rbd);
679: if (rbd != es->es_rbdhead)
680: panic("ierecv rbd");
681: while (rbd && rbd->ierbd_used) {
682: if (rbd != (struct ierbd *)from_ieoff(es,
683: (ieoff_t)es->es_rbdtail->ierbd_next))
684: panic("ierecv rbd list");
685: nrbd = (struct ierbd *)from_ieoff(es,
686: (ieoff_t)rbd->ierbd_next);
687: rbd->ierbd_el = 1;
688: eof = rbd->ierbd_eof;
689: *(short *)rbd = 0;
690: es->es_rbdtail->ierbd_el = 0;
691: es->es_rbdtail = rbd;
692: rbd = es->es_rbdhead = nrbd;
693: if (eof)
694: break;
695: }
696: }
697: if (rfd != (struct ierfd *)from_ieoff(es,
698: (ieoff_t)es->es_rfdtail->ierfd_next))
699: panic("ierecv rfd list");
700: nrfd = (struct ierfd *)from_ieoff(es, (ieoff_t)rfd->ierfd_next);
701: rfd->ierfd_rbd = IENORBD;
702: rfd->ierfd_el = 1;
703: *(short *)rfd = 0;
704: es->es_rfdtail->ierfd_el = 0;
705: es->es_rfdtail = rfd;
706: rfd = es->es_rfdhead = nrfd;
707: }
708: if (e = scb->ie_crcerrs) { /* count of CRC errors */
709: scb->ie_crcerrs = 0;
710: e = from_ieint(e);
711: es->ierrors += e;
712: es->es_ierr.crc += e;
713: }
714: if (e = scb->ie_alnerrs) { /* count of alignment errors */
715: scb->ie_alnerrs = 0;
716: e = from_ieint(e);
717: es->ierrors += e;
718: es->es_ierr.aln += e;
719: }
720: if (e = scb->ie_rscerrs) { /* count of discarded packets */
721: scb->ie_rscerrs = 0;
722: e = from_ieint(e);
723: es->ierrors += e;
724: es->es_ierr.rsc += e;
725: }
726: if (e = scb->ie_ovrnerrs) { /* count of overrun packets */
727: scb->ie_ovrnerrs = 0;
728: e = from_ieint(e);
729: es->ierrors += e;
730: es->es_ierr.ovr += e;
731: }
732: if (scb->ie_rus == IERUS_READY) /* as expected */
733: return;
734: es->es_runotready++;
735: /* following test must be made when we know chip is quiet */
736: if (es->es_rfdhead->ierfd_done) /* more snuck in */
737: goto top;
738: es->es_rfdhead->ierfd_rbd = to_ieoff(es, (caddr_t)es->es_rbdhead);
739: iechkcca(scb);
740: scb->ie_rfa = to_ieoff(es, (caddr_t)es->es_rfdhead);
741: scb->ie_cmd = IECMD_RU_START;
742: ieca(es);
743: }
744:
745: /*
746: * Free up the resources after transmitting a packet.
747: * Called by iecuclean at splie or hardware level 3.
748: */
749: iexmitdone(es, td)
750: register struct ie_softc *es;
751: register struct ietfd *td;
752: {
753: int unit = es - ie_softc;
754: register int i;
755:
756: if (td->ietfd_ok) {
757: es->collisions += td->ietfd_ncoll;
758: es->opackets++;
759: if (td->ietfd_defer) es->es_iedefer++;
760: if (td->ietfd_heart) es->es_ieheart++;
761: } else {
762: es->oerrors++;
763: if (td->ietfd_xcoll)
764: printf("ie%d: Ethernet jammed\n", unit);
765: if (td->ietfd_nocarr)
766: printf("ie%d: no carrier\n", unit);
767: if (td->ietfd_nocts)
768: printf("ie%d: no CTS\n", unit);
769: if (td->ietfd_underrun)
770: es->es_xmiturun++;
771: }
772: if (!td->ietfd_tbd)
773: panic("ie%d: iexmitdone: no tbd");
774: for(i = 0; i < NTRANSBUF; i++)
775: if (td == es->es_tfd[i])
776: break;
777: if (es->es_tfree & (1 << i))
778: printf("ie%d stray xmit interrupt\n", unit);
779: es->es_tfree |= (1 << i);
780: }
781:
782: #define rndtoeven(x) (((x)+1) & ~1)
783: /*
784: * Start or restart output to wire.
785: */
786: iestartout(unit)
787: int unit;
788: {
789: register struct ie_softc *es = &ie_softc[unit];
790: register struct iechan *ied;
791: register cnt, i;
792: register caddr_t to;
793: int count, bufnum;
794: struct ietfd *td;
795: register struct ietbd *tbd;
796: register struct queue *q;
797: register struct block *bp, *nbp;
798: struct block *head, **bnext;
799:
800: if (!es->es_tfree)
801: goto out;
802: ied = &iechan[unit * CHANS_PER_UNIT];
803: for(i = 0; i < CHANS_PER_UNIT; i++, ied++)
804: if (ied->ieq && ied->packets > 0)
805: break;
806: if (i >= CHANS_PER_UNIT)
807: goto out;
808:
809: ied->packets--;
810: q = WR(ied->ieq);
811:
812: /* The packet must be justified to the end of the buffer.
813: * Therefore, we have to count the bytes before copying.
814: */
815: bnext = &head;
816: while (*bnext = bp = getq(q)) {
817: if (bp->type == M_DELIM) {
818: bp->next = 0;
819: break;
820: }
821: cnt += bp->wptr - bp->rptr;
822: bnext = &bp->next;
823: }
824: bp = head;
825:
826: /* if there is no ethernet header in packet, throw it out */
827: if (cnt < sizeof(struct etherpup) ||
828: (bp->wptr - bp->rptr) < sizeof(struct etherpup)) {
829: while(bp) {
830: nbp = bp->next;
831: freeb(bp);
832: bp = nbp;
833: }
834: goto out;
835: }
836:
837: bufnum = ffs(es->es_tfree);
838: es->es_tfree &= ~(1 << bufnum);
839: td = es->es_tfd[bufnum];
840: tbd = es->es_tbd[bufnum];
841:
842: /* Setup the header */
843: bcopy(bp->rptr, (caddr_t)td->ietfd_dhost, 6); /* Dest */
844: bp->rptr += 12; /* Skip src */
845: bcopy(bp->rptr, (caddr_t)&td->ietfd_type, 2); /* Type */
846: bp->rptr += 2; /* Skip src */
847: cnt -= sizeof(struct etherpup);
848:
849: /* Setup the data */
850: if (cnt > 1500) /* test for too large packets */
851: cnt = 1500;
852: count = cnt;
853: to = es->es_tbuffer[bufnum];
854: while (cnt > 0 && bp != 0) {
855: i = bp->wptr - bp->rptr;
856: bcopy(bp->rptr, to, i);
857: cnt -= i;
858: to += i;
859: nbp = bp->next;
860: freeb(bp);
861: bp = nbp;
862: }
863:
864: if (count < 46) /* test for small packets */
865: count = 46;
866:
867: /* flush remaining buffers, if any (too large packet: count > 1500) */
868: while (bp) {
869: nbp = bp->next;
870: freeb(bp);
871: bp = nbp;
872: }
873:
874: /* Setup the buffer descriptor */
875: tbd->ietbd_eof = 1;
876: tbd->ietbd_next = 0;
877: tbd->ietbd_buf = to_ieaddr(es, es->es_tbuffer[bufnum]);
878: tbd->ietbd_cntlo = count & 0xFF;
879: tbd->ietbd_cnthi = count >> 8;
880: td->ietfd_tbd = to_ieoff(es, (caddr_t)tbd);
881: td->ietfd_cmd = IE_TRANSMIT;
882: iedocb(es, (struct iecb *)td);
883: out:
884: iecustart(es);
885: return;
886: }
887:
888: /*
889: * Set the control block area size
890: */
891: iesetcbsize(es)
892: register struct ie_softc *es;
893: {
894: int tfds; /* number of tfd's */
895: int tfdsize; /* cbsize for each tfd */
896: int tbufsize; /* cbsize for each tbuf */
897: int rbufs; /* number of rbuf's in cb area */
898: int rbufsize; /* cbsize for each rbuf */
899: int rfds; /* number of rfd's */
900: int rfdsize; /* cbsize for each rfd */
901: int fixed; /* fixed overhead, including slop */
902:
903: fixed = sizeof (struct iescp) + sizeof (struct ieiscp)
904: + sizeof (struct iescb) + sizeof (struct ieconf)
905: + 100;
906: tfdsize = sizeof (struct ietfd) + sizeof (struct ietbd);
907: tbufsize = sizeof (struct ieipack);
908: rbufsize = sizeof (struct ieipack);
909: rfdsize = sizeof (struct ierfd) + sizeof (struct ierbd);
910:
911: switch (es->es_type) {
912: case IE_OB:
913: tfds = NTRANSBUF;
914: rbufs = (es->es_obmem - fixed - tfds * (tfdsize+tbufsize)) /
915: (rbufsize + rfdsize);
916: break;
917: case IE_MB:
918: tfds = 50; /* maximum if_snd */
919: /* each rbuf eats into a 2K section of vmemsize */
920: rbufs = min(NPOOL_RBD, (u_int)(es->es_vmemsize>>11));
921: break;
922: }
923: rfds = rbufs;
924:
925: es->es_cbsize = fixed
926: + tfds * tfdsize
927: + rfds * rfdsize;
928: }
929:
930: /*
931: * Called by ieinit to (allocate and re)initialize rmap's
932: * We need to be careful, since the board may be in use
933: * (ieipacks loaned out, pages swapped)
934: */
935: iedomaps(es)
936: register struct ie_softc *es;
937: {
938: int unit = es - ie_softc;
939:
940: iesetcbsize(es);
941: bzero((caddr_t)iecbmap[unit], sizeof iecbmap[unit]);
942: bzero((caddr_t)iememmap[unit], sizeof iememmap[unit]);
943: es->es_cbhead = NULL;
944: es->es_cbcbusy = NULL;
945: iecbcinit(es);
946:
947: if (es->es_type == IE_OB) {
948: int memall();
949: caddr_t va;
950:
951: if (es->es_base == 0) {
952: va = wmemall(memall, es->es_obmem);
953: if (va == 0)
954: panic("ieattach: no memory");
955: es->es_base = va;
956: }
957: va = es->es_base;
958: es->es_cbmap = &iecbmap[unit][0];
959: es->es_memmap = es->es_cbmap;
960: rminit(es->es_cbmap, (long)es->es_obmem,
961: (long)es->es_base, "iecb", IEMAPSIZ);
962: es->es_memspace = (caddr_t)KERNELBASE;
963: #ifdef sun3
964: /* use the page already set up by the prom monitor */
965: es->es_scp = (struct iescp *)(IESCPADDR+es->es_memspace);
966: #else
967: /*
968: * Remap the [preallocated] virtual page containing
969: * the SCP to make it point to the same physical
970: * location as va, so that we can muck with the
971: * control blocks using the address returned from
972: * memall, and the chip can locate the scp at its
973: * fixed address
974: * Cache note: since we can not, in general, enforce
975: * the cache antialiasing separation requirement, we
976: * would need to avoid caching this physical page
977: */
978: {
979: struct pte dummypte; /* for mapin to write on */
980: int paddr = getkpgmap(va) & PG_PFNUM;
981:
982: mapin(&dummypte, (u_int)btop(IESCPADDR+
983: es->es_memspace), (u_int)paddr, 1, PG_V | PG_KW);
984: es->es_scp = (struct iescp *)escbpin(es,
985: (long)sizeof (struct iescp),
986: (long)es->es_base + (IESCPADDR & PGOFSET));
987: }
988: #endif sun3
989: } else { /* IE_MB */
990: register struct mie_device *mie = es->es_mie;
991: struct miepg *pg;
992: short *ap;
993: int i;
994: int a, vaddr, paddr;
995: int firsttime = es->es_memspace == 0;
996:
997: if (firsttime) {
998: if ((a = rmalloc(kernelmap,(long)btoc(es->es_vmemsize)))
999: == 0) {
1000: printf("ie%d: no kernelmap for ie memory\n",
1001: unit);
1002: panic("iedomaps");
1003: }
1004: es->es_memspace = (caddr_t)kmxtob(a);
1005: }
1006: vaddr = (int)es->es_memspace;
1007: a = btokmx((struct pte *)vaddr);
1008: /* board's mem boundary to byte addr */
1009: paddr = mie->mie_mbmhi << 16;
1010: /* preserve pagetype bits and which megabyte its in (for VME) */
1011: es->es_paddr = getkpgmap((caddr_t)mie) & PG_PFNUM;
1012: es->es_paddr &= ~(0x100000/NBPG -1);
1013: es->es_paddr |= btop(paddr);
1014: mapin(&Usrptmap[a], (u_int)btop(vaddr), (u_int)es->es_paddr,
1015: (int)btoc(es->es_vmemsize), PG_V | PG_KW);
1016:
1017: /* clear the board unless in use */
1018: if (firsttime) {
1019: ap = (short *)mie->mie_pgmap;
1020: for (i=0; i<IEVVSIZ; i++) /* clears mp_p2mem */
1021: *ap++ = 0;
1022: for (i=0; i<IEPMEMSIZ/IEPAGSIZ; i++) {
1023: mie->mie_pgmap[0].mp_pfnum = i;
1024: bzero(es->es_memspace, IEPAGSIZ);
1025: }
1026: pg = &mie->mie_pgmap[0];
1027: for (i=0; i<es->es_vmemsize/IEPAGSIZ; i++) {
1028: pg->mp_swab = 1;
1029: pg->mp_pfnum = i;
1030: pg++;
1031: }
1032:
1033: /* use last onboard ie page for chip init */
1034: /* (no need to reclaim, since beyond vmemsize) */
1035: pg = &mie->mie_pgmap[IEVVSIZ-1];
1036: pg->mp_swab = 1;
1037: pg->mp_pfnum = 0;
1038:
1039: /* patch potential powerup parity problem */
1040: mie->mie_peack = 1;
1041: }
1042:
1043: es->es_base = es->es_memspace;
1044: es->es_cbmap = &iecbmap[unit][0];
1045: rminit(es->es_cbmap, (long)es->es_cbsize,
1046: (long)es->es_base, "iecb", IEMAPSIZ);
1047: es->es_scp = (struct iescp *)escbpin(es,
1048: (long)sizeof (struct iescp),
1049: (long)es->es_base + (IESCPADDR & (IEPAGSIZ-1)));
1050: es->es_memmap = &iememmap[unit][0];
1051: es->es_pgmap = &iepgmap[unit][0];
1052: /*
1053: * if we have enough memory, create a page pool which
1054: * can manipulated via if_memmap, say by ND
1055: */
1056: if (es->es_vmemsize == 256*1024) {
1057: rminit(es->es_memmap, (long)(128*1024-es->es_cbsize),
1058: (long)(es->es_memspace+es->es_cbsize),
1059: "iemem", IEMAPSIZ);
1060: if (firsttime)
1061: rminit(es->es_pgmap, (long)(128*1024),
1062: (long)(es->es_memspace+128*1024),
1063: "iepg", IEMAPSIZ);
1064: } else {
1065: rminit(es->es_memmap,
1066: (long)(es->es_vmemsize-es->es_cbsize),
1067: (long)(es->es_memspace+es->es_cbsize),
1068: "iemem", IEMAPSIZ);
1069: rminit(es->es_pgmap, (long)0, (long)0,
1070: "iepg", IEMAPSIZ);
1071: }
1072: }
1073: }
1074:
1075: /*
1076: * Basic 82586 initialization
1077: */
1078: int
1079: iechipinit(es)
1080: register struct ie_softc *es;
1081: {
1082: int unit = es - ie_softc;
1083: struct ieiscp *iscp;
1084: struct iescb *scb;
1085: struct iecb *cb;
1086: struct ieconf *ic;
1087: int ok = 0;
1088: int gotintr;
1089: int i;
1090: #ifdef notdef
1091: struct ietdr *tdr;
1092: #endif
1093:
1094: if (es->es_scp == 0) {
1095: printf("ie%d: scp alloc failed\n", unit);
1096: goto exit;
1097: }
1098: iscp = escballoc(es, struct ieiscp, 0);
1099: if (iscp == 0) {
1100: printf("ie%d: iscp alloc failed\n", unit);
1101: goto exit;
1102: }
1103: scb = escballoc(es, struct iescb, 0);
1104: if (scb == 0) {
1105: printf("ie%d: scb alloc failed\n", unit);
1106: goto exit;
1107: }
1108: es->es_scb = scb;
1109:
1110: reset:
1111: bzero((caddr_t)es->es_scp, sizeof (struct iescp));
1112: es->es_scp->ie_iscp = to_ieaddr(es, (caddr_t)iscp);
1113: bzero((caddr_t)iscp, sizeof (struct ieiscp));
1114: iscp->ie_busy = 1;
1115: iscp->ie_cbbase = to_ieaddr(es, es->es_base);
1116: iscp->ie_scb = to_ieoff(es, (caddr_t)scb);
1117: bzero((caddr_t)scb, sizeof (struct iescb));
1118: scb->ie_magic = IEMAGIC;
1119: /*
1120: * Hardware reset the chip. We make the interval from
1121: * reset to initial channel attention as small as reasonable
1122: * to reduce the risk of scribbling chips getting us.
1123: */
1124: switch (es->es_type) {
1125: case IE_MB:
1126: /* hardware reset already occurred in iechipreset */
1127: break;
1128:
1129: case IE_OB:
1130: es->es_obie->obie_noreset = 1;
1131: DELAY(IEKLUDGE); /* REQUIRED */
1132: break;
1133: }
1134: ieca(es);
1135: CDELAY(!iscp->ie_busy, IEDELAY); /* ensure chip eats iscp */
1136: CDELAY(scb->ie_cnr, IEDELAY); /* ensure scb updated too */
1137: gotintr = iewaitintr(es); /* wait for interrupt */
1138: if (iscp->ie_busy || !scb->ie_cnr || !gotintr) {
1139: printf("ie%d: init failed:%s%s%s\n", unit,
1140: iscp->ie_busy?" iscp busy":"",
1141: !scb->ie_cnr ?" no cnr":"",
1142: !gotintr ?" no intr":"");
1143: goto exit;
1144: }
1145: if (scb->ie_cus != IECUS_IDLE ) {
1146: printf("ie%d: cus not idle after reset\n", unit);
1147: iechipreset(es);
1148: goto reset;
1149: }
1150:
1151: cb = escballoc(es, struct iecb, 1);
1152: if (cb == NULL) {
1153: printf("ie%d: cb alloc failed\n", unit);
1154: goto exit;
1155: }
1156: bzero((caddr_t)cb, sizeof (struct iecb));
1157: cb->ie_cmd = IE_DIAGNOSE;
1158: iesimple(es, cb);
1159: if (!cb->ie_ok) {
1160: printf("ie%d: Intel 82586 failed diagnostics\n", unit);
1161: escbfree(es, cb);
1162: goto exit;
1163: }
1164: escbfree(es, cb);
1165: #ifdef notdef
1166: /* skip, since hardware requires quiet net to work */
1167: tdr = escballoc(es, struct ietdr, 1);
1168: if (tdr == NULL) {
1169: printf("ie%d: tdr alloc failed\n", unit);
1170: goto exit;
1171: }
1172: bzero((caddr_t)tdr, sizeof (struct ietdr));
1173: tdr->ietdr_cb.ie_cmd = IE_TDR;
1174: iesimple(es, &tdr->ietdr_cb);
1175: if (!tdr->ietdr_ok) {
1176: #define TDRCONST 12 /* approx 0.77c/10Mhz */
1177: int dist = (tdr->ietdr_timhi<<8)+tdr->ietdr_timlo;
1178: if (dist != 0x7FF)
1179: printf("ie%d: link not OK - distance = ~%dm\n",
1180: unit, TDRCONST*dist);
1181: else
1182: printf("ie%d: link not OK\n", unit);
1183: escbfree(es, tdr);
1184: goto exit;
1185: }
1186: if (tdr->ietdr_xcvr) printf("ie%d: transceiver bad\n", unit);
1187: if (tdr->ietdr_open) printf("ie%d: net not terminated\n", unit);
1188: if (tdr->ietdr_shrt) printf("ie%d: net shorted\n", unit);
1189: escbfree(es, tdr);
1190: #endif notdef
1191: ic = escballoc(es, struct ieconf, 1);
1192: if (ic == NULL) {
1193: printf("ie%d: ic alloc failed\n", unit);
1194: goto exit;
1195: }
1196: iedefaultconf(ic);
1197: iesimple(es, &ic->ieconf_cb);
1198: escbfree(es, ic);
1199: for (i = 0; i < NTRANSBUF; i++) {
1200: if ((es->es_tfd[i] = escballoc(es, struct ietfd, 0)) == NULL) {
1201: printf("ie%d: tfd alloc failed\n", unit);
1202: goto exit;
1203: }
1204: if ((es->es_tbd[i] = escballoc(es, struct ietbd, 0)) == NULL) {
1205: printf("ie%d: tbd alloc failed\n", unit);
1206: goto exit;
1207: }
1208: if ((es->es_tbuffer[i]=(caddr_t)esmemalloc(es, 1500)) ==NULL) {
1209: printf("ie%d: tbuffer alloc failed\n", unit);
1210: goto exit;
1211: }
1212: es->es_tfree |= (1 << i);
1213: }
1214: ok = 1;
1215: exit:
1216: return (ok);
1217: }
1218:
1219: /*
1220: * called by ierustart to create the receiver buffer list
1221: */
1222: iegetrbufs(es)
1223: register struct ie_softc *es;
1224: {
1225: caddr_t addr;
1226: int count, avail;
1227: register int page, last;
1228: register struct ieipack *iep;
1229:
1230: es->es_iepavail = NULL;
1231: if (es->es_type == IE_OB) {
1232: last = (es->es_obmem-es->es_cbsize) /
1233: (sizeof (struct ieipack)) - NTRANSBUF;
1234: for (count = 0; count < last; count++) {
1235: iep = (struct ieipack *)esmemalloc(es,
1236: sizeof (struct ieipack));
1237: if (iep == 0)
1238: break;
1239: iep->iep_es = es;
1240: iep->iep_next = es->es_iepavail;
1241: es->es_iepavail = iep;
1242: }
1243: avail = count;
1244: } else { /* IE_MB */
1245: count = NPOOL_RBD;
1246: /* XXX not really, since there could be page pool */
1247: last = es->es_vmemsize >> IEPAGSHIFT;
1248: /* 2 pages for xmit (vice receive) buffer */
1249: page = iepages(es->es_cbsize) + 2;
1250: for (; count > 0 && page < last; page++) {
1251: addr = es->es_memspace + page*IEPAGSIZ;
1252: addr += IEPAGSIZ - (IPACKOVH + OPTHDRSIZ);
1253: if (!esmempin(es, sizeof (struct ieipack), (int)addr))
1254: continue;
1255: count--;
1256: iep = (struct ieipack *)addr;
1257: iep->iep_es = es;
1258: iep->iep_next = es->es_iepavail;
1259: es->es_iepavail = iep;
1260: }
1261: avail = NPOOL_RBD - count;
1262: }
1263:
1264: return (avail);
1265: }
1266:
1267: /*
1268: * Initialize and start the Receive Unit
1269: */
1270: ierustart(es)
1271: register struct ie_softc *es;
1272: {
1273: int unit = es - ie_softc;
1274: register struct ierbd *rbd;
1275: register struct ierfd *rfd;
1276: register struct iescb *scb;
1277: register struct ieipack *iep;
1278: register int i, nrfd, ninit_rbd;
1279:
1280: ninit_rbd = iegetrbufs(es);
1281: es->es_rbdhead = NULL;
1282: for (i = 0; i < ninit_rbd; i++) {
1283: if ((iep = es->es_iepavail) == NULL)
1284: break;
1285: rbd = escballoc(es, struct ierbd, 0);
1286: if (rbd == NULL)
1287: break;
1288: es->es_iepavail = iep->iep_next;
1289: *(short *)rbd = 0;
1290: if (es->es_rbdhead) {
1291: rbd->ierbd_next = to_ieoff(es, (caddr_t)es->es_rbdhead);
1292: rbd->ierbd_el = 0;
1293: } else {
1294: es->es_rbdtail = rbd;
1295: rbd->ierbd_next = 0;
1296: rbd->ierbd_el = 1;
1297: }
1298: es->es_rbdhead = rbd;
1299: rbd->ierbd_buf = to_ieaddr(es, iep->iep_data);
1300: rbd->ierbd_sizehi = 1500 >> 8;
1301: rbd->ierbd_sizelo = 1500 & 0xFF;
1302: rbd->ierbd_iep = iep;
1303: }
1304: /*
1305: * We allocate one fewer RFD than RBD to
1306: * avoid a suspected microcode bug in the chip
1307: */
1308: nrfd = i-1;
1309: es->es_rbdtail->ierbd_next = to_ieoff(es, (caddr_t)es->es_rbdhead);
1310: es->es_rfdhead = NULL;
1311: for (i=0; i<nrfd; i++) {
1312: rfd = escballoc(es, struct ierfd, 0);
1313: if (rfd == NULL) {
1314: break;
1315: }
1316: *(short *)rfd = 0;
1317: if (es->es_rfdhead) {
1318: rfd->ierfd_next = to_ieoff(es, (caddr_t)es->es_rfdhead);
1319: rfd->ierfd_el = 0;
1320: } else {
1321: es->es_rfdtail = rfd;
1322: rfd->ierfd_next = 0;
1323: rfd->ierfd_el = 1;
1324: }
1325: es->es_rfdhead = rfd;
1326: rfd->ierfd_susp = 0;
1327: rfd->ierfd_rbd = IENORBD;
1328: }
1329: if (i != nrfd)
1330: printf("ie%d: fewer RFD's were allocated than expected\n",
1331: unit);
1332: es->es_rfdtail->ierfd_next = to_ieoff(es, (caddr_t)es->es_rfdhead);
1333: rfd = es->es_rfdhead;
1334: rfd->ierfd_rbd = to_ieoff(es, (caddr_t)rbd);
1335: scb = es->es_scb;
1336: if (scb->ie_rus != IERUS_IDLE) {
1337: printf("ie%d: RU not idle??\n", unit);
1338: iestat(es);
1339: iechkcca(scb);
1340: scb->ie_cmd = IECMD_RU_ABORT;
1341: ieca(es);
1342: }
1343: iechkcca(scb);
1344: scb->ie_rfa = to_ieoff(es, (caddr_t)rfd);
1345: scb->ie_cmd = IECMD_RU_START;
1346: ieca(es);
1347: CDELAY(scb->ie_rus == IERUS_READY, IEDELAY);
1348: if (scb->ie_rus != IERUS_READY)
1349: printf("ie%d: RU did not become ready\n", unit);
1350: }
1351:
1352: /*
1353: * Put a CB on the CBL
1354: */
1355: iedocb(es, cb)
1356: register struct ie_softc *es;
1357: register struct iecb *cb;
1358: {
1359: int s = splie();
1360:
1361: *(short *)cb = 0; /* clear status bits */
1362: cb->ie_susp = 0; /* clear suspend bit */
1363: cb->ie_el = 1; /* will be reset in iecustart */
1364: cb->ie_intr = 1;
1365: cb->ie_next = 0;
1366: if (es->es_cbhead) {
1367: es->es_cbtail->ie_next = to_ieoff(es, (caddr_t)cb);
1368: es->es_cbtail = cb;
1369: } else {
1370: es->es_cbhead = es->es_cbtail = cb;
1371: }
1372: (void) splx(s);
1373: }
1374:
1375: /*
1376: * Process completed CBs, reclaiming specified storage.
1377: * Allocator is responsible for reclaiming other storage.
1378: * Called by iecustart at splie.
1379: * Called by iecbdone at splie or hardware level 3.
1380: */
1381: iecuclean(es)
1382: register struct ie_softc *es;
1383: {
1384: register struct iecb *cb;
1385:
1386: while ((cb = es->es_cbhead) && cb->ie_done) {
1387: if (cb->ie_next)
1388: es->es_cbhead = (struct iecb *)from_ieoff(es,
1389: (ieoff_t)cb->ie_next);
1390: else
1391: es->es_cbhead = NULL;
1392: switch (cb->ie_cmd) {
1393: case IE_TRANSMIT:
1394: iexmitdone(es, (struct ietfd *)cb);
1395: break;
1396: case IE_NOP:
1397: untimeout(iebark, (caddr_t)es);
1398: escbfree(es, cb);
1399: break;
1400: default:
1401: if (!es->es_simple)
1402: printf("ie%d: unknown cmd %x done\n",
1403: es-ie_softc, cb->ie_cmd);
1404: break;
1405: }
1406: }
1407: }
1408:
1409: /*
1410: * Start the CU with the current CBL
1411: */
1412: iecustart(es)
1413: register struct ie_softc *es;
1414: {
1415: register struct iecb *cb;
1416: register struct iescb *scb = es->es_scb;
1417: int s = splie();
1418:
1419: iechkcca(scb);
1420: if (es->es_cbhead == NULL ||
1421: scb->ie_cus == IECUS_READY) { /* still going */
1422: (void) splx(s);
1423: return;
1424: }
1425: iecuclean(es);
1426: /* link remaining CBs into continuous list */
1427: if ((cb = es->es_cbhead) == NULL) {
1428: (void) splx(s);
1429: return;
1430: }
1431: while (cb && cb->ie_next) {
1432: cb->ie_el = 0;
1433: cb = (struct iecb *)from_ieoff(es, (ieoff_t)cb->ie_next);
1434: }
1435: /* start CU */
1436: scb->ie_cbl = to_ieoff(es, (caddr_t)es->es_cbhead);
1437: scb->ie_cmd = IECMD_CU_START;
1438: ieca(es);
1439: (void) splx(s);
1440: }
1441:
1442: /*
1443: * Clean up and restart the CBs on the CBL
1444: * Called by ieintr at hardware level 3.
1445: * Called by iesimple at splie.
1446: */
1447: iecbdone(es)
1448: register struct ie_softc *es;
1449: {
1450:
1451: iecuclean(es);
1452: /* generate more CBs */
1453: iestartout(es - ie_softc);
1454: }
1455:
1456: /*
1457: * Do the command simply.
1458: * Attempted sleep/wakeup calls, but it refused to work.
1459: */
1460: iesimple(es, cb)
1461: register struct ie_softc *es;
1462: register struct iecb *cb;
1463: {
1464: register struct iescb *scb = es->es_scb;
1465: int s, cmd = 0;
1466:
1467: es->es_simple++;
1468: iedocb(es, cb);
1469: iecustart(es);
1470: CDELAY(cb->ie_done, IEDELAY);
1471: if (!cb->ie_done) {
1472: iestat(es);
1473: panic("iesimple");
1474: }
1475: s = splie();
1476: iechkcca(scb);
1477: if (scb->ie_cx)
1478: cmd |= IECMD_ACK_CX;
1479: if (scb->ie_cnr)
1480: cmd |= IECMD_ACK_CNR;
1481: scb->ie_cmd = cmd;
1482: ieca(es);
1483: if (cmd & (IECMD_ACK_CNR|IECMD_ACK_CX))
1484: iecbdone(es);
1485: es->es_simple--;
1486: (void) splx(s);
1487: }
1488:
1489: /*
1490: * Return chip's idea of given address or 0 if not chip accessible
1491: */
1492: ieaddr(es, cp)
1493: register struct ie_softc *es;
1494: caddr_t cp;
1495: {
1496: int pte;
1497:
1498: if (es->es_type == IE_OB) {
1499: /* onboard ie may only reference obmem */
1500: if ((getkpgmap(cp) & PGT_MASK) != PGT_OBMEM)
1501: cp = (caddr_t)0;
1502: #ifdef sun3
1503: else if (cp < es->es_memspace)
1504: cp = (caddr_t)0;
1505: else
1506: cp -= (u_long)es->es_memspace;
1507: #endif sun3
1508: return ((int)cp);
1509: }
1510: pte = getkpgmap(cp) & PG_PFNUM;
1511: if (pte >= es->es_paddr && pte < es->es_paddr + btoc(es->es_vmemsize))
1512: return ((pte - es->es_paddr) << BSHIFT(0)) + ((int)cp & CLOFSET);
1513: return (0);
1514: }
1515:
1516: /*
1517: * Check Control Command Acceptance by 82586
1518: */
1519: iechkcca(scb)
1520: register struct iescb *scb;
1521: {
1522: register i;
1523:
1524: for (i=0; i < IEDELAY; i++) {
1525: if (scb->ie_magic != IEMAGIC)
1526: panic("ie: scb overwritten");
1527: if (scb->ie_cmd == 0)
1528: break;
1529: }
1530: if (i >= IEDELAY) {
1531: printf("ie: cmd not accepted\n");
1532: panic("iechkcca");
1533: }
1534: }
1535:
1536: /*
1537: * The control block caching code to bypass rmalloc/rmfree.
1538: * It also allows us to check allocated lengths, as well
1539: * as aiding instrumentation for verification and tuning.
1540: * We have two sizes, small and large.
1541: * If the request exceeds the small threshold, we allocate
1542: * the larger block.
1543: */
1544:
1545: #define lo es->es_cbc_lo
1546: #define hi es->es_cbc_hi
1547: #define cache es->es_cbcache
1548: #define ovfl es->es_cbc_ovfl
1549: #define small iecbcsmall
1550: #define large iecbclarge
1551: #define head es->es_cbchain.next
1552: #define chain es->es_cbchain
1553:
1554: /*
1555: * Initialize the control block cache
1556: */
1557: iecbcinit(es)
1558: register struct ie_softc *es;
1559: {
1560: if (es->es_cbcbusy)
1561: iecbcflush(es);
1562: lo = -1;
1563: hi = CBCACHESIZ;
1564: small = sizeof (struct ietbd);
1565: large = sizeof (struct ietfd);
1566: }
1567:
1568: /*
1569: * cached is a flag used to indicate that the block must be
1570: * cached, as it will be freed (for reallocation.)
1571: */
1572: long
1573: escbget(es, len0, cached)
1574: register struct ie_softc *es;
1575: int len0;
1576: int cached;
1577: {
1578: long result;
1579: int len = rndtoeven(len0);
1580: if (!cached)
1581: result = (rmalloc(es->es_cbmap, (long)len));
1582: else if (len <= small)
1583: if (lo > -1)
1584: result = (cache[lo--]);
1585: else
1586: result = (rmalloc(es->es_cbmap, (long)small));
1587: else if (len <= large)
1588: if (hi < CBCACHESIZ)
1589: result = (cache[hi++]);
1590: else
1591: result = (rmalloc(es->es_cbmap, (long)large));
1592: else
1593: panic ("escbget"); /* len too large */
1594:
1595: if (result == 0 && es->es_cbcbusy) {
1596: iecbcflush(es);
1597: result = escbget(es, len0, cached);
1598: }
1599: return (result);
1600: }
1601:
1602: /*
1603: * flush the cb cache
1604: */
1605: iecbcflush(es)
1606: struct ie_softc *es;
1607: {
1608: printf("WARNING: ie%d: flushing cb cache\n", es - ie_softc);
1609: while (lo > -1)
1610: rmfree(es->es_cbmap, (long)small, (long)cache[lo--]);
1611: while (hi < CBCACHESIZ)
1612: rmfree(es->es_cbmap, (long)large, (long)cache[hi++]);
1613: es->es_cbcbusy = 0;
1614: }
1615:
1616: long
1617: escbput(es, len, ptr)
1618: register struct ie_softc *es;
1619: int len;
1620: long ptr;
1621: {
1622: int overflow = 0;
1623:
1624: es->es_cbcbusy = 1;
1625: len = rndtoeven(len);
1626: if (len <= small)
1627: if (lo < hi - 1)
1628: cache[++lo] = ptr;
1629: else {
1630: overflow++;
1631: rmfree(es->es_cbmap, (long)small, (long)ptr);
1632: }
1633: else if (len <= large)
1634: if (hi > lo + 1)
1635: cache[--hi] = ptr;
1636: else {
1637: overflow++;
1638: rmfree(es->es_cbmap, (long)large, (long)ptr);
1639: }
1640: else
1641: panic("escbput");
1642:
1643: if (overflow) {
1644: ovfl++;
1645: if ((ovfl & OVFLWARNMASK) == 0) {
1646: ovfl = 0;
1647: printf("ie%d: cache overflowed\n", es - ie_softc);
1648: }
1649: }
1650: }
1651:
1652: #undef lo
1653: #undef hi
1654: #undef cache
1655: #undef ovfl
1656: #undef small
1657: #undef large
1658:
1659: int iefifolim = 12;
1660: /*
1661: * Set default configuration parameters
1662: */
1663: iedefaultconf(ic)
1664: register struct ieconf *ic;
1665: {
1666: bzero((caddr_t)ic, sizeof (struct ieconf));
1667: ic->ieconf_cb.ie_cmd = IE_CONFIG;
1668: ic->ieconf_bytes = 12;
1669: ic->ieconf_fifolim = iefifolim;
1670: ic->ieconf_pream = 2; /* 8 byte preamble */
1671: ic->ieconf_alen = 6;
1672: ic->ieconf_acloc = 0;
1673: ic->ieconf_space = 96;
1674: ic->ieconf_slttmh = 512 >> 8;
1675: ic->ieconf_minfrm = 64;
1676: ic->ieconf_retry = 15;
1677: ic->ieconf_crfilt = 3;
1678: }
1679:
1680: iestat(es)
1681: struct ie_softc *es;
1682: {
1683: register struct iescb *scb = es->es_scb;
1684: static char *cus[] = { "idle", "suspended", "ready", "<3>",
1685: "<4>", "<5>", "<6>", "<7>" };
1686: static char *rus[] = { "idle", "suspended", "no resources",
1687: "<3>", "ready", "<5>", "<6>", "<7>" };
1688:
1689: printf("ie%d: scb: ", es - ie_softc);
1690: if (scb->ie_cx) printf("cx ");
1691: if (scb->ie_fr) printf("fr ");
1692: if (scb->ie_cnr) printf("cnr ");
1693: if (scb->ie_rnr) printf("rnr ");
1694: printf("cus=%s ", cus[scb->ie_cus]);
1695: printf("rus=%s\n", rus[scb->ie_rus]);
1696: printf("cbl=0x%x rfa=0x%x crc=0x%x aln=0x%x rsc=0x%x ovrn=0x%x\n",
1697: scb->ie_cbl, scb->ie_rfa,
1698: scb->ie_crcerrs, scb->ie_alnerrs, scb->ie_rscerrs,
1699: scb->ie_ovrnerrs);
1700: if (scb->ie_cmd) printf("cmd=0x%x\n", scb->ie_cmd & 0xFFFF);
1701: }
1702:
1703: /*
1704: * Parity error! Scan entire memory for errors
1705: */
1706: ieparity(es)
1707: register struct ie_softc *es;
1708: {
1709: register struct mie_device *mie = es->es_mie;
1710: register u_short *s, *e, x;
1711:
1712: printf("ie%d: parity error src=%d byte=%d addr=%x\n", es-ie_softc,
1713: mie->mie_pesrc, mie->mie_pebyte, mie->mie_erraddr);
1714: mie->mie_peack = 1;
1715: s = (u_short *)es->es_memspace;
1716: e = (u_short *)(es->es_memspace + es->es_vmemsize);
1717: printf("scanning...\n");
1718: while (s < e) {
1719: x = *s;
1720: #ifdef lint
1721: x = x;
1722: #endif
1723: if (mie->mie_pe) {
1724: printf("off=%x src=%d byte=%d addr=%x\n",
1725: (int)s - (int)es->es_memspace,
1726: mie->mie_pesrc, mie->mie_pebyte,
1727: mie->mie_erraddr);
1728: mie->mie_peack = 1;
1729: }
1730: s++;
1731: }
1732: printf("done\n");
1733: }
1734:
1735: /*
1736: * Activate the channel attention line
1737: */
1738: ieca(es)
1739: register struct ie_softc *es;
1740: {
1741: if (es->es_type == IE_MB) {
1742: es->es_mie->mie_ca = 1;
1743: es->es_mie->mie_ca = 0;
1744: } else {
1745: es->es_obie->obie_ca = 1;
1746: es->es_obie->obie_ca = 0;
1747: }
1748: }
1749:
1750: /*
1751: * Wait for an interrupt and relay results
1752: */
1753: int
1754: iewaitintr(es)
1755: register struct ie_softc *es;
1756: {
1757: register struct obie_device *obie = es->es_obie;
1758: register struct mie_device *mie = es->es_mie;
1759: int ok;
1760:
1761: switch (es->es_type) {
1762: case IE_OB:
1763: CDELAY(obie->obie_intr, IEDELAY);
1764: ok = obie->obie_intr;
1765: break;
1766:
1767: case IE_MB:
1768: CDELAY(mie->mie_intr, IEDELAY);
1769: ok = mie->mie_intr;
1770: break;
1771: }
1772: return (ok);
1773: }
1774:
1775: /*
1776: * Cut the chip out of the loop and halt it by starting the reset cycle.
1777: * For IE_MB, we must enable pagemaps, hence we complete the reset cycle.
1778: */
1779: iechipreset(es)
1780: register struct ie_softc *es;
1781: {
1782:
1783: switch (es->es_type) {
1784: case IE_MB:
1785: es->es_mie->mie_reset = 1;
1786: DELAY(IEKLUDGE); /* REQUIRED */
1787: *(char *)&es->es_mie->mie_status = 0; /* power on reset */
1788: break;
1789:
1790: case IE_OB:
1791: *(char *)es->es_obie = 0; /* power on reset */
1792: break;
1793:
1794: default:
1795: panic("iechipreset");
1796: }
1797: }
1798:
1799: /*
1800: * Splice the chip into the loop
1801: */
1802: iesplice(es)
1803: register struct ie_softc *es;
1804: {
1805: switch (es->es_type) {
1806: case IE_MB:
1807: es->es_mie->mie_ie = 1; /* enable chip interrupts */
1808: es->es_mie->mie_pie = 1; /* enable parity interrupts */
1809: es->es_mie->mie_noloop = 1; /* enable cable */
1810: break;
1811:
1812: case IE_OB:
1813: es->es_obie->obie_ie = 1; /* enable interrupts */
1814: es->es_obie->obie_noloop = 1; /* enable cable */
1815: break;
1816: }
1817: }
1818:
1819: /*
1820: * Change 68000 address to Intel 24-bit address.
1821: * We take advantage of the fact that all 82586 blocks with 24-bit
1822: * addresses have an adjacent unused 8-bit field, and store 32 bits.
1823: */
1824: ieaddr_t
1825: to_ieaddr(es, cp)
1826: struct ie_softc *es;
1827: caddr_t cp;
1828: {
1829: union {
1830: int n;
1831: char c[4];
1832: } a, b;
1833:
1834: a.n = ieaddr(es, cp); /* necessary for double mapping */
1835: b.c[0] = a.c[3];
1836: b.c[1] = a.c[2];
1837: b.c[2] = a.c[1];
1838: b.c[3] = 0;
1839: return (b.n);
1840: }
1841:
1842: caddr_t
1843: from_ieaddr(es, n)
1844: struct ie_softc *es;
1845: ieaddr_t n;
1846: {
1847: union {
1848: int n;
1849: char c[4];
1850: } a, b;
1851:
1852: a.n = n;
1853: b.c[0] = 0;
1854: b.c[1] = a.c[2];
1855: b.c[2] = a.c[1];
1856: b.c[3] = a.c[0];
1857: return (es->es_memspace + b.n);
1858: }
1859:
1860: ieoff_t
1861: to_ieoff(es, addr)
1862: register struct ie_softc *es;
1863: caddr_t addr;
1864: {
1865: union {
1866: ieoff_t s;
1867: char c[2];
1868: } a, b;
1869:
1870: a.s = (ieoff_t)(addr - es->es_base);
1871: b.c[0] = a.c[1];
1872: b.c[1] = a.c[0];
1873: return (b.s);
1874: }
1875:
1876: caddr_t
1877: from_ieoff(es, off)
1878: register struct ie_softc *es;
1879: ieoff_t off;
1880: {
1881: union {
1882: ieoff_t s;
1883: char c[2];
1884: } a, b;
1885:
1886: a.s = off;
1887: b.c[0] = a.c[1];
1888: b.c[1] = a.c[0];
1889: return (es->es_base + b.s);
1890: }
1891:
1892: ieint_t
1893: to_ieint(n)
1894: ieint_t n;
1895: {
1896: union {
1897: ieint_t s;
1898: char c[2];
1899: } a, b;
1900:
1901: a.s = n;
1902: b.c[0] = a.c[1];
1903: b.c[1] = a.c[0];
1904: return (b.s);
1905: }
1906: #endif NIE > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.