]> git.saurik.com Git - apple/xnu.git/blame - bsd/if/ppc/if_en.c
xnu-344.23.tar.gz
[apple/xnu.git] / bsd / if / ppc / if_en.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
de355530
A
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.
1c79356b 11 *
de355530
A
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
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
de355530
A
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.
1c79356b
A
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 (dieter@next.com) 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 (dieter@next.com) 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 (justin@apple.com) Tue May 20 10:29:29 PDT 1997
38 * - Added multicast support
39 *
40 * Dieter Siegmund (dieter@next.com) 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 (dieter@apple.com) 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 (dieter@apple.com) 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#include <machdep/ppc/dbdma.h>
64#include <kern/kdp_en_debugger.h>
65
66#define RECEIVE_INT DBDMA_INT_ALWAYS
67
68#include <sys/types.h>
69#include <sys/systm.h>
70#include <sys/param.h>
71#include <sys/errno.h>
72#include <sys/socket.h>
73#include <net/if.h>
74#include <net/etherdefs.h>
75#include <netinet/if_ether.h>
76#include <sys/sockio.h>
77#include <netinet/in_var.h>
78#include <netinet/in.h>
79#include <sys/mbuf.h>
80#include <mach/mach_types.h>
81#include <ppc/powermac.h>
82#include <ppc/interrupts.h>
83#include <ppc/proc_reg.h>
84#include <libkern/libkern.h>
85#include <kern/thread_call.h>
86#include "if_en.h"
87#include "mace.h"
88
89extern int kdp_flag;
90
91#if NBPFILTER > 0
92#include <net/bpf.h>
93#endif
94
95static void polled_send_pkt(char * data, int len);
96static void polled_receive_pkt(char *data, int *len, int timeout_ms);
97void mace_dbdma_rx_intr(int unit, void *, void *);
98void mace_dbdma_tx_intr(int, void *, void *);
99void mace_pci_intr(int, void *);
100void mace_service_queue(struct ifnet * ifp);
101
102#ifdef MACE_DEBUG
103static int mace_watchdog();
104#endif
105
106static __inline__ vm_offset_t
107KVTOPHYS(vm_offset_t v)
108{
109 return (v);
110}
111
112typedef int (*funcptr)(char *, int, void *);
113
114#ifdef MACE_DEBUG
115static int
116macAddrsEqual(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
127static __inline__ int
128isprint(unsigned char c)
129{
130 return (c >= 0x20 && c <= 0x7e);
131}
132
133static void
134printEtherHeader(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
145static void
146printData(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
177static void
178printEtherPacket(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
185void
186printContiguousEtherPacket(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
194mace_t mace;
195
196#define MACE_DMA_AREA_SIZE (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE)
197static unsigned long mace_rx_dma_area[(MACE_DMA_AREA_SIZE + sizeof(long))/sizeof(long)];
198
199static 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
208unsigned char
209mace_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
221void
222mace_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
237void
238mace_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
253void
254mace_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
274static void
275mace_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
308void
309mace_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(&regmap->d_wait, DBDMA_SET_CNTRL(0x00));
358
359 /* Set the tx wait value */
360 regmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
361 dbdma_st4_endian(&regmap->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
370static unsigned char testBuffer[PG_SIZE * 4];
371static unsigned char testMsg[] = "mace ethernet interface test";
372
373static void
374send_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 */
402void
403init_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
511static void
512txstatus(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
530static void
531tx_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
576static void
577waitForDBDMADone(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
596void
597mace_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
651static int
652mace_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
678static int
679mace_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
691int
692mace_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 */
770struct kdbCopy {
771 int * len;
772 char * data;
773};
774
775static int
776kdb_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 */
786static void
787polled_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
795static void
796polled_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 */
830static int
831rxpkt(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
915static void
916rx_intr()
917{
918 mace_recv_pkt(rxpkt, 0);
919}
920
921void
922mace_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
931int
932mace_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
1033void
1034mace_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
1088void
1089mace_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
1108static void
1109tx_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 */
1121void
1122mace_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}