|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Computer Consoles Inc.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: * @(#)if_ace.c 7.8 (Berkeley) 12/16/90
37: */
38:
39: /*
40: * ACC VERSAbus Ethernet controller
41: */
42: #include "ace.h"
43: #if NACE > 0
44:
45: #include "sys/param.h"
46: #include "sys/systm.h"
47: #include "sys/malloc.h"
48: #include "sys/mbuf.h"
49: #include "sys/buf.h"
50: #include "sys/protosw.h"
51: #include "sys/socket.h"
52: #include "sys/vmmac.h"
53: #include "sys/ioctl.h"
54: #include "sys/errno.h"
55: #include "sys/vmparam.h"
56: #include "sys/syslog.h"
57:
58: #include "net/if.h"
59: #include "net/netisr.h"
60: #include "net/route.h"
61: #ifdef INET
62: #include "netinet/in.h"
63: #include "netinet/in_systm.h"
64: #include "netinet/in_var.h"
65: #include "netinet/ip.h"
66: #include "netinet/ip_var.h"
67: #include "netinet/if_ether.h"
68: #endif
69: #ifdef NS
70: #include "netns/ns.h"
71: #include "netns/ns_if.h"
72: #endif
73:
74: #include "../include/cpu.h"
75: #include "../include/pte.h"
76:
77: #include "../include/mtpr.h"
78: #include "../if/if_acereg.h"
79: #include "../vba/vbavar.h"
80:
81: int aceprobe(), aceattach(), acerint(), acecint(), acestart();
82: struct vba_device *aceinfo[NACE];
83: long acestd[] = { 0 };
84: struct vba_driver acedriver =
85: { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };
86:
87: int aceinit(), aceoutput(), aceioctl(), acereset();
88: struct mbuf *aceget();
89:
90: /*
91: * Ethernet software status per interface.
92: *
93: * Each interface is referenced by a network interface structure,
94: * is_if, which the routing code uses to locate the interface.
95: * This structure contains the output queue for the interface, its address, ...
96: */
97: struct ace_softc {
98: struct arpcom is_ac; /* Ethernet common part */
99: #define is_if is_ac.ac_if /* network-visible interface */
100: #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */
101: short is_flags;
102: #define ACEF_OACTIVE 0x1 /* output is active */
103: #define ACEF_RCVPENDING 0x2 /* start rcv in acecint */
104: short is_promiscuous; /* true is enabled */
105: short is_segboundry; /* first TX Seg in dpm */
106: short is_eictr; /* Rx segment tracking ctr */
107: short is_eoctr; /* Tx segment tracking ctr */
108: short is_txnext; /* Next available Tx segment */
109: short is_currnd; /* current random backoff */
110: struct ace_stats is_stats; /* holds board statistics */
111: short is_xcnt; /* count xmitted segments to be acked
112: by the controller */
113: long is_ivec; /* autoconfig interrupt vector base */
114: struct pte *is_map; /* pte map for dual ported memory */
115: caddr_t is_dpm; /* address of mapped memory */
116: } ace_softc[NACE];
117: extern struct ifnet loif;
118:
119: aceprobe(reg, vi)
120: caddr_t reg;
121: struct vba_device *vi;
122: {
123: register br, cvec; /* must be r12, r11 */
124: struct acedevice *ap = (struct acedevice *)reg;
125: struct ace_softc *is = &ace_softc[vi->ui_unit];
126:
127: #ifdef lint
128: br = 0; cvec = br; br = cvec;
129: acerint(0); acecint(0);
130: #endif
131: if (badaddr(reg, 2))
132: return (0);
133: movow(&ap->csr, CSR_RESET);
134: DELAY(10000);
135: #ifdef notdef
136: /*
137: * Select two spaces for the interrupts aligned to an
138: * eight vector boundary and fitting in 8 bits (as
139: * required by the controller) -- YECH. The controller
140: * will be notified later at initialization time.
141: */
142: if ((vi->ui_hd->vh_lastiv -= 2) > 0xff)
143: vi->ui_hd->vh_lastiv = 0x200;
144: is->is_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x7;
145: #else
146: is->is_ivec = 0x90+vi->ui_unit*8;
147: #endif
148: br = 0x14, cvec = is->is_ivec; /* XXX */
149: return (sizeof (*ap));
150: }
151:
152: /*
153: * Interface exists: make available by filling in network interface
154: * record. System will initialize the interface when it is ready
155: * to accept packets.
156: */
157: aceattach(ui)
158: struct vba_device *ui;
159: {
160: register short unit = ui->ui_unit;
161: register struct ace_softc *is = &ace_softc[unit];
162: register struct ifnet *ifp = &is->is_if;
163: register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
164: register short *wp, i;
165:
166: ifp->if_unit = unit;
167: ifp->if_name = "ace";
168: ifp->if_mtu = ETHERMTU;
169: /*
170: * Get station's addresses and set multicast hash table.
171: */
172: for (wp = (short *)addr->station, i = 0; i < 6; i++)
173: is->is_addr[i] = ~*wp++;
174: printf("ace%d: hardware address %s\n", unit,
175: ether_sprintf(is->is_addr));
176: is->is_promiscuous = 0;
177: for (wp = (short *)addr->hash, i = 0; i < 8; i++)
178: movow(wp++, ~0xf);
179: movow(&addr->bcastena[0], ~0xffff);
180: movow(&addr->bcastena[1], ~0xffff);
181: /*
182: * Allocate and map dual ported VERSAbus memory.
183: */
184: if (vbmemalloc(32, (caddr_t)ui->ui_flags,
185: &is->is_map, &is->is_dpm) == 0) {
186: printf("ace%d: can't allocate VERSAbus memory map\n", unit);
187: return;
188: }
189:
190: ifp->if_init = aceinit;
191: ifp->if_output = ether_output;
192: ifp->if_start = acestart;
193: ifp->if_ioctl = aceioctl;
194: ifp->if_reset = acereset;
195: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
196: if_attach(ifp);
197: }
198:
199: /*
200: * Reset of interface after "system" reset.
201: */
202: acereset(unit, vban)
203: int unit, vban;
204: {
205: register struct vba_device *ui;
206:
207: if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||
208: ui->ui_vbanum != vban)
209: return;
210: printf(" ace%d", unit);
211: aceinit(unit);
212: }
213:
214: /*
215: * Initialization of interface; clear recorded pending operations
216: */
217: aceinit(unit)
218: int unit;
219: {
220: register struct ace_softc *is = &ace_softc[unit];
221: register struct vba_device *ui = aceinfo[unit];
222: register struct acedevice *addr;
223: register short Csr;
224: register int s;
225:
226: if (is->is_if.if_addrlist == (struct ifaddr *)0)
227: return;
228: if ((is->is_if.if_flags & IFF_RUNNING) == 0) {
229: /*
230: * Reset the controller, initialize the recieve buffers,
231: * and turn the controller on again and set board online.
232: */
233: addr = (struct acedevice *)ui->ui_addr;
234: s = splimp();
235: movow(&addr->csr, CSR_RESET);
236: DELAY(10000);
237:
238: /*
239: * Clean up dpm since the controller might
240: * jumble dpm after reset.
241: */
242: acesetup(unit);
243: movow(&addr->csr, CSR_GO);
244: Csr = addr->csr;
245: if (Csr & CSR_ACTIVE) {
246: movow(&addr->ivct, is->is_ivec);
247: Csr |= CSR_IENA | is->is_promiscuous;
248: movow(&addr->csr, Csr);
249: is->is_flags = 0;
250: is->is_xcnt = 0;
251: is->is_if.if_flags |= IFF_RUNNING;
252: }
253: splx(s);
254: }
255: if (is->is_if.if_snd.ifq_head)
256: acestart(&is->is_if);
257: }
258:
259: /*
260: * Start output on interface.
261: * Get another datagram to send off of the interface queue,
262: * and map it to the interface before starting the output.
263: */
264: acestart(ifp)
265: register struct ifnet *ifp;
266: {
267: register struct tx_segment *txs;
268: register long len;
269: register int s;
270: struct mbuf *m;
271: short retries;
272: #define is ((struct ace_softc *)ifp)
273:
274: again:
275: txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
276: if (txs->tx_csr & TCS_TBFULL) {
277: is->is_stats.tx_busy++;
278: ifp->if_flags |= IFF_OACTIVE;
279: return (0);
280: }
281: s = splimp();
282: IF_DEQUEUE(&ifp->if_snd, m);
283: splx(s);
284: if (m == 0) {
285: ifp->if_flags &= ~IFF_OACTIVE;
286: return (0);
287: }
288: len = aceput(txs->tx_data, m);
289: retries = txs->tx_csr & TCS_RTC;
290: if (retries > 0)
291: acebakoff(is, txs, retries);
292:
293: /*
294: * Ensure minimum packet length.
295: * This makes the safe assumtion that there are no virtual holes
296: * after the data.
297: * For security, it might be wise to zero out the added bytes,
298: * but we're mainly interested in speed at the moment.
299: */
300: if (len - sizeof (struct ether_header) < ETHERMIN)
301: len = ETHERMIN + sizeof (struct ether_header);
302: if (++is->is_txnext > SEG_MAX)
303: is->is_txnext = is->is_segboundry;
304: ifp->if_opackets++;
305: is->is_xcnt++;
306: len = (len & 0x7fff) | TCS_TBFULL;
307: movow(txs, len);
308: goto again;
309: #undef is
310: }
311:
312: /*
313: * Transmit done interrupt.
314: */
315: acecint(unit)
316: int unit;
317: {
318: register struct ace_softc *is = &ace_softc[unit];
319: register struct tx_segment *txseg;
320: short eostat;
321:
322: if (is->is_xcnt <= 0) {
323: log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n",
324: unit, is->is_xcnt);
325: is->is_xcnt = 0;
326: if (is->is_if.if_snd.ifq_head)
327: acestart(&is->is_if);
328: return;
329: }
330: is->is_xcnt--;
331: txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);
332: eostat = txseg->tx_csr;
333: if ((eostat & TCS_TBFULL) == 0) {
334: is->is_stats.tx_retries += eostat & TCS_RTC;
335: if (eostat & TCS_RTFAIL) {
336: is->is_stats.tx_discarded++;
337: is->is_if.if_oerrors++;
338: } else
339: is->is_stats.tx_datagrams++;
340: if (++is->is_eoctr >= 16)
341: is->is_eoctr = is->is_segboundry;
342: }
343: if (is->is_if.if_snd.ifq_head)
344: acestart(&is->is_if);
345: }
346:
347: /*
348: * Ethernet interface receiver interrupt.
349: * If input error just drop packet.
350: * Otherwise purge input buffered data path and examine
351: * packet to determine type. If can't determine length
352: * from type, then have to drop packet. Othewise decapsulate
353: * packet based on type and pass to type specific higher-level
354: * input routine.
355: */
356: acerint(unit)
357: int unit;
358: {
359: register struct ace_softc *is = &ace_softc[unit];
360: register struct ifqueue *inq;
361: register struct ether_header *ace;
362: register struct rx_segment *rxseg;
363: int len, s, off, resid;
364: struct mbuf *m;
365: short eistat;
366:
367: if ((is->is_if.if_flags&IFF_RUNNING) == 0)
368: return;
369: again:
370: rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);
371: eistat = rxseg->rx_csr;
372: if ((eistat & RCS_RBFULL) == 0)
373: return;
374: is->is_if.if_ipackets++;
375: if (++is->is_eictr >= is->is_segboundry)
376: is->is_eictr = 0;
377: len = eistat & RCS_RBC;
378: if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) ||
379: len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) {
380: if (eistat & RCS_ROVRN)
381: is->is_stats.rx_overruns++;
382: if (eistat & RCS_RCRC)
383: is->is_stats.rx_crc_errors++;
384: if (eistat & RCS_RODD)
385: is->is_stats.rx_align_errors++;
386: if (len < ET_MINLEN)
387: is->is_stats.rx_underruns++;
388: if (len > ET_MAXLEN+CRC_SIZE)
389: is->is_stats.rx_overruns++;
390: is->is_if.if_ierrors++;
391: rxseg->rx_csr = 0;
392: return;
393: } else
394: is->is_stats.rx_datagrams++;
395: ace = (struct ether_header *)rxseg->rx_data;
396: len -= sizeof (struct ether_header);
397: /*
398: * Deal with trailer protocol: if type is trailer
399: * get true type from first 16-bit word past data.
400: * Remember that type was trailer by setting off.
401: */
402: ace->ether_type = ntohs((u_short)ace->ether_type);
403: #define acedataaddr(ace, off, type) \
404: ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off))))
405: if (ace->ether_type >= ETHERTYPE_TRAIL &&
406: ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
407: off = (ace->ether_type - ETHERTYPE_TRAIL) * 512;
408: if (off >= ETHERMTU)
409: goto setup; /* sanity */
410: ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *));
411: resid = ntohs(*(acedataaddr(ace, off+2, u_short *)));
412: if (off + resid > len)
413: goto setup; /* sanity */
414: len = off + resid;
415: } else
416: off = 0;
417: if (len == 0)
418: goto setup;
419:
420: /*
421: * Pull packet off interface. Off is nonzero if packet
422: * has trailing header; aceget will then force this header
423: * information to be at the front.
424: */
425: m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if);
426: if (m)
427: ether_input(&is->is_if, ace, m);
428: setup:
429: rxseg->rx_csr = 0;
430: goto again;
431: }
432:
433: /*
434: * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
435: * If packet size is less than the minimum legal size,
436: * the buffer is expanded. We probably should zero out the extra
437: * bytes for security, but that would slow things down.
438: */
439: aceput(txbuf, m)
440: char *txbuf;
441: struct mbuf *m;
442: #ifdef notdef
443: {
444: register u_char *bp, *mcp;
445: register short *s1, *s2;
446: register u_int len;
447: register struct mbuf *mp;
448: int total;
449:
450: total = mp->m_pkthdr.len;
451: bp = (u_char *)txbuf;
452: for (mp = m; mp; mp = mp->m_next) {
453: len = mp->m_len;
454: if (len == 0)
455: continue;
456: mcp = mtod(mp, u_char *);
457: if (((int)mcp & 01) && ((int)bp & 01)) {
458: /* source & destination at odd addresses */
459: movob(bp++, *mcp++);
460: --len;
461: }
462: if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
463: int l = len & 1;
464:
465: s1 = (short *)bp;
466: s2 = (short *)mcp;
467: len >>= 1; /* count # of shorts */
468: while (len-- != 0)
469: movow(s1++, *s2++);
470: len = l; /* # remaining bytes */
471: bp = (u_char *)s1;
472: mcp = (u_char *)s2;
473: }
474: while (len-- != 0)
475: movob(bp++, *mcp++);
476: }
477: m_freem(m);
478: return (total);
479: }
480: #else
481: {
482: register u_char *bp, *mcp;
483: register short *s1, *s2;
484: register u_int len;
485: register struct mbuf *mp;
486: int total;
487:
488: total = 0;
489: bp = (u_char *)txbuf;
490: for (mp = m; (mp); mp = mp->m_next) {
491: len = mp->m_len;
492: if (len == 0)
493: continue;
494: total += len;
495: mcp = mtod(mp, u_char *);
496: if (((int)mcp & 01) && ((int)bp & 01)) {
497: /* source & destination at odd addresses */
498: movob(bp++, *mcp++);
499: --len;
500: }
501: if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
502: register u_int l;
503:
504: s1 = (short *)bp;
505: s2 = (short *)mcp;
506: l = len >> 1; /* count # of shorts */
507: while (l-- != 0)
508: movow(s1++, *s2++);
509: len &= 1; /* # remaining bytes */
510: bp = (u_char *)s1;
511: mcp = (u_char *)s2;
512: }
513: while (len-- != 0)
514: movob(bp++, *mcp++);
515: }
516: m_freem(m);
517: return (total);
518: }
519: #endif
520:
521: /*
522: * Routine to copy from VERSAbus memory into mbufs.
523: *
524: * Warning: This makes the fairly safe assumption that
525: * mbufs have even lengths.
526: */
527: struct mbuf *
528: aceget(rxbuf, totlen, off, ifp)
529: u_char *rxbuf;
530: int totlen, off;
531: struct ifnet *ifp;
532: {
533: register u_char *cp, *mcp;
534: register struct mbuf *m;
535: register int tlen;
536: struct mbuf *top = 0, **mp = ⊤
537: int len;
538: u_char *packet_end;
539:
540: rxbuf += sizeof (struct ether_header);
541: cp = rxbuf;
542: packet_end = cp + totlen;
543: if (off) {
544: off += 2 * sizeof(u_short);
545: totlen -= 2 * sizeof(u_short);
546: cp = rxbuf + off;
547: }
548:
549: MGETHDR(m, M_DONTWAIT, MT_DATA);
550: if (m == 0)
551: return (0);
552: m->m_pkthdr.rcvif = ifp;
553: m->m_pkthdr.len = totlen;
554: m->m_len = MHLEN;
555:
556: while (totlen > 0) {
557: if (top) {
558: MGET(m, M_DONTWAIT, MT_DATA);
559: if (m == 0) {
560: m_freem(top);
561: return (0);
562: }
563: m->m_len = MLEN;
564: }
565: len = min(totlen, (packet_end - cp));
566: if (len >= MINCLSIZE) {
567: MCLGET(m, M_DONTWAIT);
568: if (m->m_flags & M_EXT)
569: m->m_len = len = min(len, MCLBYTES);
570: else
571: len = m->m_len;
572: } else {
573: /*
574: * Place initial small packet/header at end of mbuf.
575: */
576: if (len < m->m_len) {
577: if (top == 0 && len + max_linkhdr <= m->m_len)
578: m->m_data += max_linkhdr;
579: m->m_len = len;
580: } else
581: len = m->m_len;
582: }
583: mcp = mtod(m, u_char *);
584: /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
585: /*cp += len; mcp += len;*/
586: tlen = len;
587: if (((int)mcp & 01) && ((int)cp & 01)) {
588: /* source & destination at odd addresses */
589: *mcp++ = *cp++;
590: --tlen;
591: }
592: if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) {
593: register short *s1, *s2;
594: register int l;
595:
596: s1 = (short *)mcp;
597: s2 = (short *)cp;
598: l = tlen >> 1; /* count # of shorts */
599: while (l-- > 0) /* copy shorts */
600: *s1++ = *s2++;
601: tlen &= 1; /* # remaining bytes */
602: mcp = (u_char *)s1;
603: cp = (u_char *)s2;
604: }
605: while (tlen-- > 0)
606: *mcp++ = *cp++;
607: *mp = m;
608: mp = &m->m_next;
609: totlen -= len;
610: if (cp == packet_end)
611: cp = rxbuf;
612: }
613: return (top);
614: }
615:
616: /* backoff table masks */
617: short random_mask_tbl[16] = {
618: 0x0040, 0x00c0, 0x01c0, 0x03c0, 0x07c0, 0x0fc0, 0x1fc0, 0x3fc0,
619: 0x7fc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0
620: };
621:
622: acebakoff(is, txseg, retries)
623: struct ace_softc *is;
624: struct tx_segment *txseg;
625: register int retries;
626: {
627: register short *pBakNum, random_num;
628: short *pMask;
629:
630: pMask = &random_mask_tbl[0];
631: pBakNum = &txseg->tx_backoff[0];
632: while (--retries >= 0) {
633: random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
634: random_num &= *pMask++;
635: *pBakNum++ = random_num ^ (short)(0xff00 | 0x00fc);
636: }
637: }
638:
639: /*
640: * Process an ioctl request.
641: */
642: aceioctl(ifp, cmd, data)
643: register struct ifnet *ifp;
644: int cmd;
645: caddr_t data;
646: {
647: register struct ifaddr *ifa = (struct ifaddr *)data;
648: struct acedevice *addr;
649: int s = splimp(), error = 0;
650:
651: switch (cmd) {
652:
653: case SIOCSIFADDR:
654: ifp->if_flags |= IFF_UP;
655: switch (ifa->ifa_addr->sa_family) {
656: #ifdef INET
657: case AF_INET:
658: aceinit(ifp->if_unit); /* before arpwhohas */
659: ((struct arpcom *)ifp)->ac_ipaddr =
660: IA_SIN(ifa)->sin_addr;
661: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
662: break;
663: #endif
664: #ifdef NS
665: case AF_NS: {
666: struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
667: struct ace_softc *is = &ace_softc[ifp->if_unit];
668:
669: if (!ns_nullhost(*ina)) {
670: ifp->if_flags &= ~IFF_RUNNING;
671: addr = (struct acedevice *)
672: aceinfo[ifp->if_unit]->ui_addr;
673: movow(&addr->csr, CSR_RESET);
674: DELAY(10000);
675: /* set station address & copy addr to arp */
676: acesetaddr(ifp->if_unit, addr,
677: ina->x_host.c_host);
678: } else
679: ina->x_host = *(union ns_host *)is->is_addr;
680: aceinit(ifp->if_unit);
681: break;
682: }
683: #endif
684: default:
685: aceinit(ifp->if_unit);
686: break;
687: }
688: break;
689:
690: case SIOCSIFFLAGS:
691: if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
692: addr = (struct acedevice *)
693: (aceinfo[ifp->if_unit]->ui_addr);
694: movow(&addr->csr, CSR_RESET);
695: ifp->if_flags &= ~IFF_RUNNING;
696: } else if (ifp->if_flags&IFF_UP &&
697: (ifp->if_flags&IFF_RUNNING) == 0)
698: aceinit(ifp->if_unit);
699: break;
700:
701: default:
702: error = EINVAL;
703: }
704: splx(s);
705: return (error);
706: }
707:
708: /*
709: * Set the on-board station address, then read it back
710: * to initialize the address used by ARP (among others).
711: */
712: acesetaddr(unit, addr, station)
713: short unit;
714: struct acedevice *addr;
715: u_char *station;
716: {
717: struct ace_softc *is = &ace_softc[unit];
718: register short *wp, i;
719:
720: for (wp = (short *)addr->station, i = 0; i < 6; i++)
721: movow(wp++, ~*station++);
722: for (wp = (short *)addr->station, i = 0; i < 6; i++)
723: is->is_addr[i] = ~*wp++;
724: printf("ace%d: hardware address %s\n", unit,
725: ether_sprintf(is->is_addr));
726: }
727:
728: /*
729: * Setup the device for use. Initialize dual-ported memory,
730: * backoff parameters, and various other software state.
731: */
732: acesetup(unit)
733: int unit;
734: {
735: register struct ace_softc *is = &ace_softc[unit];
736: register char *pData1;
737: register short i;
738: struct acedevice *addr;
739:
740: bzero(is->is_dpm, 16384*2);
741: is->is_currnd = 49123;
742: addr = (struct acedevice *)aceinfo[unit]->ui_addr;
743: is->is_segboundry = (addr->segb >> 11) & 0xf;
744: pData1 = is->is_dpm + (is->is_segboundry << 11);
745: for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) {
746: acebakoff(is, (struct tx_segment *)pData1, 15);
747: pData1 += sizeof (struct tx_segment);
748: }
749: is->is_eictr = 0;
750: is->is_eoctr = is->is_txnext = is->is_segboundry;
751: bzero((char *)&is->is_stats, sizeof (is->is_stats));
752: }
753: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.