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