]> git.saurik.com Git - apple/xnu.git/blob - bsd/if/ppc/if_en.c
xnu-344.49.tar.gz
[apple/xnu.git] / bsd / if / ppc / if_en.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
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 (dieter@next.com) 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 (dieter@next.com) 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 (justin@apple.com) Tue May 20 10:29:29 PDT 1997
41 * - Added multicast support
42 *
43 * Dieter Siegmund (dieter@next.com) 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 (dieter@apple.com) 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 (dieter@apple.com) 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 #include <machdep/ppc/dbdma.h>
67 #include <kern/kdp_en_debugger.h>
68
69 #define RECEIVE_INT DBDMA_INT_ALWAYS
70
71 #include <sys/types.h>
72 #include <sys/systm.h>
73 #include <sys/param.h>
74 #include <sys/errno.h>
75 #include <sys/socket.h>
76 #include <net/if.h>
77 #include <net/etherdefs.h>
78 #include <netinet/if_ether.h>
79 #include <sys/sockio.h>
80 #include <netinet/in_var.h>
81 #include <netinet/in.h>
82 #include <sys/mbuf.h>
83 #include <mach/mach_types.h>
84 #include <ppc/powermac.h>
85 #include <ppc/interrupts.h>
86 #include <ppc/proc_reg.h>
87 #include <libkern/libkern.h>
88 #include <kern/thread_call.h>
89 #include "if_en.h"
90 #include "mace.h"
91
92 extern int kdp_flag;
93
94 #if NBPFILTER > 0
95 #include <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(&regmap->d_wait, DBDMA_SET_CNTRL(0x00));
361
362 /* Set the tx wait value */
363 regmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
364 dbdma_st4_endian(&regmap->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_flags =
1062 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
1063 #if NBPFILTER > 0
1064 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
1065 #endif
1066 if_attach(ifp);
1067 ether_ifattach(ifp);
1068
1069 mace.rxintr = 0;
1070
1071 /* wire in the interrupt routines */
1072 pmac_register_int(PMAC_DMA_ETHERNET_RX, SPLNET,
1073 mace_dbdma_rx_intr, 0);
1074 pmac_register_int(PMAC_DMA_ETHERNET_TX, SPLNET,
1075 mace_dbdma_tx_intr, 0);
1076
1077 // pmac_register_int(PMAC_DEV_ETHERNET, SPLNET, mace_pci_intr);
1078 mace.ready = 1;
1079 #ifdef MACE_DEBUG
1080 timeout(mace_watchdog, 0, 10*hz); /* just in case we drop an interrupt */
1081 #endif
1082 return;
1083 }
1084
1085 /*
1086 * mace_pci_intr
1087 *
1088 * Service MACE interrupt
1089 */
1090
1091 void
1092 mace_pci_intr(int device, void *ssp)
1093 {
1094 unsigned char ir, retry, frame, packet, length;
1095
1096 ir = mace.ereg->ir; eieio(); /* Clear Interrupt */
1097 packet = mace.ereg->mpc; eieio();
1098 length = mace.ereg->rntpc; eieio();
1099
1100 printf("(txI)");
1101
1102 if (ir & IR_XMTINT) {
1103 retry = mace.ereg->xmtrc; eieio(); /* Grab transmit retry count */
1104 frame = mace.ereg->xmtfs; eieio();
1105 // if (mace.ready)
1106 // mace_dbdma_tx_intr(device, ssp);
1107 }
1108 return;
1109 }
1110
1111 static void
1112 tx_intr()
1113 {
1114 mace.txintr++;
1115 mace.tx_busy = 0;
1116 mace_service_queue(&mace.en_arpcom.ac_if);
1117 }
1118
1119 /*
1120 * mace_dbdma_tx_intr
1121 *
1122 * DBDMA interrupt routine
1123 */
1124 void
1125 mace_dbdma_tx_intr(int unit, void *ignored, void * arg)
1126 {
1127 if (!mace.ready)
1128 return;
1129
1130 thread_call_func((thread_call_func_t)tx_intr, 0, TRUE);
1131 return;
1132 }