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