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