|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1997 Apple Computer, Inc.
27: *
28: * ethernet driver for mace on-board ethernet
29: *
30: * HISTORY
31: *
32: * Dieter Siegmund ([email protected]) Thu Feb 27 18:25:33 PST 1997
33: * - ripped off code from MK/LINUX, turned it into a polled-mode
34: * driver for the PCI (8500) class machines
35: *
36: * Dieter Siegmund ([email protected]) Fri Mar 21 12:41:29 PST 1997
37: * - reworked to support a BSD-style interface, and to support kdb polled
38: * interface and interrupt-driven interface concurrently
39: *
40: * Justin Walker ([email protected]) Tue May 20 10:29:29 PDT 1997
41: * - Added multicast support
42: *
43: * Dieter Siegmund ([email protected]) Thu May 29 15:02:29 PDT 1997
44: * - fixed problem with sending arp packets for ip address 0.0.0.0
45: * - use kdp_register_send_receive() instead of defining
46: * en_send_pkt/en_recv_pkt routines to avoid name space
47: * collisions with IOEthernetDebugger and allow these routines to be
48: * overridden by a driverkit-style driver
49: *
50: * Dieter Siegmund ([email protected]) Tue Jun 24 18:29:15 PDT 1997
51: * - don't let the adapter auto-strip 802.3 receive frames, it messes
52: * up the frame size logic
53: *
54: * Dieter Siegmund ([email protected]) Tue Aug 5 16:24:52 PDT 1997
55: * - handle multicast address deletion correctly
56: */
57: #ifdef MACE_DEBUG
58: /*
59: * Caveat: MACE_DEBUG delimits some code that is getting kind of
60: * stale. Before blindly turning on MACE_DEBUG for your
61: * testing, take a look at the code enabled by it to check
62: * that it is reasonably sane.
63: */
64: #endif
65:
66: #import <machdep/ppc/dbdma.h>
67: #import <kern/kdp_en_debugger.h>
68:
69: #define RECEIVE_INT DBDMA_INT_ALWAYS
70:
71: #import <sys/types.h>
72: #import <sys/systm.h>
73: #import <sys/param.h>
74: #import <sys/errno.h>
75: #import <sys/socket.h>
76: #import <net/if.h>
77: #import <net/etherdefs.h>
78: #import <netinet/if_ether.h>
79: #import <sys/sockio.h>
80: #import <netinet/in_var.h>
81: #import <netinet/in.h>
82: #import <sys/mbuf.h>
83: #import <mach/mach_types.h>
84: #import <ppc/powermac.h>
85: #import <ppc/interrupts.h>
86: #import <ppc/proc_reg.h>
87: #import <libkern/libkern.h>
88: #import <kern/thread_call.h>
89: #import "if_en.h"
90: #import "mace.h"
91:
92: extern int kdp_flag;
93:
94: #if NBPFILTER > 0
95: #import <net/bpf.h>
96: #endif
97:
98: static void polled_send_pkt(char * data, int len);
99: static void polled_receive_pkt(char *data, int *len, int timeout_ms);
100: void mace_dbdma_rx_intr(int unit, void *, void *);
101: void mace_dbdma_tx_intr(int, void *, void *);
102: void mace_pci_intr(int, void *);
103: void mace_service_queue(struct ifnet * ifp);
104:
105: #ifdef MACE_DEBUG
106: static int mace_watchdog();
107: #endif
108:
109: static __inline__ vm_offset_t
110: KVTOPHYS(vm_offset_t v)
111: {
112: return (v);
113: }
114:
115: typedef int (*funcptr)(char *, int, void *);
116:
117: #ifdef MACE_DEBUG
118: static int
119: macAddrsEqual(unsigned char * one, unsigned char * two)
120: {
121: int i;
122:
123: for (i = 0; i < NUM_EN_ADDR_BYTES; i++)
124: if (*one++ != *two++)
125: return 0;
126: return 1;
127: }
128: #endif
129:
130: static __inline__ int
131: isprint(unsigned char c)
132: {
133: return (c >= 0x20 && c <= 0x7e);
134: }
135:
136: static void
137: printEtherHeader(enet_addr_t * dh, enet_addr_t * sh, u_short etype)
138: {
139: u_char * dhost = dh->ether_addr_octet;
140: u_char * shost = sh->ether_addr_octet;
141:
142: printf("Dst: %x:%x:%x:%x:%x:%x Src: %x:%x:%x:%x:%x:%x Type: 0x%x\n",
143: dhost[0], dhost[1], dhost[2], dhost[3], dhost[4], dhost[5],
144: shost[0], shost[1], shost[2], shost[3], shost[4], shost[5],
145: etype);
146: }
147:
148: static void
149: printData(u_char * data_p, int n_bytes)
150: {
151: #define CHARS_PER_LINE 16
152: char line_buf[CHARS_PER_LINE + 1];
153: int line_pos;
154: int offset;
155:
156: for (line_pos = 0, offset = 0; offset < n_bytes; offset++, data_p++) {
157: if (line_pos == 0) {
158: printf("%04d ", offset);
159: }
160:
161: line_buf[line_pos] = isprint(*data_p) ? *data_p : '.';
162: printf(" %02x", *data_p);
163: line_pos++;
164: if (line_pos == CHARS_PER_LINE) {
165: line_buf[CHARS_PER_LINE] = '\0';
166: printf(" %s\n", line_buf);
167: line_pos = 0;
168: }
169: }
170: if (line_pos) { /* need to finish up the line */
171: for (; line_pos < CHARS_PER_LINE; line_pos++) {
172: printf(" ");
173: line_buf[line_pos] = ' ';
174: }
175: line_buf[CHARS_PER_LINE] = '\0';
176: printf(" %s\n", line_buf);
177: }
178: }
179:
180: static void
181: printEtherPacket(enet_addr_t * dhost, enet_addr_t * shost, u_short type,
182: u_char * data_p, int n_bytes)
183: {
184: printEtherHeader(dhost, shost, type);
185: printData(data_p, n_bytes);
186: }
187:
188: void
189: printContiguousEtherPacket(u_char * data_p, int n_bytes)
190: {
191: printEtherPacket((enet_addr_t *)data_p,
192: (enet_addr_t *)(data_p + NUM_EN_ADDR_BYTES),
193: *((u_short *)(data_p + (NUM_EN_ADDR_BYTES * 2))),
194: data_p, n_bytes);
195: }
196:
197: mace_t mace;
198:
199: #define MACE_DMA_AREA_SIZE (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE)
200: static unsigned long mace_rx_dma_area[(MACE_DMA_AREA_SIZE + sizeof(long))/sizeof(long)];
201:
202: static unsigned long mace_tx_dma_area[(ETHERNET_BUF_SIZE + PG_SIZE + sizeof(long))/sizeof(long)];
203:
204: /*
205: * mace_get_hwid
206: *
207: * This function computes the Ethernet Hardware address
208: * from PROM. (Its best not to ask how this is done.)
209: */
210:
211: unsigned char
212: mace_swapbits(unsigned char bits)
213: {
214: unsigned char mask = 0x1, i, newbits = 0;
215:
216: for (i = 0x80; i; mask <<= 1, i >>=1) {
217: if (bits & mask)
218: newbits |= i;
219: }
220:
221: return newbits;
222: }
223:
224: void
225: mace_get_hwid(unsigned char *hwid_addr, mace_t * m)
226: {
227: int i;
228:
229: for (i = 0; i < NUM_EN_ADDR_BYTES; i++, hwid_addr += 16) {
230: m->macaddr[i] = mace_swapbits(*hwid_addr);
231: }
232: }
233:
234: /*
235: * mace_reset
236: *
237: * Reset the board..
238: */
239:
240: void
241: mace_reset()
242: {
243: dbdma_reset(DBDMA_ETHERNET_RV);
244: dbdma_reset(DBDMA_ETHERNET_TX);
245: }
246:
247:
248: /*
249: * mace_geteh:
250: *
251: * This function gets the ethernet address (array of 6 unsigned
252: * bytes) from the MACE board registers.
253: *
254: */
255:
256: void
257: mace_geteh(char *ep)
258: {
259: int i;
260: unsigned char ep_temp;
261:
262: mace.ereg->iac = IAC_PHYADDR; eieio();
263:
264: for (i = 0; i < ETHER_ADD_SIZE; i++) {
265: ep_temp = mace.ereg->padr; eieio();
266: *ep++ = ep_temp;
267: }
268: }
269:
270: /*
271: * mace_seteh:
272: *
273: * This function sets the ethernet address (array of 6 unsigned
274: * bytes) on the MACE board.
275: */
276:
277: static void
278: mace_seteh(char *ep)
279: {
280: int i;
281: unsigned char status;
282:
283: if (mace.chip_id != MACE_REVISION_A2) {
284: mace.ereg->iac = IAC_ADDRCHG|IAC_PHYADDR; eieio();
285:
286: while ((status = mace.ereg->iac)) {
287: if ((status & IAC_ADDRCHG) == 0) {
288: eieio();
289: break;
290: }
291: eieio();
292: }
293: }
294: else {
295: /* start to load the address.. */
296: mace.ereg->iac = IAC_PHYADDR; eieio();
297: }
298:
299: for (i = 0; i < NUM_EN_ADDR_BYTES; i++) {
300: mace.ereg->padr = *(ep+i); eieio();
301: }
302: return;
303: }
304:
305: /*
306: * mace_setup_dbdma
307: *
308: * Setup various dbdma pointers.
309: */
310:
311: void
312: mace_setup_dbdma()
313: {
314: mace_t * m = &mace;
315: int i;
316: dbdma_command_t * d;
317: vm_offset_t address;
318: dbdma_regmap_t * regmap;
319:
320: #define ALIGN_MASK 0xfffffffcUL
321: if (m->rv_dma_area == 0) {
322: m->rv_dma_area = (unsigned char *)
323: ((((unsigned long)mace_rx_dma_area) + 3) & ALIGN_MASK);
324: m->rv_dma = dbdma_alloc(ETHER_RX_NUM_DBDMA_BUFS + 2);
325: m->tx_dma = dbdma_alloc(TX_NUM_DBDMA);
326: m->tx_dma_area = (unsigned char *)
327: ((((unsigned long)mace_tx_dma_area) + 3) & ALIGN_MASK);
328: }
329:
330: /* set up a ring of buffers */
331: d = m->rv_dma;
332: for (i = 0; i < ETHER_RX_NUM_DBDMA_BUFS; i++, d++) {
333: address = (vm_offset_t) KVTOPHYS((vm_offset_t)&m->rv_dma_area[i*ETHERNET_BUF_SIZE]);
334: DBDMA_BUILD(d, DBDMA_CMD_IN_LAST, 0, ETHERNET_BUF_SIZE,
335: address, RECEIVE_INT,
336: DBDMA_WAIT_NEVER,
337: DBDMA_BRANCH_NEVER);
338: }
339:
340: /* stop when we hit the end of the list */
341: DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, RECEIVE_INT,
342: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
343: d++;
344:
345: /* branch to command at "address" ie. element 0 of the "array" */
346: DBDMA_BUILD(d, DBDMA_CMD_NOP, 0, 0, 0, DBDMA_INT_NEVER,
347: DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
348: address = (vm_offset_t) KVTOPHYS((vm_offset_t)m->rv_dma);
349: dbdma_st4_endian(&d->d_cmddep, address);
350:
351: m->rv_head = 0;
352: m->rv_tail = ETHER_RX_NUM_DBDMA_BUFS; /* always contains DBDMA_CMD_STOP */
353:
354: /* stop/init/restart dma channel */
355: dbdma_reset(DBDMA_ETHERNET_RV);
356: dbdma_reset(DBDMA_ETHERNET_TX);
357:
358: /* Set the wait value.. */
359: regmap = DBDMA_REGMAP(DBDMA_ETHERNET_RV);
360: dbdma_st4_endian(®map->d_wait, DBDMA_SET_CNTRL(0x00));
361:
362: /* Set the tx wait value */
363: regmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
364: dbdma_st4_endian(®map->d_wait, DBDMA_SET_CNTRL(0x20));
365:
366: flush_cache_v((vm_offset_t)m->rv_dma,
367: sizeof(dbdma_command_t) * (ETHER_RX_NUM_DBDMA_BUFS + 2));
368: /* start receiving */
369: dbdma_start(DBDMA_ETHERNET_RV, m->rv_dma);
370: }
371:
372: #ifdef MACE_DEBUG
373: static unsigned char testBuffer[PG_SIZE * 4];
374: static unsigned char testMsg[] = "mace ethernet interface test";
375:
376: static void
377: send_test_packet()
378: {
379: unsigned char * tp;
380:
381: bzero(testBuffer, sizeof(testBuffer));
382:
383: tp = testBuffer;
384:
385: /* send self-addressed packet */
386: bcopy(&mace.macaddr[0], tp, NUM_EN_ADDR_BYTES);
387: tp += NUM_EN_ADDR_BYTES;
388: bcopy(&mace.macaddr[0], tp, NUM_EN_ADDR_BYTES);
389: tp += NUM_EN_ADDR_BYTES;
390: *tp++ = 0;
391: *tp++ = 0;
392: bcopy(testMsg, tp, sizeof(testMsg));
393: polled_send_pkt(testBuffer, 80);
394: return;
395: }
396: #endif
397:
398: /*
399: * Function: init_mace
400: *
401: * Purpose:
402: * Called early on, initializes the adapter and readies it for
403: * kdb kernel debugging.
404: */
405: void
406: init_mace()
407: {
408: unsigned char status;
409: mace_t * m = &mace;
410: struct mace_board * ereg;
411: int mpc = 0;
412:
413: /*
414: * Only use in-kernel driver for early debugging (bootargs: kdp=1 or kdp=3)
415: */
416: if ( (kdp_flag & 1) == 0 )
417: {
418: return;
419: }
420:
421: bzero(&mace, sizeof(mace));
422:
423: /* get the ethernet registers' mapped address */
424: ereg = m->ereg
425: = (struct mace_board *) POWERMAC_IO(PCI_ETHERNET_BASE_PHYS);
426: mace_get_hwid((unsigned char *)POWERMAC_IO(PCI_ETHERNET_ADDR_PHYS), m);
427:
428: /* Reset the board & AMIC.. */
429: mace_reset();
430:
431: /* grab the MACE chip rev */
432: m->chip_id = (ereg->chipid2 << 8 | ereg->chipid1);
433:
434: /* don't auto-strip for 802.3 */
435: m->ereg->rcvfc &= ~(RCVFC_ASTRPRCV);
436:
437: /* set the ethernet address */
438: mace_seteh(mace.macaddr);
439: {
440: unsigned char macaddr[NUM_EN_ADDR_BYTES];
441: mace_geteh(macaddr);
442: printf("mace ethernet [%02x:%02x:%02x:%02x:%02x:%02x]\n",
443: macaddr[0], macaddr[1], macaddr[2],
444: macaddr[3], macaddr[4], macaddr[5]);
445: }
446:
447: /* Now clear the Multicast filter */
448: if (m->chip_id != MACE_REVISION_A2) {
449: ereg->iac = IAC_ADDRCHG|IAC_LOGADDR; eieio();
450:
451: while ((status = ereg->iac)) {
452: if ((status & IAC_ADDRCHG) == 0)
453: break;
454: eieio();
455: }
456: eieio();
457: }
458: else {
459: ereg->iac = IAC_LOGADDR; eieio();
460: }
461: {
462: int i;
463:
464: for (i=0; i < 8; i++)
465: { ereg->ladrf = 0;
466: eieio();
467: }
468: }
469:
470: /* register interrupt routines */
471: mace_setup_dbdma();
472:
473: /* Start the chip... */
474: m->ereg->maccc = MACCC_ENXMT|MACCC_ENRCV; eieio();
475: {
476: volatile char ch = mace.ereg->ir; eieio();
477: }
478:
479: delay(500); /* paranoia */
480: mace.ereg->imr = 0xfe; eieio();
481:
482: /* register our debugger routines */
483: kdp_register_send_receive((kdp_send_t)polled_send_pkt,
484: (kdp_receive_t)polled_receive_pkt);
485:
486: #if 0
487: printf("Testing 1 2 3\n");
488: send_test_packet();
489: printf("Testing 1 2 3\n");
490: send_test_packet();
491: printf("Testing 1 2 3\n");
492: send_test_packet();
493: do {
494: static unsigned char buf[ETHERNET_BUF_SIZE];
495: int len;
496: int nmpc = mace.ereg->mpc; eieio();
497:
498: if (nmpc > mpc) {
499: mpc = nmpc;
500: printf("mpc %d\n", mpc);
501: }
502: polled_receive_pkt(buf, &len, 100);
503: if (len > 0) {
504: printf("rx %d\n", len);
505: printContiguousEtherPacket(buf, len);
506: }
507: } while(1);
508: #endif
509:
510: return;
511: }
512:
513: #ifdef MACE_DEBUG
514: static void
515: txstatus(char * msg)
516: {
517: volatile dbdma_regmap_t * dmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
518: volatile unsigned long status;
519: volatile unsigned long intr;
520: volatile unsigned long branch;
521: volatile unsigned long wait;
522:
523: status = dbdma_ld4_endian(&dmap->d_status); eieio();
524: intr = dbdma_ld4_endian(&dmap->d_intselect); eieio();
525: branch = dbdma_ld4_endian(&dmap->d_branch); eieio();
526: wait = dbdma_ld4_endian(&dmap->d_wait); eieio();
527: printf("(%s s=0x%x i=0x%x b=0x%x w=0x%x)", msg, status, intr, branch,
528: wait);
529: return;
530: }
531: #endif
532:
533: static void
534: tx_dbdma(char * data, int len)
535: {
536: unsigned long count;
537: dbdma_command_t * d;
538: unsigned long page;
539:
540: d = mace.tx_dma;
541: page = ((unsigned long) data) & PG_MASK;
542: if ((page + len) <= PG_SIZE) { /* one piece dma */
543: DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0,
544: len,
545: (vm_offset_t) KVTOPHYS((vm_offset_t) data),
546: DBDMA_INT_NEVER,
547: DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER);
548: }
549: else { /* two piece dma */
550: count = PG_SIZE - page;
551: DBDMA_BUILD(d, DBDMA_CMD_OUT_MORE, DBDMA_KEY_STREAM0,
552: count,
553: (vm_offset_t)KVTOPHYS((vm_offset_t) data),
554: DBDMA_INT_NEVER,
555: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
556: d++;
557: DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0,
558: len - count, (vm_offset_t)
559: KVTOPHYS((vm_offset_t)((unsigned char *)data + count)),
560: DBDMA_INT_NEVER,
561: DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER);
562: }
563: d++;
564: DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM,
565: 1, KVTOPHYS((vm_offset_t) &mace.ereg->xmtfs),DBDMA_INT_NEVER,
566: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
567: d++;
568: DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM,
569: 1, KVTOPHYS((vm_offset_t) &mace.ereg->ir), DBDMA_INT_ALWAYS,
570: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
571: d++;
572: DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, 0, 0, 0);
573: flush_cache_v((vm_offset_t)mace.tx_dma, sizeof(dbdma_command_t) * TX_NUM_DBDMA);
574: dbdma_start(DBDMA_ETHERNET_TX, mace.tx_dma);
575: return;
576:
577: }
578:
579: static void
580: waitForDBDMADone(char * msg)
581: {
582: {
583: /* wait for tx dma completion */
584: volatile dbdma_regmap_t * dmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
585: int i;
586: volatile unsigned long val;
587:
588: i = 0;
589: do {
590: val = dbdma_ld4_endian(&dmap->d_status); eieio();
591: delay(50);
592: i++;
593: } while ((i < 100000) && (val & DBDMA_CNTRL_ACTIVE));
594: if (i == 100000)
595: printf("mace(%s): tx_dbdma poll timed out 0x%x", msg, val);
596: }
597: }
598:
599: void
600: mace_service_queue(struct ifnet * ifp)
601: {
602: unsigned char * buf_p;
603: struct mbuf * m;
604: struct mbuf * mp;
605: int len;
606:
607: if (mace.tx_busy) { /* transmit in progress? */
608: return;
609: }
610:
611: IF_DEQUEUE(&(ifp->if_snd), m);
612: if (m == 0) {
613: return;
614: }
615:
616: len = m->m_pkthdr.len;
617:
618: if (len > ETHERMAXPACKET) {
619: printf("mace_start: packet too big (%d), dropping\n", len);
620: m_freem(m);
621: return;
622:
623: }
624: buf_p = mace.tx_dma_area;
625: if (m->m_nextpkt) {
626: printf("mace: sending more than one mbuf\n");
627: }
628: for (mp = m; mp; mp = mp->m_next) {
629: if (mp->m_len == 0)
630: continue;
631: bcopy(mtod(mp, caddr_t), buf_p, min(mp->m_len, len));
632: len -= mp->m_len;
633: buf_p += mp->m_len;
634: }
635: m_freem(m);
636:
637: #if NBPFILTER > 0
638: if (ifp->if_bpf)
639: BPF_TAP(ifp->if_bpf, mace.tx_dma_area, m->m_pkthdr.len);
640: #endif
641:
642: #if 0
643: printf("tx packet %d\n", m->m_pkthdr.len);
644: printContiguousEtherPacket(mace.tx_dma_area, m->m_pkthdr.len);
645: #endif
646:
647: /* fill in the dbdma records and kick off the dma */
648: tx_dbdma(mace.tx_dma_area, m->m_pkthdr.len);
649: mace.tx_busy = 1;
650: return;
651: }
652:
653: #ifdef MACE_DEBUG
654: static int
655: mace_watchdog()
656: {
657: struct ifnet * ifp = &mace.en_arpcom.ac_if;
658: int s;
659:
660: mace.txwatchdog++;
661: s = splnet();
662: if (mace.rxintr == 0) {
663: printf("rx is hung up\n");
664: rx_intr();
665: }
666: mace.rxintr = 0;
667: #if 0
668: if (mace.txintr == 0 && ifp->if_snd.ifq_head) {
669: if (mace.tx_busy)
670: dbdma_stop(DBDMA_ETHERNET_TX);
671: mace.tx_busy = 0;
672: mace_service_queue(ifp);
673: }
674: mace.txintr = 0;
675: #endif
676: timeout(mace_watchdog, 0, 10*hz); /* just in case we drop an interrupt */
677: return (0);
678: }
679: #endif /* MACE_DEBUG */
680:
681: static int
682: mace_start(struct ifnet * ifp)
683: {
684: // int i = mace.tx_busy;
685:
686: // printf("mace_start %s\n", mace.tx_busy ? "(txBusy)" : "");
687: mace_service_queue(ifp);
688:
689: // if (mace.tx_busy && !i)
690: // printf("(txStarted)\n");
691: return 0;
692: }
693:
694: int
695: mace_recv_pkt(funcptr pktfunc, void * p)
696: {
697: vm_offset_t address;
698: struct mace_board * board;
699: long bytes;
700: int done = 0;
701: int doContinue = 0;
702: mace_t * m;
703: unsigned long resid;
704: unsigned short status;
705: int tail;
706:
707: m = &mace;
708: board = m->ereg;
709:
710: /* remember where the tail was */
711: tail = m->rv_tail;
712: for (done = 0; (done == 0) && (m->rv_head != tail);) {
713: dbdma_command_t * dmaHead;
714:
715: dmaHead = &m->rv_dma[m->rv_head];
716: resid = dbdma_ld4_endian(&dmaHead->d_status_resid);
717: status = (resid >> 16);
718: bytes = resid & 0xffff;
719: bytes = ETHERNET_BUF_SIZE - bytes - 8; /* strip off FCS/CRC */
720:
721: if ((status & DBDMA_ETHERNET_EOP) == 0) {
722: /* no packets are ready yet */
723: break;
724: }
725: doContinue = 1;
726: /* if the packet is good, pass it up */
727: if (bytes >= (ETHER_MIN_PACKET - 4)) {
728: char * dmaPacket;
729: dmaPacket = &m->rv_dma_area[m->rv_head * ETHERNET_BUF_SIZE];
730: done = (*pktfunc)(dmaPacket, bytes, p);
731: }
732: /* mark the head as the new tail in the dma channel command list */
733: DBDMA_BUILD(dmaHead, DBDMA_CMD_STOP, 0, 0, 0, RECEIVE_INT,
734: DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
735: flush_cache_v((vm_offset_t)dmaHead, sizeof(*dmaHead));
736: eieio();
737:
738: /* make the tail an available dma'able entry */
739: {
740: dbdma_command_t * dmaTail;
741: dmaTail = &m->rv_dma[m->rv_tail];
742: address = KVTOPHYS((vm_offset_t)
743: &m->rv_dma_area[m->rv_tail*ETHERNET_BUF_SIZE]);
744: // this command is live so write it carefully
745: DBDMA_ST4_ENDIAN(&dmaTail->d_address, address);
746: dmaTail->d_status_resid = 0;
747: dmaTail->d_cmddep = 0;
748: eieio();
749: DBDMA_ST4_ENDIAN(&dmaTail->d_cmd_count,
750: ((DBDMA_CMD_IN_LAST) << 28) | ((0) << 24) |
751: ((RECEIVE_INT) << 20) |
752: ((DBDMA_BRANCH_NEVER) << 18) | ((DBDMA_WAIT_NEVER) << 16) |
753: (ETHERNET_BUF_SIZE));
754: eieio();
755: flush_cache_v((vm_offset_t)dmaTail, sizeof(*dmaTail));
756: }
757: /* head becomes the tail */
758: m->rv_tail = m->rv_head;
759:
760: /* advance the head */
761: m->rv_head++;
762: if (m->rv_head == (ETHER_RX_NUM_DBDMA_BUFS + 1))
763: m->rv_head = 0;
764: }
765: if (doContinue) {
766: sync();
767: dbdma_continue(DBDMA_ETHERNET_RV);
768: }
769: return (done);
770: }
771:
772: /* kdb handle buffer routines */
773: struct kdbCopy {
774: int * len;
775: char * data;
776: };
777:
778: static int
779: kdb_copy(char * pktBuf, int len, void * p)
780: {
781: struct kdbCopy * cp = (struct kdbCopy *)p;
782:
783: bcopy(pktBuf, cp->data, len);
784: *cp->len = len;
785: return (1); /* signal that we're done */
786: }
787:
788: /* kdb debugger routines */
789: static void
790: polled_send_pkt(char * data, int len)
791: {
792: waitForDBDMADone("mace: polled_send_pkt start");
793: tx_dbdma(data, len);
794: waitForDBDMADone("mace: polled_send_pkt end");
795: return;
796: }
797:
798: static void
799: polled_receive_pkt(char *data, int *len, int timeout_ms)
800: {
801: struct kdbCopy cp;
802:
803: cp.len = len;
804: cp.data = data;
805:
806: timeout_ms *= 1000;
807: *len = 0;
808: while (mace_recv_pkt(kdb_copy, (void *)&cp) == 0) {
809: if (timeout_ms <= 0)
810: break;
811: delay(50);
812: timeout_ms -= 50;
813: }
814: return;
815: }
816:
817: /* Bump to force ethernet data to be 4-byte aligned
818: * (since the ethernet header is 14 bytes, and the 802.3 header is
819: * 22 = 14+8 bytes). This assumes that m_data is word-aligned
820: * (which it is).
821: */
822: #define ETHER_DATA_ALIGN 2
823:
824: /*
825: * Function: rxpkt
826: *
827: * Purpose:
828: * Called from within mace_recv_pkt to deal with a packet of data.
829: * rxpkt() allocates an mbuf(+cluser) and passes it up to the stacks.
830: * Returns:
831: * 0 if the packet was copied to an mbuf, 1 otherwise
832: */
833: static int
834: rxpkt(char * data, int len, void * p)
835: {
836: struct ether_header * eh_p = (struct ether_header *)data;
837: struct ifnet * ifp = &mace.en_arpcom.ac_if;
838: struct mbuf * m;
839:
840: int interesting;
841:
842: mace.rxintr++;
843:
844: /* mcast, bcast -- we're interested in either */
845: interesting = eh_p->ether_dhost[0] & 1;
846:
847: #if NBPFILTER > 0
848: /*
849: * Check if there's a bpf filter listening on this interface.
850: * If so, hand off the raw packet to bpf_tap().
851: */
852: if (ifp->if_bpf) {
853: BPF_TAP(ifp->if_bpf, data, len);
854:
855: /*
856: * Keep the packet if it's a broadcast or has our
857: * physical ethernet address (or if we support
858: * multicast and it's one).
859: */
860: if ((interesting == 0) && bcmp(eh_p->ether_dhost, mace.macaddr,
861: sizeof(eh_p->ether_dhost)) != 0) {
862: return (1);
863: }
864: }
865: #endif
866:
867: /*
868: * We "know" a full-sized packet fits in one cluster. Set up the
869: * packet header, and if the length is sufficient, attempt to allocate
870: * a cluster. If that fails, fall back to the old way (m_devget()).
871: * Here, we take the simple approach of cluster vs. single mbuf.
872: */
873: MGETHDR(m, M_DONTWAIT, MT_DATA);
874: if (m == 0) {
875: #ifdef MACE_DEBUG
876: printf("mget failed\n");
877: #endif
878: return (1);
879: }
880:
881: if (len > (MHLEN - ETHER_DATA_ALIGN))
882: { MCLGET(m, M_DONTWAIT);
883: if (m->m_flags&M_EXT) /* MCLGET succeeded */
884: { m->m_data += ETHER_DATA_ALIGN;
885: bcopy(data, mtod(m, caddr_t), (unsigned)len);
886: } else
887: {
888: #ifdef MACE_DEBUG
889: printf("no clusters\n");
890: #endif
891: m_free(m);
892: m = (struct mbuf *)m_devget(data, len, 0, ifp, 0);
893: if (m == 0)
894: return (1);
895: }
896: } else
897: { m->m_data += ETHER_DATA_ALIGN;
898: bcopy(data, mtod(m, caddr_t), (unsigned)len);
899: }
900:
901: /*
902: * Current code up the line assumes that the media header's been
903: * stripped, but we'd like to preserve it, just in case someone
904: * wants to peek.
905: */
906: m->m_pkthdr.len = len;
907: m->m_len = len;
908: m->m_pkthdr.rcvif = ifp;
909: m->m_data += sizeof(*eh_p);
910: m->m_len -= sizeof (*eh_p);
911: m->m_pkthdr.len -= sizeof(*eh_p);
912: ether_input(ifp, eh_p, m);
913:
914: return (0);
915: }
916:
917:
918: static void
919: rx_intr()
920: {
921: mace_recv_pkt(rxpkt, 0);
922: }
923:
924: void
925: mace_dbdma_rx_intr(int unit, void *ignored, void * arp)
926: {
927: if (!mace.ready)
928: return;
929:
930: thread_call_func((thread_call_func_t)rx_intr, 0, TRUE);
931: }
932:
933:
934: int
935: mace_ioctl(struct ifnet * ifp,u_long cmd, caddr_t data)
936: {
937: struct arpcom * ar;
938: unsigned error = 0;
939: struct ifaddr * ifa = (struct ifaddr *)data;
940: struct ifreq * ifr = (struct ifreq *)data;
941: struct sockaddr_in * sin;
942:
943: sin = (struct sockaddr_in *)(&((struct ifreq *)data)->ifr_addr);
944: ar = (struct arpcom *)ifp;
945:
946: switch (cmd) {
947: case SIOCAUTOADDR:
948: error = in_bootp(ifp, sin, &mace.en_arpcom.ac_enaddr);
949: break;
950:
951: case SIOCSIFADDR:
952: #if NeXT
953: ifp->if_flags |= (IFF_UP | IFF_RUNNING);
954: #else
955: ifp->if_flags |= IFF_UP;
956: #endif
957: switch (ifa->ifa_addr->sa_family) {
958: case AF_INET:
959: /*
960: * See if another station has *our* IP address.
961: * i.e.: There is an address conflict! If a
962: * conflict exists, a message is sent to the
963: * console.
964: */
965: if (IA_SIN(ifa)->sin_addr.s_addr != 0) { /* don't bother for 0.0.0.0 */
966: ar->ac_ipaddr = IA_SIN(ifa)->sin_addr;
967: arpwhohas(ar, &IA_SIN(ifa)->sin_addr);
968: }
969: break;
970: default:
971: break;
972: }
973: break;
974:
975: case SIOCSIFFLAGS:
976: /*
977: * If interface is marked down and it is running, then stop it
978: */
979: if ((ifp->if_flags & IFF_UP) == 0 &&
980: (ifp->if_flags & IFF_RUNNING) != 0) {
981: /*
982: * If interface is marked down and it is running, then
983: * stop it.
984: */
985: ifp->if_flags &= ~IFF_RUNNING;
986: } else if ((ifp->if_flags & IFF_UP) != 0 &&
987: (ifp->if_flags & IFF_RUNNING) == 0) {
988: /*
989: * If interface is marked up and it is stopped, then
990: * start it.
991: */
992: ifp->if_flags |= IFF_RUNNING;
993: }
994:
995: /*
996: * If the state of the promiscuous bit changes, the
997: * interface must be reset to effect the change.
998: */
999: if (((ifp->if_flags ^ mace.promisc) & IFF_PROMISC) &&
1000: (ifp->if_flags & IFF_RUNNING)) {
1001: mace.promisc = ifp->if_flags & IFF_PROMISC;
1002: mace_sync_promisc(ifp);
1003: }
1004:
1005: break;
1006:
1007: case SIOCADDMULTI:
1008: if ((error = ether_addmulti(ifr, ar)) == ENETRESET)
1009: { if ((error = mace_addmulti(ifr, ar)) != 0)
1010: { error = 0;
1011: mace_sync_mcast(ifp);
1012: }
1013: }
1014: break;
1015:
1016: case SIOCDELMULTI:
1017: {
1018: struct ether_addr enaddr[2]; /* [0] - addrlo, [1] - addrhi */
1019:
1020: if ((error = ether_delmulti(ifr, ar, enaddr)) == ENETRESET) {
1021: if ((error = mace_delmulti(ifr, ar, enaddr)) != 0) {
1022: error = 0;
1023: mace_sync_mcast(ifp);
1024: }
1025: }
1026: }
1027: break;
1028:
1029: default:
1030: error = EINVAL;
1031: break;
1032: }
1033: return (error);
1034: }
1035:
1036: void
1037: mace_init()
1038: {
1039: struct ifnet * ifp = &mace.en_arpcom.ac_if;
1040:
1041: /*
1042: * Only use in-kernel driver for early debugging (bootargs: kdp=1|3)
1043: */
1044: if ( (kdp_flag & 1) == 0 )
1045: {
1046: return;
1047: }
1048:
1049: mace.tx_busy = 0;
1050: mace.txintr = 0;
1051: mace.promisc = 0;
1052:
1053: bzero((caddr_t)ifp, sizeof(struct ifnet));
1054: bcopy(&mace.macaddr, &mace.en_arpcom.ac_enaddr, NUM_EN_ADDR_BYTES);
1055:
1056: ifp->if_name = "en";
1057: ifp->if_unit = 0;
1058: ifp->if_private = 0;
1059: ifp->if_ioctl = mace_ioctl;
1060: ifp->if_start = mace_start;
1061: ifp->if_watchdog = 0;
1062: ifp->if_flags =
1063: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
1064: #if NBPFILTER > 0
1065: bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
1066: #endif
1067: if_attach(ifp);
1068: ether_ifattach(ifp);
1069:
1070: mace.rxintr = 0;
1071:
1072: /* wire in the interrupt routines */
1073: pmac_register_int(PMAC_DMA_ETHERNET_RX, SPLNET,
1074: mace_dbdma_rx_intr, 0);
1075: pmac_register_int(PMAC_DMA_ETHERNET_TX, SPLNET,
1076: mace_dbdma_tx_intr, 0);
1077:
1078: // pmac_register_int(PMAC_DEV_ETHERNET, SPLNET, mace_pci_intr);
1079: mace.ready = 1;
1080: #ifdef MACE_DEBUG
1081: timeout(mace_watchdog, 0, 10*hz); /* just in case we drop an interrupt */
1082: #endif
1083: return;
1084: }
1085:
1086: /*
1087: * mace_pci_intr
1088: *
1089: * Service MACE interrupt
1090: */
1091:
1092: void
1093: mace_pci_intr(int device, void *ssp)
1094: {
1095: unsigned char ir, retry, frame, packet, length;
1096:
1097: ir = mace.ereg->ir; eieio(); /* Clear Interrupt */
1098: packet = mace.ereg->mpc; eieio();
1099: length = mace.ereg->rntpc; eieio();
1100:
1101: printf("(txI)");
1102:
1103: if (ir & IR_XMTINT) {
1104: retry = mace.ereg->xmtrc; eieio(); /* Grab transmit retry count */
1105: frame = mace.ereg->xmtfs; eieio();
1106: // if (mace.ready)
1107: // mace_dbdma_tx_intr(device, ssp);
1108: }
1109: return;
1110: }
1111:
1112: static void
1113: tx_intr()
1114: {
1115: mace.txintr++;
1116: mace.tx_busy = 0;
1117: mace_service_queue(&mace.en_arpcom.ac_if);
1118: }
1119:
1120: /*
1121: * mace_dbdma_tx_intr
1122: *
1123: * DBDMA interrupt routine
1124: */
1125: void
1126: mace_dbdma_tx_intr(int unit, void *ignored, void * arg)
1127: {
1128: if (!mace.ready)
1129: return;
1130:
1131: thread_call_func((thread_call_func_t)tx_intr, 0, TRUE);
1132: return;
1133: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.