]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/pe/POWERMAC/kdp_mace.c
563f7cdd52097ca7a1009b65d7474b41172fc858
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1997 Apple Computer, Inc.
28 * ethernet driver for mace on-board ethernet
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
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
40 * Justin Walker (justin@apple.com) Tue May 20 10:29:29 PDT 1997
41 * - Added multicast support
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
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
54 * Dieter Siegmund (dieter@apple.com) Tue Aug 5 16:24:52 PDT 1997
55 * - handle multicast address deletion correctly
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.
66 #include <mach/boolean.h>
67 #include <mach/exception_types.h>
68 #include <mach/mach_types.h>
70 #include <ppc/proc_reg.h>
72 #include <pexpert/ppc/powermac.h>
73 #include <pexpert/ppc/dbdma.h>
74 #include <kdp/kdp_en_debugger.h>
75 #include <kdp/kdp_udp.h>
79 struct kdp_mace_copy_desc
{
85 #define MACE_DMA_AREA_SIZE \
86 (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE)
88 mace_rx_dma_area
[(MACE_DMA_AREA_SIZE
+
89 sizeof(long))/sizeof(long)];
91 mace_tx_dma_area
[(ETHERNET_BUF_SIZE
+ PG_SIZE
+
92 sizeof(long))/sizeof(long)];
95 static unsigned char testBuffer
[PG_SIZE
* 4];
96 static unsigned char testMsg
[] = "mace ethernet interface test";
99 static void polled_send_pkt(char * data
, int len
);
100 static void polled_receive_pkt(char *data
, int *len
, int timeout_ms
);
102 void kdp_mace_reset(mace_t
*);
103 void kdp_mace_geteh(unsigned char *);
104 void kdp_mace_setup_dbdma(void);
105 boolean_t
kdp_mace_init(void * baseAddresses
[3], unsigned char * netAddr
);
107 static void printContiguousEtherPacket(u_char
*, int);
108 static void send_test_packet(void);
111 typedef int (*funcptr
)(char *, int, void *);
112 int kdp_mace_recv_pkt(funcptr
, void *);
116 macAddrsEqual(unsigned char * one
, unsigned char * two
)
120 for (i
= 0; i
< NUM_EN_ADDR_BYTES
; i
++)
121 if (*one
++ != *two
++)
126 static __inline__
int
127 isprint(unsigned char c
)
129 return (c
>= 0x20 && c
<= 0x7e);
133 printEtherHeader(enet_addr_t
* dh
, enet_addr_t
* sh
, u_short etype
)
135 u_char
* dhost
= dh
->ether_addr_octet
;
136 u_char
* shost
= sh
->ether_addr_octet
;
138 printf("Dst: %x:%x:%x:%x:%x:%x Src: %x:%x:%x:%x:%x:%x Type: 0x%x\n",
139 dhost
[0], dhost
[1], dhost
[2], dhost
[3], dhost
[4], dhost
[5],
140 shost
[0], shost
[1], shost
[2], shost
[3], shost
[4], shost
[5],
145 printData(u_char
* data_p
, int n_bytes
)
147 #define CHARS_PER_LINE 16
148 char line_buf
[CHARS_PER_LINE
+ 1];
152 for (line_pos
= 0, offset
= 0; offset
< n_bytes
; offset
++, data_p
++) {
154 printf("%04d ", offset
);
157 line_buf
[line_pos
] = isprint(*data_p
) ? *data_p
: '.';
158 printf(" %02x", *data_p
);
160 if (line_pos
== CHARS_PER_LINE
) {
161 line_buf
[CHARS_PER_LINE
] = '\0';
162 printf(" %s\n", line_buf
);
166 if (line_pos
) { /* need to finish up the line */
167 for (; line_pos
< CHARS_PER_LINE
; line_pos
++) {
169 line_buf
[line_pos
] = ' ';
171 line_buf
[CHARS_PER_LINE
] = '\0';
172 printf(" %s\n", line_buf
);
177 printEtherPacket(enet_addr_t
* dhost
, enet_addr_t
* shost
, u_short type
,
178 u_char
* data_p
, int n_bytes
)
180 printEtherHeader(dhost
, shost
, type
);
181 printData(data_p
, n_bytes
);
185 printContiguousEtherPacket(u_char
* data_p
, int n_bytes
)
187 printEtherPacket((enet_addr_t
*)data_p
,
188 (enet_addr_t
*)(data_p
+ NUM_EN_ADDR_BYTES
),
189 *((u_short
*)(data_p
+ (NUM_EN_ADDR_BYTES
* 2))),
201 kdp_mace_reset(mace_t
* m
)
203 dbdma_reset(m
->rv_dbdma
);
204 dbdma_reset(m
->tx_dbdma
);
211 * This function gets the ethernet address (array of 6 unsigned
212 * bytes) from the MACE board registers.
216 kdp_mace_geteh(unsigned char *ep
)
219 unsigned char ep_temp
;
221 mace
.ereg
->iac
= IAC_PHYADDR
; eieio();
223 for (i
= 0; i
< ETHER_ADD_SIZE
; i
++) {
224 ep_temp
= mace
.ereg
->padr
; eieio();
232 * This function sets the ethernet address (array of 6 unsigned
233 * bytes) on the MACE board.
236 mace_seteh(unsigned char *ep
)
239 unsigned char status
;
241 if (mace
.chip_id
!= MACE_REVISION_A2
) {
242 mace
.ereg
->iac
= IAC_ADDRCHG
|IAC_PHYADDR
; eieio();
244 while ((status
= mace
.ereg
->iac
)) {
245 if ((status
& IAC_ADDRCHG
) == 0) {
253 /* start to load the address.. */
254 mace
.ereg
->iac
= IAC_PHYADDR
; eieio();
257 for (i
= 0; i
< NUM_EN_ADDR_BYTES
; i
++) {
258 mace
.ereg
->padr
= *(ep
+i
); eieio();
264 * kdp_mace_setup_dbdma
266 * Setup various dbdma pointers.
269 kdp_mace_setup_dbdma()
275 dbdma_regmap_t
* regmap
;
277 #define ALIGN_MASK 0xfffffffcUL
278 if (m
->rv_dma_area
== 0) {
279 m
->rv_dma_area
= (unsigned char *)
280 ((((unsigned long)mace_rx_dma_area
) + 3) & ALIGN_MASK
);
281 m
->rv_dma
= dbdma_alloc(ETHER_RX_NUM_DBDMA_BUFS
+ 2);
282 m
->tx_dma
= dbdma_alloc(TX_NUM_DBDMA
);
283 m
->tx_dma_area
= (unsigned char *)
284 ((((unsigned long)mace_tx_dma_area
) + 3) & ALIGN_MASK
);
287 /* set up a ring of buffers */
289 for (i
= 0; i
< ETHER_RX_NUM_DBDMA_BUFS
; i
++, d
++) {
290 address
= (vm_offset_t
) kvtophys((vm_offset_t
)&m
->rv_dma_area
[i
*ETHERNET_BUF_SIZE
]);
291 DBDMA_BUILD(d
, DBDMA_CMD_IN_LAST
, 0, ETHERNET_BUF_SIZE
,
292 address
, DBDMA_INT_ALWAYS
,
297 /* stop when we hit the end of the list */
298 DBDMA_BUILD(d
, DBDMA_CMD_STOP
, 0, 0, 0, DBDMA_INT_ALWAYS
,
299 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
302 /* branch to command at "address" ie. element 0 of the "array" */
303 DBDMA_BUILD(d
, DBDMA_CMD_NOP
, 0, 0, 0, DBDMA_INT_NEVER
,
304 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_ALWAYS
);
305 address
= (vm_offset_t
) kvtophys((vm_offset_t
)m
->rv_dma
);
306 dbdma_st4_endian(&d
->d_cmddep
, address
);
309 m
->rv_tail
= ETHER_RX_NUM_DBDMA_BUFS
; /* always contains DBDMA_CMD_STOP */
310 regmap
= m
->rv_dbdma
;
312 /* stop/init/restart dma channel */
314 dbdma_reset(m
->tx_dbdma
);
316 /* Set the wait value.. */
317 dbdma_st4_endian(®map
->d_wait
, DBDMA_SET_CNTRL(0x00));
319 /* Set the tx wait value */
320 regmap
= m
->tx_dbdma
;
321 dbdma_st4_endian(®map
->d_wait
, DBDMA_SET_CNTRL(0x20));
323 flush_dcache((vm_offset_t
)m
->rv_dma
,
324 sizeof(dbdma_command_t
) * (ETHER_RX_NUM_DBDMA_BUFS
+ 2),
326 /* start receiving */
327 dbdma_start(m
->rv_dbdma
, m
->rv_dma
);
336 bzero((char *)testBuffer
, sizeof(testBuffer
));
340 /* send self-addressed packet */
341 bcopy((char *)&mace
.macaddr
[0], (char *)tp
, NUM_EN_ADDR_BYTES
);
342 tp
+= NUM_EN_ADDR_BYTES
;
343 bcopy((char *)&mace
.macaddr
[0], (char *)tp
, NUM_EN_ADDR_BYTES
);
344 tp
+= NUM_EN_ADDR_BYTES
;
347 bcopy((char *)testMsg
, (char *)tp
, sizeof(testMsg
));
348 polled_send_pkt((char *)testBuffer
, 80);
354 * Function: kdp_mace_init
357 * Called early on, initializes the adapter and readies it for
358 * kdb kernel debugging.
361 kdp_mace_init(void * baseAddresses
[3], unsigned char * netAddr
)
363 unsigned char status
;
365 struct mace_board
* ereg
;
369 bzero((char *)&mace
, sizeof(mace
));
371 /* get the ethernet registers' mapped address */
373 = (struct mace_board
*) baseAddresses
[0];
374 m
->tx_dbdma
= (dbdma_regmap_t
*) baseAddresses
[1];
375 m
->rv_dbdma
= (dbdma_regmap_t
*) baseAddresses
[2];
377 for (i
= 0; i
< NUM_EN_ADDR_BYTES
; i
++)
378 m
->macaddr
[i
] = netAddr
[i
];
380 /* Reset the board & AMIC.. */
383 /* grab the MACE chip rev */
384 m
->chip_id
= (ereg
->chipid2
<< 8 | ereg
->chipid1
);
386 /* don't auto-strip for 802.3 */
387 m
->ereg
->rcvfc
&= ~(RCVFC_ASTRPRCV
);
389 /* set the ethernet address */
390 mace_seteh(mace
.macaddr
);
392 unsigned char macaddr
[NUM_EN_ADDR_BYTES
];
393 kdp_mace_geteh(macaddr
);
394 printf("mace ethernet [%02x:%02x:%02x:%02x:%02x:%02x]\n",
395 macaddr
[0], macaddr
[1], macaddr
[2],
396 macaddr
[3], macaddr
[4], macaddr
[5]);
399 /* Now clear the Multicast filter */
400 if (m
->chip_id
!= MACE_REVISION_A2
) {
401 ereg
->iac
= IAC_ADDRCHG
|IAC_LOGADDR
; eieio();
403 while ((status
= ereg
->iac
)) {
404 if ((status
& IAC_ADDRCHG
) == 0)
411 ereg
->iac
= IAC_LOGADDR
; eieio();
416 for (i
=0; i
< 8; i
++)
422 /* register interrupt routines */
423 kdp_mace_setup_dbdma();
425 /* Start the chip... */
426 m
->ereg
->maccc
= MACCC_ENXMT
|MACCC_ENRCV
; eieio();
428 volatile char ch
= mace
.ereg
->ir
; eieio();
431 delay(500); /* paranoia */
432 mace
.ereg
->imr
= 0xfe; eieio();
434 /* register our debugger routines */
435 kdp_register_send_receive((kdp_send_t
)polled_send_pkt
,
436 (kdp_receive_t
)polled_receive_pkt
);
439 printf("Testing 1 2 3\n");
441 printf("Testing 1 2 3\n");
443 printf("Testing 1 2 3\n");
446 static unsigned char buf
[ETHERNET_BUF_SIZE
];
448 int nmpc
= mace
.ereg
->mpc
; eieio();
452 printf("mpc %d\n", mpc
);
454 polled_receive_pkt((char *)buf
, &len
, 100);
456 printf("rx %d\n", len
);
457 printContiguousEtherPacket(buf
, len
);
467 kdp_mace_txstatus(char * msg
)
469 dbdma_regmap_t
* dmap
= mace
.tx_dbdma
;
470 volatile unsigned long status
;
471 volatile unsigned long intr
;
472 volatile unsigned long branch
;
473 volatile unsigned long wait
;
475 status
= dbdma_ld4_endian(&dmap
->d_status
); eieio();
476 intr
= dbdma_ld4_endian(&dmap
->d_intselect
); eieio();
477 branch
= dbdma_ld4_endian(&dmap
->d_branch
); eieio();
478 wait
= dbdma_ld4_endian(&dmap
->d_wait
); eieio();
479 printf("(%s s=0x%x i=0x%x b=0x%x w=0x%x)", msg
, status
, intr
, branch
,
486 kdp_mace_tx_dbdma(char * data
, int len
)
493 page
= ((unsigned long) data
) & PG_MASK
;
494 if ((page
+ len
) <= PG_SIZE
) { /* one piece dma */
495 DBDMA_BUILD(d
, DBDMA_CMD_OUT_LAST
, DBDMA_KEY_STREAM0
,
497 (vm_offset_t
) kvtophys((vm_offset_t
) data
),
499 DBDMA_WAIT_IF_FALSE
, DBDMA_BRANCH_NEVER
);
501 else { /* two piece dma */
502 count
= PG_SIZE
- page
;
503 DBDMA_BUILD(d
, DBDMA_CMD_OUT_MORE
, DBDMA_KEY_STREAM0
,
505 (vm_offset_t
)kvtophys((vm_offset_t
) data
),
507 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
509 DBDMA_BUILD(d
, DBDMA_CMD_OUT_LAST
, DBDMA_KEY_STREAM0
,
510 len
- count
, (vm_offset_t
)
511 kvtophys((vm_offset_t
)((unsigned char *)data
+ count
)),
513 DBDMA_WAIT_IF_FALSE
, DBDMA_BRANCH_NEVER
);
516 DBDMA_BUILD(d
, DBDMA_CMD_LOAD_QUAD
, DBDMA_KEY_SYSTEM
,
517 1, kvtophys((vm_offset_t
) &mace
.ereg
->xmtfs
),DBDMA_INT_NEVER
,
518 // 1, &mace.ereg->xmtfs,DBDMA_INT_NEVER,
519 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
521 DBDMA_BUILD(d
, DBDMA_CMD_LOAD_QUAD
, DBDMA_KEY_SYSTEM
,
522 1, kvtophys((vm_offset_t
) &mace
.ereg
->ir
), DBDMA_INT_ALWAYS
,
523 // 1, &mace.ereg->ir, DBDMA_INT_ALWAYS,
524 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
526 DBDMA_BUILD(d
, DBDMA_CMD_STOP
, 0, 0, 0, 0, 0, 0);
528 flush_dcache((vm_offset_t
)mace
.tx_dma
,
529 sizeof(dbdma_command_t
) * TX_NUM_DBDMA
,
531 dbdma_start(mace
.tx_dbdma
, mace
.tx_dma
);
537 waitForDBDMADone(char * msg
)
540 /* wait for tx dma completion */
541 dbdma_regmap_t
* dmap
= mace
.tx_dbdma
;
543 volatile unsigned long val
;
547 val
= dbdma_ld4_endian(&dmap
->d_status
); eieio();
550 } while ((i
< 100000) && (val
& DBDMA_CNTRL_ACTIVE
));
552 printf("mace(%s): kdp_mace_tx_dbdma poll timed out 0x%x", msg
, val
);
557 kdp_mace_recv_pkt(funcptr pktfunc
, void * p
)
560 struct mace_board
* board
;
566 unsigned short status
;
572 /* remember where the tail was */
574 for (done
= 0; (done
== 0) && (m
->rv_head
!= tail
);) {
575 dbdma_command_t
* dmaHead
;
577 dmaHead
= &m
->rv_dma
[m
->rv_head
];
578 resid
= dbdma_ld4_endian(&dmaHead
->d_status_resid
);
579 status
= (resid
>> 16);
580 bytes
= resid
& 0xffff;
581 bytes
= ETHERNET_BUF_SIZE
- bytes
- 8; /* strip off FCS/CRC */
583 if ((status
& DBDMA_ETHERNET_EOP
) == 0) {
584 /* no packets are ready yet */
588 /* if the packet is good, pass it up */
589 if (bytes
>= (ETHER_MIN_PACKET
- 4)) {
591 dmaPacket
= (char *)&m
->rv_dma_area
[m
->rv_head
* ETHERNET_BUF_SIZE
];
592 done
= (*pktfunc
)(dmaPacket
, bytes
, p
);
594 /* mark the head as the new tail in the dma channel command list */
595 DBDMA_BUILD(dmaHead
, DBDMA_CMD_STOP
, 0, 0, 0, DBDMA_INT_ALWAYS
,
596 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
597 flush_dcache((vm_offset_t
)dmaHead
,
602 /* make the tail an available dma'able entry */
604 dbdma_command_t
* dmaTail
;
605 dmaTail
= &m
->rv_dma
[m
->rv_tail
];
606 address
= kvtophys((vm_offset_t
)
607 &m
->rv_dma_area
[m
->rv_tail
*ETHERNET_BUF_SIZE
]);
608 // this command is live so write it carefully
609 DBDMA_ST4_ENDIAN(&dmaTail
->d_address
, address
);
610 dmaTail
->d_status_resid
= 0;
611 dmaTail
->d_cmddep
= 0;
613 DBDMA_ST4_ENDIAN(&dmaTail
->d_cmd_count
,
614 ((DBDMA_CMD_IN_LAST
) << 28) | ((0) << 24) |
615 ((DBDMA_INT_ALWAYS
) << 20) |
616 ((DBDMA_BRANCH_NEVER
) << 18) | ((DBDMA_WAIT_NEVER
) << 16) |
617 (ETHERNET_BUF_SIZE
));
619 flush_dcache((vm_offset_t
)dmaTail
,
623 /* head becomes the tail */
624 m
->rv_tail
= m
->rv_head
;
626 /* advance the head */
628 if (m
->rv_head
== (ETHER_RX_NUM_DBDMA_BUFS
+ 1))
633 dbdma_continue(m
->rv_dbdma
);
639 kdp_mace_copy(char * pktBuf
, int len
, void * p
)
641 struct kdp_mace_copy_desc
* cp
= (struct kdp_mace_copy_desc
*)p
;
643 bcopy((char *)pktBuf
, (char *)cp
->data
, len
);
645 return (1); /* signal that we're done */
648 /* kdb debugger routines */
650 polled_send_pkt(char * data
, int len
)
652 waitForDBDMADone("mace: polled_send_pkt start");
653 kdp_mace_tx_dbdma(data
, len
);
654 waitForDBDMADone("mace: polled_send_pkt end");
659 polled_receive_pkt(char *data
, int *len
, int timeout_ms
)
661 struct kdp_mace_copy_desc cp
;
668 while (kdp_mace_recv_pkt(kdp_mace_copy
, (void *)&cp
) == 0) {