|
|
1.1 root 1: #include "../chunix/chsys.h"
2: #include "../chunix/chconf.h"
3: #include "../chaos/chaos.h"
4: #include "../chaos/address-res.h"
5:
6: #ifdef VMUNIX
7: #include "../h/buf.h"
8: #include "../h/ubavar.h"
9: #include "../h/pte.h"
10: #include "../h/ubareg.h"
11: #endif VMUNIX
12:
13: /*
14: * Chaos device driver for the interlan ethernet interface.
15: *
16: * This driver depends heavily on the fact that the device will
17: * interrupt exactly once per receive buffer and once per command
18: * regardless of how many times the CSR is read (and thus the
19: * DONE bits cleared).
20: * Until a lot of this chaos code is rewritten, it is too painful to DMA
21: * directly into a packet buffer since the buffers must be > 512 bytes, even
22: * for the smallest packet. Thus we just have fixed buffers, and copy the data out.
23: * For transmission, we do indeed DMA directly from packets.
24: * Note that for the VAX we permanently allocate a buffered data path for transmit,
25: * unless NOHOG is defined, in which case we allocate as needed.
26: * For receive, we use a direct data path and a permanently-mapped buffer.
27: *
28: * NOTE!!! The size of this structure must not be an even multiple of 8 !!!
29: * If it is then "buffer chaining" will occur!
30: */
31: union chilpkt {
32: struct il_stat ilp_stat;
33: struct {
34: struct il_rheader ilp_Rhdr;
35: union {
36: struct ar_packet ilp_Arpkt;
37: struct {
38: struct pkt_header ilp_Chhead;
39: char ilp_Chdata[CHMAXDATA];
40: } ilp_Chpkt;
41: } ilp_data;
42: char ilp_crc[4];
43: } ilp_edata;
44: };
45: #define ilp_arpkt ilp_edata.ilp_data.ilp_Arpkt
46: #define ilp_chhead ilp_edata.ilp_data.ilp_Chpkt.ilp_Chhead
47: #define ilp_chdata ilp_edata.ilp_data.ilp_Chpkt.ilp_Chdata
48: #define ilp_chpkt ilp_edata.ilp_data.ilp_Chpkt
49: #define ilp_rhdr ilp_edata.ilp_Rhdr
50: int chilstart(), chilreset();
51:
52: /*
53: #define DEBUG
54: */
55:
56: #ifdef DEBUG
57: #define IF_DEBUG(x) (x)
58: #else
59: #define IF_DEBUG(x)
60: #endif
61:
62: #define NOHOG /* Don't hog buffered data path (for xmit) */
63:
64: #define splIL() spl5()
65:
66: /*
67: * Address resolution data:
68: * This should move to an "address resolution" file when more than one
69: * Ethernet device is supported.
70: */
71: #define ETHER_BROADCAST {-1, -1, -1, -1, -1, -1}
72: u_char ether_broadcast[6] = ETHER_BROADCAST;
73: #define NPAIRS 20 /* how many addresses should we remember */
74: struct ar_pair {
75: chaddr arp_chaos;
76: u_char arp_ether[6];
77: long arp_time;
78: };
79: long arptime; /* LRU clock for ar_pair slots */
80:
81: /*
82: * Canned request packet we send out when we don't have the ethernet address
83: * of an outgoing packet.
84: */
85: struct chilapkt {
86: struct il_xheader ar_xhdr;
87: struct ar_packet ar_pkt;
88: };
89: /*
90: * Software state per interface.
91: */
92: struct chilsoft {
93: char il_unit;
94: #ifdef VMUNIX
95: char il_ubanum;
96: char il_rbdp;
97: char il_xbdp;
98: int il_ruba;
99: int il_xuba;
100: #endif
101: short il_oactive; /* is output active? */
102: short il_startrcv; /* hang receive next chance */
103: short il_scsr;
104: u_char il_enaddr[6]; /* board's ethernet address */
105: short il_doreply; /* Reply buffer full */
106: short il_replying; /* Reply buffer being transmitted */
107: struct ildevice *il_devaddr;
108: struct chxcvr il_xcvr;
109: struct ar_pair il_pairs[NPAIRS];
110: struct ar_pair *il_epairs;
111: struct il_xheader il_savex; /* Yick. */
112: union chilpkt il_rpkt; /* DMA input buffer */
113: struct chilapkt il_arrequest; /* Address request buffer */
114: struct chilapkt il_arreply; /* Address reply buffer */
115: } chilsoft[NCHIL];
116:
117: /*
118: * Error codes
119: */
120: char *ilerrs[] = {
121: "success", /* 0 */
122: "success with retries", /* 01 */
123: "illegal command", /* 02 */
124: "inappropriate command", /* 03 */
125: "failure", /* 04 */
126: "buffer size exceeded", /* 05 */
127: "frame too small", /* 06 */
128: 0, /* 07 */
129: "excessive collisions", /* 010 */
130: 0, /* 011 */
131: "buffer alignment error", /* 012 */
132: 0, /* 013 */
133: 0, /* 014 */
134: 0, /* 015 */
135: 0, /* 016 */
136: "non-existent memory" /* 017 */
137: };
138:
139: char *ildiag[] = {
140: "success", /* 0 */
141: "checksum error", /* 1 */
142: "NM10 dma error", /* 2 */
143: "transmitter error", /* 3 */
144: "receiver error", /* 4 */
145: "loopback failure", /* 5 */
146: };
147: long chillost;
148: long chilarrp;
149: long chilarls;
150: long chilxstat;
151: long chilrst;
152: long chilrin;
153: long chilcin;
154: long chilar;
155: long chilxrq;
156: long chilxrp;
157:
158: #ifdef VMUNIX
159:
160: /*
161: * This stuff should be elsewhere, but isn't right now.
162: */
163:
164: #ifdef VAX780
165: #define UBAPURGEBITS UBADPR_BNE
166: #else
167: #define UBAPURGEBITS (UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE)
168: #endif VAX780
169:
170: #define PURGEBDP(ubanum, bdpnum) \
171: uba_hd[ubanum].uh_uba->uba_dpr[bdpnum] |= UBAPURGEBITS
172:
173: /*
174: * Autoconfiguration support for VMUNIX
175: */
176: int chilprobe(), chilattach(), chilrint(), chilcint();
177: struct uba_device *chilinfo[NCHIL];
178: unsigned short chilstd[] = { 0 };
179: struct uba_driver childriver = { chilprobe, 0, chilattach, 0, chilstd, "chil", chilinfo };
180:
181: /*
182: * Do an OFFLINE command to cause an interrupt for the
183: * autoconfigure stuff.
184: */
185: chilprobe(reg)
186: caddr_t reg;
187: {
188: register int br, cvec; /* r11, r10 */
189: register struct ildevice *addr = (struct ildevice *)reg;
190: register int i;
191:
192: #ifdef lint
193: {
194: int j = 0;
195:
196: br = 0; cvec = br; br = cvec;
197: i = j; j = i;
198: chilrint(0); chilcint(0);
199: }
200: #endif
201: addr->il_csr = ILC_OFFLINE|IL_CIE;
202: DELAY(100000);
203: i = addr->il_csr; /* clear CDONE */
204: if (cvec > 0 && cvec != 0x200)
205: cvec -= 4;
206:
207: return (1);
208: }
209:
210: /*
211: * Attach interface
212: */
213: chilattach(ui)
214: register struct uba_device *ui;
215: {
216: chilsoft[ui->ui_unit].il_ubanum = ui->ui_ubanum;
217: chilsetup(ui->ui_unit, (struct ildevice *)ui->ui_addr);
218: }
219: #else VMUNIX
220: int chilndev = NCHIL;
221: int chiladdr[NCHIL] = { CHIL_ADDR };
222: #endif VMUNIX
223:
224: /*
225: * Do the run-time initialization of the given transceiver.
226: * Reception is not enabled.
227: */
228: chilsetup(unit, addr)
229: int unit;
230: register struct ildevice *addr;
231: {
232: register struct chilsoft *sp = &chilsoft[unit];
233: int s;
234:
235: sp->il_xcvr.xc_devaddr = (unsigned *)addr; /* This indicates attachment! */
236: sp->il_xcvr.xc_addr = 0; /* We don't know chaos addr yet */
237: sp->il_xcvr.xc_start = chilstart;
238: sp->il_xcvr.xc_reset = chilreset;
239: sp->il_xcvr.xc_ilinfo.il_soft = sp;
240: sp->il_epairs = &sp->il_pairs[NPAIRS];
241: sp->il_devaddr = addr;
242: sp->il_unit = unit;
243:
244: #ifdef VMUNIX
245:
246: #ifndef NOHOG
247: sp->il_xuba = uballoc(sp->il_ubanum, (caddr_t)&sp->il_rpkt,
248: sizeof(union chilpkt), UBA_CANTWAIT|UBA_NEEDBDP);
249: sp->il_xbdp = (sp->il_xuba >> 28) & 0x0f;
250: #endif not NOHOG
251:
252: sp->il_ruba = uballoc(sp->il_ubanum, (caddr_t)&sp->il_rpkt,
253: sizeof(union chilpkt), UBA_CANTWAIT);
254: sp->il_rbdp = (sp->il_ruba >> 28) & 0x0f;
255: #endif VMUNIX
256:
257: s = splIL();
258: ilbusywait(sp, ILC_RESET, 0); /* Initialize interface */
259: addr->il_bar = sp->il_ruba & 0xffff;
260: addr->il_bcr = sizeof(struct il_stat);
261: ilbusywait(sp, ILC_STAT, (sp->il_ruba >> 2) & IL_EUA);
262: if (sp->il_rbdp)
263: PURGEBDP(sp->il_ubanum, sp->il_rbdp);
264: splx(s);
265: bcopy(sp->il_rpkt.ilp_stat.ils_addr, sp->il_enaddr, 6);
266: bcopy(ether_broadcast, sp->il_arrequest.ar_xhdr.ilx_dhost, 6);
267: sp->il_arrequest.ar_xhdr.ilx_type = ILADDR_TYPE;
268: sp->il_arrequest.ar_pkt.ar_hardware = AR_ETHERNET;
269: sp->il_arrequest.ar_pkt.ar_protocol = ILCHAOS_TYPE;
270: sp->il_arrequest.ar_pkt.ar_hlength = 6;
271: sp->il_arrequest.ar_pkt.ar_plength = 2;
272: sp->il_arrequest.ar_pkt.ar_opcode = AR_REQUEST;
273: bcopy(sp->il_enaddr, sp->il_arrequest.ar_pkt.ar_esender, 6);
274: bcopy((u_char *)&sp->il_arrequest, (u_char *)&sp->il_arreply,
275: sizeof(struct chilapkt));
276: sp->il_arreply.ar_pkt.ar_opcode = AR_REPLY;
277:
278: printf("chil%d: ether addr %x %x %x %x %x %x module %s firmware %s\n",
279: unit,
280: sp->il_enaddr[0]&0xff, sp->il_enaddr[1]&0xff,
281: sp->il_enaddr[2]&0xff, sp->il_enaddr[3]&0xff,
282: sp->il_enaddr[4]&0xff, sp->il_enaddr[5]&0xff,
283: sp->il_rpkt.ilp_stat.ils_module,
284: sp->il_rpkt.ilp_stat.ils_firmware);
285: }
286:
287: /*
288: * chaos interlan initialization. Also does initialization to the static xcvr
289: * structure since initialized unions don't work anyway.
290: */
291: chilinit()
292: {
293: int unit;
294:
295: for (unit = 0; unit < NCHIL; unit++) {
296:
297: #ifndef VMUNIX
298: chilsetup(unit, (struct ildevice *)chiladdr[unit]);
299: #endif not VMUNIX
300:
301: chilreset(&chilsoft[unit].il_xcvr);
302: }
303: }
304: /*
305: * Receive our chaosnet address
306: */
307: chilseta(dev, addr)
308: unsigned dev;
309: unsigned short addr;
310: {
311: register struct chilsoft *sp;
312: register struct chroute *r;
313:
314: if (dev >= NCHIL)
315: return 1;
316: else {
317: sp = &chilsoft[dev];
318: if (sp->il_xcvr.xc_devaddr == 0)
319: return 1;
320: if (sp->il_xcvr.xc_addr != 0) { /* If we were already connected */
321: r = &Chroutetab[sp->il_xcvr.xc_subnet];
322: r->rt_type = 0;
323: r->rt_cost = CHHCOST;
324: }
325: sp->il_xcvr.xc_addr = addr;
326: if (sp->il_xcvr.xc_subnet >= CHNSUBNET)
327: return 1;
328: sp->il_arrequest.ar_pkt.ar_csender.ch_addr = addr;
329: sp->il_arreply.ar_pkt.ar_csender.ch_addr = addr;
330: r = &Chroutetab[sp->il_xcvr.xc_subnet];
331: r->rt_type = CHDIRECT;
332: r->rt_cost = CHHCOST/2;
333: r->rt_xcvr = &sp->il_xcvr;
334: return 0;
335: }
336: }
337: /*
338: * Reset interface after UNIBUS reset.
339: */
340: chilreset(xp)
341: struct chxcvr *xp;
342: {
343: register struct chilsoft *sp = xp->xc_ilinfo.il_soft;
344: register int s;
345:
346: if (sp == 0)
347: return;
348: s = splIL();
349: ilbusywait(sp, ILC_RESET, 0);
350: ilbusywait(sp, ILC_CLPBAK, 0);
351: ilbusywait(sp, ILC_CLPRMSC, 0);
352: ilbusywait(sp, ILC_CRCVERR, 0);
353: ilbusywait(sp, ILC_FLUSH, 0);
354: ilbusywait(sp, ILC_ONLINE, 0);
355: chilrstart(sp);
356: splx(s);
357: }
358:
359: /*
360: * Start output on an idle line
361: */
362: chilstart(xp)
363: struct chxcvr *xp;
364: {
365: register struct chilsoft *sp = xp->xc_ilinfo.il_soft;
366:
367: /* IF_DEBUG(printf("chilstart (unit %d)\n", sp->il_unit)); */
368: if (sp->il_xcvr.xc_tpkt != NOPKT)
369: panic("chilstart: already busy");
370: if (sp->il_oactive == 0)
371: chilcint(sp->il_unit);
372: }
373: /*
374: * Command (usually transmit) done interrupt.
375: */
376: chilcint(dev)
377: {
378: register struct ildevice *addr;
379: register struct il_xheader *epkt;
380: register struct chilsoft *sp = &chilsoft[dev];
381: register struct packet *pkt;
382: int elength;
383:
384: chilcin++;
385: LOCK;
386: addr = (struct ildevice *)sp->il_xcvr.xc_devaddr;
387: IF_DEBUG(printf("chilcint: unit %d oactive %d xbdp %d\n",
388: minor(dev), sp->il_oactive, (sp->il_xuba >> 28) & 0x0f));
389:
390: #ifdef VMUNIX
391: #ifdef NOHOG
392: if (sp->il_oactive)
393: ubarelse(sp->il_ubanum, &sp->il_xuba);
394: #else
395: if (sp->il_xbdp)
396: PURGEBDP(sp->il_ubanum, sp->il_xbdp);
397: #endif NOHOG
398: #endif VMUNIX
399:
400: sp->il_oactive = 0;
401: sp->il_scsr = addr->il_csr;
402: if (sp->il_replying) {
403: sp->il_replying = 0;
404: sp->il_doreply = 0;
405: } else if ((pkt = sp->il_xcvr.xc_tpkt) != NOPKT) {
406: if ((sp->il_scsr & IL_STATUS) > 1) {
407: chilxstat = sp->il_scsr;
408: sp->il_xcvr.xc_abrt++;
409: } else {
410: if (sp->il_scsr & IL_STATUS)
411: sp->il_xcvr.xc_abrt++;
412: sp->il_xcvr.xc_xmtd++;
413: }
414: bcopy(&sp->il_savex,
415: (char *)&pkt->pk_phead - sizeof(struct il_xheader),
416: sizeof(struct il_xheader));
417: IF_DEBUG(printf("chil: pkt %d (op %o didx %x) done\n",
418: pkt->pk_pkn, pkt->pk_op, pkt->pk_didx & 0xffff));
419: xmitdone(pkt);
420: }
421: /*
422: * If the last receive interrupt happened while a command was
423: * in progress, it couldn't prime the receive buffer then, so it
424: * set the flag telling us to do it here.
425: */
426: if (sp->il_startrcv)
427: chilrstart(sp);
428: /*
429: * If last receive interrupt created an address resolution reply
430: * to send, send it rather than another data packet.
431: */
432: if (sp->il_doreply) {
433: sp->il_replying = 1;
434: epkt = (struct il_xheader *)&sp->il_arreply;
435: elength = sizeof(struct chilapkt);
436: chilxrp++;
437: } else if ((pkt = xmitnext(&sp->il_xcvr)) == NOPKT)
438: return;
439: else {
440: IF_DEBUG(printf("chil: pkt %d (op %o didx %x) started\n",
441: pkt->pk_pkn, pkt->pk_op, pkt->pk_didx & 0xffff));
442: epkt = (struct il_xheader *)
443: ((char *)&pkt->pk_phead - sizeof(struct il_xheader));
444: elength = sizeof(struct il_xheader) +
445: sizeof(struct pkt_header) +
446: pkt->pk_len;
447: bcopy((char *)epkt, (char *)&sp->il_savex,
448: sizeof(struct il_xheader));
449: if (pkt->pk_xdest == 0) {
450: epkt->ilx_type = ILCHAOS_TYPE;
451: bcopy(ether_broadcast, epkt->ilx_dhost, 6);
452: } else {
453: register struct ar_pair *app;
454:
455: for (app = sp->il_pairs;
456: app < sp->il_epairs && app->arp_chaos.ch_addr;
457: app++)
458: if (pkt->pk_xdest == app->arp_chaos.ch_addr) {
459: app->arp_time = ++arptime;
460: epkt->ilx_type = ILCHAOS_TYPE;
461: bcopy(app->arp_ether, epkt->ilx_dhost,
462: 6);
463: app = 0;
464: break;
465: }
466: if (app) {
467: chilxrq++;
468: /*
469: * We have no cached address translation -
470: * we must ask for one.
471: */
472: epkt = (struct il_xheader *)&sp->il_arrequest;
473: sp->il_arrequest.ar_pkt.ar_ctarget.ch_addr =
474: pkt->pk_xdest;
475: elength = sizeof(struct chilapkt);
476: }
477: }
478: }
479:
480: #ifdef NOHOG
481: sp->il_xuba = uballoc(sp->il_ubanum, (caddr_t)epkt, elength, UBA_WANTBDP);
482: #else
483: sp->il_xuba = ubaremap(sp->il_ubanum, sp->il_xuba, (caddr_t)epkt);
484: #endif NOHOG
485:
486: IF_DEBUG(printf(" new uba map: xbdp %d addr %x\n",
487: (sp->il_xuba >> 28) & 0x0f, sp->il_xuba & 0xfff));
488:
489: addr->il_bar = sp->il_xuba & 0xffff;
490: addr->il_bcr = (elength + 1) & ~1;
491: addr->il_csr = ((sp->il_xuba >> 2) & IL_EUA) |
492: ILC_XMIT|IL_CIE|IL_RIE;
493: sp->il_oactive++;
494: }
495: /*
496: * Receiver interrupt
497: */
498: chilrint(dev)
499: {
500: register struct chilsoft *sp = &chilsoft[dev];
501: register struct packet *pkt; /* shouldn't be reg on pdp11 */
502: int elength;
503:
504: chilrin++;
505: if (sp->il_rbdp)
506: PURGEBDP(sp->il_ubanum, sp->il_rbdp);
507: if (sp->il_rpkt.ilp_rhdr.ilr_status == 0377) {
508: printf("chil%d: Receive interrupt with no packet!\n");
509: return;
510: }
511: if (sp->il_rpkt.ilp_rhdr.ilr_status & 4) {
512: sp->il_xcvr.xc_rej++;
513: chillost++;
514: }
515: /*
516: * Data length is chaos packet size plus header (minus
517: * frame status and length == 4 plus 4 for the crc == 0!)
518: */
519: elength = sp->il_rpkt.ilp_rhdr.ilr_length - sizeof(struct il_rheader);
520: if (sp->il_rpkt.ilp_rhdr.ilr_status & 3)
521: printf("chil%d: Received erroneous frame. Status: %d\n",
522: dev, sp->il_rpkt.ilp_rhdr.ilr_status);
523: else if (sp->il_rpkt.ilp_rhdr.ilr_type == ILADDR_TYPE)
524: chilrar(sp, &sp->il_rpkt.ilp_arpkt, elength);
525: else if (sp->il_rpkt.ilp_rhdr.ilr_type == ILCHAOS_TYPE)
526: if (elength < sizeof(struct pkt_header) ||
527: elength < sizeof(struct pkt_header) + sp->il_rpkt.ilp_chhead.ph_len)
528: sp->il_xcvr.xc_leng++;
529: else {
530: register struct chroute *r;
531:
532: r = &Chroutetab[sp->il_xcvr.xc_subnet];
533: r->rt_type = CHDIRECT;
534: r->rt_cost = CHCCOST;
535: r->rt_xcvr = &sp->il_xcvr;
536: if ((pkt = pkalloc((int)sp->il_rpkt.ilp_chhead.ph_len,
537: 1)) == NOPKT)
538: sp->il_xcvr.xc_rej++;
539: else {
540: bcopy((u_char *)&sp->il_rpkt.ilp_chpkt,
541: (u_char *)&pkt->pk_phead,
542: sizeof(struct pkt_header) +
543: sp->il_rpkt.ilp_chhead.ph_len);
544: sp->il_xcvr.xc_rcvd++;
545: LOCK;
546: if (pkt->pk_daddr == sp->il_xcvr.xc_addr &&
547: Chmyaddr != -1)
548: pkt->pk_daddr = Chmyaddr;
549: rcvpkt(pkt);
550: }
551: }
552: if (sp->il_oactive)
553: sp->il_startrcv = 1;
554: else
555: chilrstart(sp);
556: }
557: chilrstart(sp)
558: register struct chilsoft *sp;
559: {
560: register struct ildevice *addr = sp->il_devaddr;
561:
562: chilrst++;
563: sp->il_rpkt.ilp_rhdr.ilr_status = 0177777;
564: addr->il_bar = sp->il_ruba & 0xffff;
565: addr->il_bcr = sizeof(union chilpkt);
566: addr->il_csr = (sp->il_ruba >> 2) & IL_EUA |
567: ILC_RCV|IL_RIE;
568: while (!((sp->il_scsr = addr->il_csr) & IL_CDONE))
569: /* Busy wait */;
570: if (sp->il_scsr & IL_STATUS)
571: printf("il%d: receive buffer error: %d\n",
572: sp->il_unit, sp->il_scsr & IL_STATUS);
573: sp->il_startrcv = 0;
574: }
575: /*
576: * Receive an address resolution packet.
577: */
578: chilrar(sp, arp, length)
579: register struct chilsoft *sp;
580: register struct ar_packet *arp;
581: {
582: register struct ar_pair *app;
583: register struct ar_pair *nap;
584:
585: u_char *eaddr;
586:
587: chilar++;
588: if (length < sizeof(struct ar_packet) ||
589: arp->ar_hardware != AR_ETHERNET ||
590: arp->ar_protocol != ILCHAOS_TYPE ||
591: arp->ar_plength != sizeof(chaddr) ||
592: arp->ar_csender.ch_addr == 0)
593: return;
594: eaddr = 0;
595: nap = sp->il_pairs;
596: for (app = nap; app < sp->il_epairs && app->arp_chaos.ch_addr; app++)
597: if (arp->ar_csender.ch_addr == app->arp_chaos.ch_addr) {
598: eaddr = app->arp_ether;
599: break;
600: } else if (app->arp_time < nap->arp_time)
601: nap = app;
602: /*
603: * If we are already cacheing the senders addresses,
604: * update our cache with possibly new information.
605: */
606: if (eaddr)
607: bcopy(arp->ar_esender, app->arp_ether, 6);
608: if (arp->ar_ctarget.ch_addr != sp->il_xcvr.xc_addr)
609: return;
610: /*
611: * If we have never heard of this host before, find
612: * a slot and remember him.
613: * Note that we leave the time alone since we haven't used the entry.
614: * This is to prevent other hosts from flushing our cache
615: */
616: if (eaddr == 0) {
617: bcopy(arp->ar_esender, nap->arp_ether, 6);
618: nap->arp_chaos.ch_addr = arp->ar_csender.ch_addr;
619: }
620: if (arp->ar_opcode == AR_REQUEST)
621: if (sp->il_doreply)
622: chilarls++;
623: else {
624: chilarrp++;
625: IF_DEBUG(printf("chilrar: sending arp (unit %d)\n",
626: sp->il_unit));
627: sp->il_arreply.ar_pkt.ar_ctarget.ch_addr = arp->ar_csender.ch_addr;
628: bcopy(arp->ar_esender, sp->il_arreply.ar_pkt.ar_etarget, 6);
629: bcopy(arp->ar_esender, sp->il_arreply.ar_xhdr.ilx_dhost, 6);
630: sp->il_doreply = 1;
631: if (sp->il_oactive == 0)
632: chilcint(sp->il_unit);
633: }
634: }
635: #define MAXWAIT 1000000 /* on the order of 10 seconds */
636: /*
637: * Perform a command and busy-wait for the interrupt.
638: * Used when it's not safe to sleep.
639: * This should never be called to receive a packet.
640: */
641: ilbusywait(sp, command, bits)
642: register struct chilsoft *sp;
643: int command, bits;
644: {
645: register struct ildevice *addr = sp->il_devaddr;
646: register int csr, i;
647:
648: csr = addr->il_csr;
649: IF_DEBUG(printf("il%d: busy wait %x csr %x bcr %x bar %x bits %x",
650: sp->il_unit, command, csr&0xffff, addr->il_bcr&0xffff, addr->il_bar&0xffff, bits));
651: addr->il_csr = bits|command;
652: for (i = 0; !((csr = addr->il_csr) & IL_CDONE); i++)
653: if (i >= MAXWAIT) {
654: printf("il%d: lost CDONE\n", sp->il_unit);
655: return;
656: }
657: IF_DEBUG((csr & IL_STATUS) ? printf("%s\n",
658: (command == ILC_DIAG || command == ILC_RESET ?
659: ildiag : ilerrs)[csr & IL_STATUS])
660: : printf("done\n"));
661: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.