]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/pe/POWERMAC/kdp_mace.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1997 Apple Computer, Inc.
25 * ethernet driver for mace on-board ethernet
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
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
37 * Justin Walker (justin@apple.com) Tue May 20 10:29:29 PDT 1997
38 * - Added multicast support
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
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
51 * Dieter Siegmund (dieter@apple.com) Tue Aug 5 16:24:52 PDT 1997
52 * - handle multicast address deletion correctly
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.
63 #include <mach/boolean.h>
64 #include <mach/exception_types.h>
65 #include <mach/mach_types.h>
67 #include <ppc/proc_reg.h>
69 #include <pexpert/ppc/powermac.h>
70 #include <pexpert/ppc/dbdma.h>
71 #include <kdp/kdp_en_debugger.h>
72 #include <kdp/kdp_udp.h>
76 struct kdp_mace_copy_desc
{
82 #define MACE_DMA_AREA_SIZE \
83 (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE)
85 mace_rx_dma_area
[(MACE_DMA_AREA_SIZE
+
86 sizeof(long))/sizeof(long)];
88 mace_tx_dma_area
[(ETHERNET_BUF_SIZE
+ PG_SIZE
+
89 sizeof(long))/sizeof(long)];
92 static unsigned char testBuffer
[PG_SIZE
* 4];
93 static unsigned char testMsg
[] = "mace ethernet interface test";
96 static void polled_send_pkt(char * data
, int len
);
97 static void polled_receive_pkt(char *data
, int *len
, int timeout_ms
);
99 void kdp_mace_reset(mace_t
*);
100 void kdp_mace_geteh(unsigned char *);
101 void kdp_mace_setup_dbdma(void);
102 boolean_t
kdp_mace_init(void * baseAddresses
[3], unsigned char * netAddr
);
104 static void printContiguousEtherPacket(u_char
*, int);
105 static void send_test_packet(void);
108 typedef int (*funcptr
)(char *, int, void *);
109 int kdp_mace_recv_pkt(funcptr
, void *);
113 macAddrsEqual(unsigned char * one
, unsigned char * two
)
117 for (i
= 0; i
< NUM_EN_ADDR_BYTES
; i
++)
118 if (*one
++ != *two
++)
123 static __inline__
int
124 isprint(unsigned char c
)
126 return (c
>= 0x20 && c
<= 0x7e);
130 printEtherHeader(enet_addr_t
* dh
, enet_addr_t
* sh
, u_short etype
)
132 u_char
* dhost
= dh
->ether_addr_octet
;
133 u_char
* shost
= sh
->ether_addr_octet
;
135 printf("Dst: %x:%x:%x:%x:%x:%x Src: %x:%x:%x:%x:%x:%x Type: 0x%x\n",
136 dhost
[0], dhost
[1], dhost
[2], dhost
[3], dhost
[4], dhost
[5],
137 shost
[0], shost
[1], shost
[2], shost
[3], shost
[4], shost
[5],
142 printData(u_char
* data_p
, int n_bytes
)
144 #define CHARS_PER_LINE 16
145 char line_buf
[CHARS_PER_LINE
+ 1];
149 for (line_pos
= 0, offset
= 0; offset
< n_bytes
; offset
++, data_p
++) {
151 printf("%04d ", offset
);
154 line_buf
[line_pos
] = isprint(*data_p
) ? *data_p
: '.';
155 printf(" %02x", *data_p
);
157 if (line_pos
== CHARS_PER_LINE
) {
158 line_buf
[CHARS_PER_LINE
] = '\0';
159 printf(" %s\n", line_buf
);
163 if (line_pos
) { /* need to finish up the line */
164 for (; line_pos
< CHARS_PER_LINE
; line_pos
++) {
166 line_buf
[line_pos
] = ' ';
168 line_buf
[CHARS_PER_LINE
] = '\0';
169 printf(" %s\n", line_buf
);
174 printEtherPacket(enet_addr_t
* dhost
, enet_addr_t
* shost
, u_short type
,
175 u_char
* data_p
, int n_bytes
)
177 printEtherHeader(dhost
, shost
, type
);
178 printData(data_p
, n_bytes
);
182 printContiguousEtherPacket(u_char
* data_p
, int n_bytes
)
184 printEtherPacket((enet_addr_t
*)data_p
,
185 (enet_addr_t
*)(data_p
+ NUM_EN_ADDR_BYTES
),
186 *((u_short
*)(data_p
+ (NUM_EN_ADDR_BYTES
* 2))),
198 kdp_mace_reset(mace_t
* m
)
200 dbdma_reset(m
->rv_dbdma
);
201 dbdma_reset(m
->tx_dbdma
);
208 * This function gets the ethernet address (array of 6 unsigned
209 * bytes) from the MACE board registers.
213 kdp_mace_geteh(unsigned char *ep
)
216 unsigned char ep_temp
;
218 mace
.ereg
->iac
= IAC_PHYADDR
; eieio();
220 for (i
= 0; i
< ETHER_ADD_SIZE
; i
++) {
221 ep_temp
= mace
.ereg
->padr
; eieio();
229 * This function sets the ethernet address (array of 6 unsigned
230 * bytes) on the MACE board.
233 mace_seteh(unsigned char *ep
)
236 unsigned char status
;
238 if (mace
.chip_id
!= MACE_REVISION_A2
) {
239 mace
.ereg
->iac
= IAC_ADDRCHG
|IAC_PHYADDR
; eieio();
241 while ((status
= mace
.ereg
->iac
)) {
242 if ((status
& IAC_ADDRCHG
) == 0) {
250 /* start to load the address.. */
251 mace
.ereg
->iac
= IAC_PHYADDR
; eieio();
254 for (i
= 0; i
< NUM_EN_ADDR_BYTES
; i
++) {
255 mace
.ereg
->padr
= *(ep
+i
); eieio();
261 * kdp_mace_setup_dbdma
263 * Setup various dbdma pointers.
266 kdp_mace_setup_dbdma()
272 dbdma_regmap_t
* regmap
;
274 #define ALIGN_MASK 0xfffffffcUL
275 if (m
->rv_dma_area
== 0) {
276 m
->rv_dma_area
= (unsigned char *)
277 ((((unsigned long)mace_rx_dma_area
) + 3) & ALIGN_MASK
);
278 m
->rv_dma
= dbdma_alloc(ETHER_RX_NUM_DBDMA_BUFS
+ 2);
279 m
->tx_dma
= dbdma_alloc(TX_NUM_DBDMA
);
280 m
->tx_dma_area
= (unsigned char *)
281 ((((unsigned long)mace_tx_dma_area
) + 3) & ALIGN_MASK
);
284 /* set up a ring of buffers */
286 for (i
= 0; i
< ETHER_RX_NUM_DBDMA_BUFS
; i
++, d
++) {
287 address
= (vm_offset_t
) kvtophys((vm_offset_t
)&m
->rv_dma_area
[i
*ETHERNET_BUF_SIZE
]);
288 DBDMA_BUILD(d
, DBDMA_CMD_IN_LAST
, 0, ETHERNET_BUF_SIZE
,
289 address
, DBDMA_INT_ALWAYS
,
294 /* stop when we hit the end of the list */
295 DBDMA_BUILD(d
, DBDMA_CMD_STOP
, 0, 0, 0, DBDMA_INT_ALWAYS
,
296 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
299 /* branch to command at "address" ie. element 0 of the "array" */
300 DBDMA_BUILD(d
, DBDMA_CMD_NOP
, 0, 0, 0, DBDMA_INT_NEVER
,
301 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_ALWAYS
);
302 address
= (vm_offset_t
) kvtophys((vm_offset_t
)m
->rv_dma
);
303 dbdma_st4_endian(&d
->d_cmddep
, address
);
306 m
->rv_tail
= ETHER_RX_NUM_DBDMA_BUFS
; /* always contains DBDMA_CMD_STOP */
307 regmap
= m
->rv_dbdma
;
309 /* stop/init/restart dma channel */
311 dbdma_reset(m
->tx_dbdma
);
313 /* Set the wait value.. */
314 dbdma_st4_endian(®map
->d_wait
, DBDMA_SET_CNTRL(0x00));
316 /* Set the tx wait value */
317 regmap
= m
->tx_dbdma
;
318 dbdma_st4_endian(®map
->d_wait
, DBDMA_SET_CNTRL(0x20));
320 flush_dcache((vm_offset_t
)m
->rv_dma
,
321 sizeof(dbdma_command_t
) * (ETHER_RX_NUM_DBDMA_BUFS
+ 2),
323 /* start receiving */
324 dbdma_start(m
->rv_dbdma
, m
->rv_dma
);
333 bzero((char *)testBuffer
, sizeof(testBuffer
));
337 /* send self-addressed packet */
338 bcopy((char *)&mace
.macaddr
[0], (char *)tp
, NUM_EN_ADDR_BYTES
);
339 tp
+= NUM_EN_ADDR_BYTES
;
340 bcopy((char *)&mace
.macaddr
[0], (char *)tp
, NUM_EN_ADDR_BYTES
);
341 tp
+= NUM_EN_ADDR_BYTES
;
344 bcopy((char *)testMsg
, (char *)tp
, sizeof(testMsg
));
345 polled_send_pkt((char *)testBuffer
, 80);
351 * Function: kdp_mace_init
354 * Called early on, initializes the adapter and readies it for
355 * kdb kernel debugging.
358 kdp_mace_init(void * baseAddresses
[3], unsigned char * netAddr
)
360 unsigned char status
;
362 struct mace_board
* ereg
;
366 bzero((char *)&mace
, sizeof(mace
));
368 /* get the ethernet registers' mapped address */
370 = (struct mace_board
*) baseAddresses
[0];
371 m
->tx_dbdma
= (dbdma_regmap_t
*) baseAddresses
[1];
372 m
->rv_dbdma
= (dbdma_regmap_t
*) baseAddresses
[2];
374 for (i
= 0; i
< NUM_EN_ADDR_BYTES
; i
++)
375 m
->macaddr
[i
] = netAddr
[i
];
377 /* Reset the board & AMIC.. */
380 /* grab the MACE chip rev */
381 m
->chip_id
= (ereg
->chipid2
<< 8 | ereg
->chipid1
);
383 /* don't auto-strip for 802.3 */
384 m
->ereg
->rcvfc
&= ~(RCVFC_ASTRPRCV
);
386 /* set the ethernet address */
387 mace_seteh(mace
.macaddr
);
389 unsigned char macaddr
[NUM_EN_ADDR_BYTES
];
390 kdp_mace_geteh(macaddr
);
391 printf("mace ethernet [%02x:%02x:%02x:%02x:%02x:%02x]\n",
392 macaddr
[0], macaddr
[1], macaddr
[2],
393 macaddr
[3], macaddr
[4], macaddr
[5]);
396 /* Now clear the Multicast filter */
397 if (m
->chip_id
!= MACE_REVISION_A2
) {
398 ereg
->iac
= IAC_ADDRCHG
|IAC_LOGADDR
; eieio();
400 while ((status
= ereg
->iac
)) {
401 if ((status
& IAC_ADDRCHG
) == 0)
408 ereg
->iac
= IAC_LOGADDR
; eieio();
413 for (i
=0; i
< 8; i
++)
419 /* register interrupt routines */
420 kdp_mace_setup_dbdma();
422 /* Start the chip... */
423 m
->ereg
->maccc
= MACCC_ENXMT
|MACCC_ENRCV
; eieio();
425 volatile char ch
= mace
.ereg
->ir
; eieio();
428 delay(500); /* paranoia */
429 mace
.ereg
->imr
= 0xfe; eieio();
431 /* register our debugger routines */
432 kdp_register_send_receive((kdp_send_t
)polled_send_pkt
,
433 (kdp_receive_t
)polled_receive_pkt
);
436 printf("Testing 1 2 3\n");
438 printf("Testing 1 2 3\n");
440 printf("Testing 1 2 3\n");
443 static unsigned char buf
[ETHERNET_BUF_SIZE
];
445 int nmpc
= mace
.ereg
->mpc
; eieio();
449 printf("mpc %d\n", mpc
);
451 polled_receive_pkt((char *)buf
, &len
, 100);
453 printf("rx %d\n", len
);
454 printContiguousEtherPacket(buf
, len
);
464 kdp_mace_txstatus(char * msg
)
466 dbdma_regmap_t
* dmap
= mace
.tx_dbdma
;
467 volatile unsigned long status
;
468 volatile unsigned long intr
;
469 volatile unsigned long branch
;
470 volatile unsigned long wait
;
472 status
= dbdma_ld4_endian(&dmap
->d_status
); eieio();
473 intr
= dbdma_ld4_endian(&dmap
->d_intselect
); eieio();
474 branch
= dbdma_ld4_endian(&dmap
->d_branch
); eieio();
475 wait
= dbdma_ld4_endian(&dmap
->d_wait
); eieio();
476 printf("(%s s=0x%x i=0x%x b=0x%x w=0x%x)", msg
, status
, intr
, branch
,
483 kdp_mace_tx_dbdma(char * data
, int len
)
490 page
= ((unsigned long) data
) & PG_MASK
;
491 if ((page
+ len
) <= PG_SIZE
) { /* one piece dma */
492 DBDMA_BUILD(d
, DBDMA_CMD_OUT_LAST
, DBDMA_KEY_STREAM0
,
494 (vm_offset_t
) kvtophys((vm_offset_t
) data
),
496 DBDMA_WAIT_IF_FALSE
, DBDMA_BRANCH_NEVER
);
498 else { /* two piece dma */
499 count
= PG_SIZE
- page
;
500 DBDMA_BUILD(d
, DBDMA_CMD_OUT_MORE
, DBDMA_KEY_STREAM0
,
502 (vm_offset_t
)kvtophys((vm_offset_t
) data
),
504 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
506 DBDMA_BUILD(d
, DBDMA_CMD_OUT_LAST
, DBDMA_KEY_STREAM0
,
507 len
- count
, (vm_offset_t
)
508 kvtophys((vm_offset_t
)((unsigned char *)data
+ count
)),
510 DBDMA_WAIT_IF_FALSE
, DBDMA_BRANCH_NEVER
);
513 DBDMA_BUILD(d
, DBDMA_CMD_LOAD_QUAD
, DBDMA_KEY_SYSTEM
,
514 1, kvtophys((vm_offset_t
) &mace
.ereg
->xmtfs
),DBDMA_INT_NEVER
,
515 // 1, &mace.ereg->xmtfs,DBDMA_INT_NEVER,
516 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
518 DBDMA_BUILD(d
, DBDMA_CMD_LOAD_QUAD
, DBDMA_KEY_SYSTEM
,
519 1, kvtophys((vm_offset_t
) &mace
.ereg
->ir
), DBDMA_INT_ALWAYS
,
520 // 1, &mace.ereg->ir, DBDMA_INT_ALWAYS,
521 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
523 DBDMA_BUILD(d
, DBDMA_CMD_STOP
, 0, 0, 0, 0, 0, 0);
525 flush_dcache((vm_offset_t
)mace
.tx_dma
,
526 sizeof(dbdma_command_t
) * TX_NUM_DBDMA
,
528 dbdma_start(mace
.tx_dbdma
, mace
.tx_dma
);
534 waitForDBDMADone(char * msg
)
537 /* wait for tx dma completion */
538 dbdma_regmap_t
* dmap
= mace
.tx_dbdma
;
540 volatile unsigned long val
;
544 val
= dbdma_ld4_endian(&dmap
->d_status
); eieio();
547 } while ((i
< 100000) && (val
& DBDMA_CNTRL_ACTIVE
));
549 printf("mace(%s): kdp_mace_tx_dbdma poll timed out 0x%x", msg
, val
);
554 kdp_mace_recv_pkt(funcptr pktfunc
, void * p
)
557 struct mace_board
* board
;
563 unsigned short status
;
569 /* remember where the tail was */
571 for (done
= 0; (done
== 0) && (m
->rv_head
!= tail
);) {
572 dbdma_command_t
* dmaHead
;
574 dmaHead
= &m
->rv_dma
[m
->rv_head
];
575 resid
= dbdma_ld4_endian(&dmaHead
->d_status_resid
);
576 status
= (resid
>> 16);
577 bytes
= resid
& 0xffff;
578 bytes
= ETHERNET_BUF_SIZE
- bytes
- 8; /* strip off FCS/CRC */
580 if ((status
& DBDMA_ETHERNET_EOP
) == 0) {
581 /* no packets are ready yet */
585 /* if the packet is good, pass it up */
586 if (bytes
>= (ETHER_MIN_PACKET
- 4)) {
588 dmaPacket
= (char *)&m
->rv_dma_area
[m
->rv_head
* ETHERNET_BUF_SIZE
];
589 done
= (*pktfunc
)(dmaPacket
, bytes
, p
);
591 /* mark the head as the new tail in the dma channel command list */
592 DBDMA_BUILD(dmaHead
, DBDMA_CMD_STOP
, 0, 0, 0, DBDMA_INT_ALWAYS
,
593 DBDMA_WAIT_NEVER
, DBDMA_BRANCH_NEVER
);
594 flush_dcache((vm_offset_t
)dmaHead
,
599 /* make the tail an available dma'able entry */
601 dbdma_command_t
* dmaTail
;
602 dmaTail
= &m
->rv_dma
[m
->rv_tail
];
603 address
= kvtophys((vm_offset_t
)
604 &m
->rv_dma_area
[m
->rv_tail
*ETHERNET_BUF_SIZE
]);
605 // this command is live so write it carefully
606 DBDMA_ST4_ENDIAN(&dmaTail
->d_address
, address
);
607 dmaTail
->d_status_resid
= 0;
608 dmaTail
->d_cmddep
= 0;
610 DBDMA_ST4_ENDIAN(&dmaTail
->d_cmd_count
,
611 ((DBDMA_CMD_IN_LAST
) << 28) | ((0) << 24) |
612 ((DBDMA_INT_ALWAYS
) << 20) |
613 ((DBDMA_BRANCH_NEVER
) << 18) | ((DBDMA_WAIT_NEVER
) << 16) |
614 (ETHERNET_BUF_SIZE
));
616 flush_dcache((vm_offset_t
)dmaTail
,
620 /* head becomes the tail */
621 m
->rv_tail
= m
->rv_head
;
623 /* advance the head */
625 if (m
->rv_head
== (ETHER_RX_NUM_DBDMA_BUFS
+ 1))
630 dbdma_continue(m
->rv_dbdma
);
636 kdp_mace_copy(char * pktBuf
, int len
, void * p
)
638 struct kdp_mace_copy_desc
* cp
= (struct kdp_mace_copy_desc
*)p
;
640 bcopy((char *)pktBuf
, (char *)cp
->data
, len
);
642 return (1); /* signal that we're done */
645 /* kdb debugger routines */
647 polled_send_pkt(char * data
, int len
)
649 waitForDBDMADone("mace: polled_send_pkt start");
650 kdp_mace_tx_dbdma(data
, len
);
651 waitForDBDMADone("mace: polled_send_pkt end");
656 polled_receive_pkt(char *data
, int *len
, int timeout_ms
)
658 struct kdp_mace_copy_desc cp
;
665 while (kdp_mace_recv_pkt(kdp_mace_copy
, (void *)&cp
) == 0) {