]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kdp/pe/POWERMAC/kdp_mace.c
563f7cdd52097ca7a1009b65d7474b41172fc858
[apple/xnu.git] / osfmk / kdp / pe / POWERMAC / kdp_mace.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 <mach/boolean.h>
67 #include <mach/exception_types.h>
68 #include <mach/mach_types.h>
69
70 #include <ppc/proc_reg.h>
71 #include <ppc/pmap.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>
76
77 #include "kdp_mace.h"
78
79 struct kdp_mace_copy_desc {
80 int * len;
81 char * data;
82 };
83 static mace_t mace;
84
85 #define MACE_DMA_AREA_SIZE \
86 (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE)
87 static unsigned long
88 mace_rx_dma_area[(MACE_DMA_AREA_SIZE +
89 sizeof(long))/sizeof(long)];
90 static unsigned long
91 mace_tx_dma_area[(ETHERNET_BUF_SIZE + PG_SIZE +
92 sizeof(long))/sizeof(long)];
93
94 #ifdef MACE_DEBUG
95 static unsigned char testBuffer[PG_SIZE * 4];
96 static unsigned char testMsg[] = "mace ethernet interface test";
97 #endif
98
99 static void polled_send_pkt(char * data, int len);
100 static void polled_receive_pkt(char *data, int *len, int timeout_ms);
101
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);
106 #ifdef MACE_DEBUG
107 static void printContiguousEtherPacket(u_char *, int);
108 static void send_test_packet(void);
109 #endif
110
111 typedef int (*funcptr)(char *, int, void *);
112 int kdp_mace_recv_pkt(funcptr , 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
126 static __inline__ int
127 isprint(unsigned char c)
128 {
129 return (c >= 0x20 && c <= 0x7e);
130 }
131
132 static void
133 printEtherHeader(enet_addr_t * dh, enet_addr_t * sh, u_short etype)
134 {
135 u_char * dhost = dh->ether_addr_octet;
136 u_char * shost = sh->ether_addr_octet;
137
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],
141 etype);
142 }
143
144 static void
145 printData(u_char * data_p, int n_bytes)
146 {
147 #define CHARS_PER_LINE 16
148 char line_buf[CHARS_PER_LINE + 1];
149 int line_pos;
150 int offset;
151
152 for (line_pos = 0, offset = 0; offset < n_bytes; offset++, data_p++) {
153 if (line_pos == 0) {
154 printf("%04d ", offset);
155 }
156
157 line_buf[line_pos] = isprint(*data_p) ? *data_p : '.';
158 printf(" %02x", *data_p);
159 line_pos++;
160 if (line_pos == CHARS_PER_LINE) {
161 line_buf[CHARS_PER_LINE] = '\0';
162 printf(" %s\n", line_buf);
163 line_pos = 0;
164 }
165 }
166 if (line_pos) { /* need to finish up the line */
167 for (; line_pos < CHARS_PER_LINE; line_pos++) {
168 printf(" ");
169 line_buf[line_pos] = ' ';
170 }
171 line_buf[CHARS_PER_LINE] = '\0';
172 printf(" %s\n", line_buf);
173 }
174 }
175
176 static void
177 printEtherPacket(enet_addr_t * dhost, enet_addr_t * shost, u_short type,
178 u_char * data_p, int n_bytes)
179 {
180 printEtherHeader(dhost, shost, type);
181 printData(data_p, n_bytes);
182 }
183
184 static void
185 printContiguousEtherPacket(u_char * data_p, int n_bytes)
186 {
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))),
190 data_p, n_bytes);
191 }
192 #endif
193
194
195 /*
196 * kdp_mace_reset
197 *
198 * Reset the board..
199 */
200 void
201 kdp_mace_reset(mace_t * m)
202 {
203 dbdma_reset(m->rv_dbdma);
204 dbdma_reset(m->tx_dbdma);
205 }
206
207
208 /*
209 * kdp_mace_geteh:
210 *
211 * This function gets the ethernet address (array of 6 unsigned
212 * bytes) from the MACE board registers.
213 *
214 */
215 void
216 kdp_mace_geteh(unsigned char *ep)
217 {
218 int i;
219 unsigned char ep_temp;
220
221 mace.ereg->iac = IAC_PHYADDR; eieio();
222
223 for (i = 0; i < ETHER_ADD_SIZE; i++) {
224 ep_temp = mace.ereg->padr; eieio();
225 *ep++ = ep_temp;
226 }
227 }
228
229 /*
230 * mace_seteh:
231 *
232 * This function sets the ethernet address (array of 6 unsigned
233 * bytes) on the MACE board.
234 */
235 static void
236 mace_seteh(unsigned char *ep)
237 {
238 int i;
239 unsigned char status;
240
241 if (mace.chip_id != MACE_REVISION_A2) {
242 mace.ereg->iac = IAC_ADDRCHG|IAC_PHYADDR; eieio();
243
244 while ((status = mace.ereg->iac)) {
245 if ((status & IAC_ADDRCHG) == 0) {
246 eieio();
247 break;
248 }
249 eieio();
250 }
251 }
252 else {
253 /* start to load the address.. */
254 mace.ereg->iac = IAC_PHYADDR; eieio();
255 }
256
257 for (i = 0; i < NUM_EN_ADDR_BYTES; i++) {
258 mace.ereg->padr = *(ep+i); eieio();
259 }
260 return;
261 }
262
263 /*
264 * kdp_mace_setup_dbdma
265 *
266 * Setup various dbdma pointers.
267 */
268 void
269 kdp_mace_setup_dbdma()
270 {
271 mace_t * m = &mace;
272 int i;
273 dbdma_command_t * d;
274 vm_offset_t address;
275 dbdma_regmap_t * regmap;
276
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);
285 }
286
287 /* set up a ring of buffers */
288 d = m->rv_dma;
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,
293 DBDMA_WAIT_NEVER,
294 DBDMA_BRANCH_NEVER);
295 }
296
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);
300 d++;
301
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);
307
308 m->rv_head = 0;
309 m->rv_tail = ETHER_RX_NUM_DBDMA_BUFS; /* always contains DBDMA_CMD_STOP */
310 regmap = m->rv_dbdma;
311
312 /* stop/init/restart dma channel */
313 dbdma_reset(regmap);
314 dbdma_reset(m->tx_dbdma);
315
316 /* Set the wait value.. */
317 dbdma_st4_endian(&regmap->d_wait, DBDMA_SET_CNTRL(0x00));
318
319 /* Set the tx wait value */
320 regmap = m->tx_dbdma;
321 dbdma_st4_endian(&regmap->d_wait, DBDMA_SET_CNTRL(0x20));
322
323 flush_dcache((vm_offset_t)m->rv_dma,
324 sizeof(dbdma_command_t) * (ETHER_RX_NUM_DBDMA_BUFS + 2),
325 FALSE);
326 /* start receiving */
327 dbdma_start(m->rv_dbdma, m->rv_dma);
328 }
329
330 #ifdef MACE_DEBUG
331 static void
332 send_test_packet()
333 {
334 unsigned char * tp;
335
336 bzero((char *)testBuffer, sizeof(testBuffer));
337
338 tp = testBuffer;
339
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;
345 *tp++ = 0;
346 *tp++ = 0;
347 bcopy((char *)testMsg, (char *)tp, sizeof(testMsg));
348 polled_send_pkt((char *)testBuffer, 80);
349 return;
350 }
351 #endif
352
353 /*
354 * Function: kdp_mace_init
355 *
356 * Purpose:
357 * Called early on, initializes the adapter and readies it for
358 * kdb kernel debugging.
359 */
360 boolean_t
361 kdp_mace_init(void * baseAddresses[3], unsigned char * netAddr)
362 {
363 unsigned char status;
364 mace_t * m = &mace;
365 struct mace_board * ereg;
366 int mpc = 0;
367 int i;
368
369 bzero((char *)&mace, sizeof(mace));
370
371 /* get the ethernet registers' mapped address */
372 ereg = m->ereg
373 = (struct mace_board *) baseAddresses[0];
374 m->tx_dbdma = (dbdma_regmap_t *) baseAddresses[1];
375 m->rv_dbdma = (dbdma_regmap_t *) baseAddresses[2];
376
377 for (i = 0; i < NUM_EN_ADDR_BYTES; i++)
378 m->macaddr[i] = netAddr[i];
379
380 /* Reset the board & AMIC.. */
381 kdp_mace_reset(m);
382
383 /* grab the MACE chip rev */
384 m->chip_id = (ereg->chipid2 << 8 | ereg->chipid1);
385
386 /* don't auto-strip for 802.3 */
387 m->ereg->rcvfc &= ~(RCVFC_ASTRPRCV);
388
389 /* set the ethernet address */
390 mace_seteh(mace.macaddr);
391 {
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]);
397 }
398
399 /* Now clear the Multicast filter */
400 if (m->chip_id != MACE_REVISION_A2) {
401 ereg->iac = IAC_ADDRCHG|IAC_LOGADDR; eieio();
402
403 while ((status = ereg->iac)) {
404 if ((status & IAC_ADDRCHG) == 0)
405 break;
406 eieio();
407 }
408 eieio();
409 }
410 else {
411 ereg->iac = IAC_LOGADDR; eieio();
412 }
413 {
414 int i;
415
416 for (i=0; i < 8; i++)
417 { ereg->ladrf = 0;
418 eieio();
419 }
420 }
421
422 /* register interrupt routines */
423 kdp_mace_setup_dbdma();
424
425 /* Start the chip... */
426 m->ereg->maccc = MACCC_ENXMT|MACCC_ENRCV; eieio();
427 {
428 volatile char ch = mace.ereg->ir; eieio();
429 }
430
431 delay(500); /* paranoia */
432 mace.ereg->imr = 0xfe; eieio();
433
434 /* register our debugger routines */
435 kdp_register_send_receive((kdp_send_t)polled_send_pkt,
436 (kdp_receive_t)polled_receive_pkt);
437
438 #ifdef MACE_DEBUG
439 printf("Testing 1 2 3\n");
440 send_test_packet();
441 printf("Testing 1 2 3\n");
442 send_test_packet();
443 printf("Testing 1 2 3\n");
444 send_test_packet();
445 do {
446 static unsigned char buf[ETHERNET_BUF_SIZE];
447 int len;
448 int nmpc = mace.ereg->mpc; eieio();
449
450 if (nmpc > mpc) {
451 mpc = nmpc;
452 printf("mpc %d\n", mpc);
453 }
454 polled_receive_pkt((char *)buf, &len, 100);
455 if (len > 0) {
456 printf("rx %d\n", len);
457 printContiguousEtherPacket(buf, len);
458 }
459 } while(1);
460 #endif
461
462 return TRUE;
463 }
464
465 #ifdef MACE_DEBUG
466 static void
467 kdp_mace_txstatus(char * msg)
468 {
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;
474
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,
480 wait);
481 return;
482 }
483 #endif
484
485 static void
486 kdp_mace_tx_dbdma(char * data, int len)
487 {
488 unsigned long count;
489 dbdma_command_t * d;
490 unsigned long page;
491
492 d = mace.tx_dma;
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,
496 len,
497 (vm_offset_t) kvtophys((vm_offset_t) data),
498 DBDMA_INT_NEVER,
499 DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER);
500 }
501 else { /* two piece dma */
502 count = PG_SIZE - page;
503 DBDMA_BUILD(d, DBDMA_CMD_OUT_MORE, DBDMA_KEY_STREAM0,
504 count,
505 (vm_offset_t)kvtophys((vm_offset_t) data),
506 DBDMA_INT_NEVER,
507 DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
508 d++;
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)),
512 DBDMA_INT_NEVER,
513 DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER);
514 }
515 d++;
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);
520 d++;
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);
525 d++;
526 DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, 0, 0, 0);
527
528 flush_dcache((vm_offset_t)mace.tx_dma,
529 sizeof(dbdma_command_t) * TX_NUM_DBDMA,
530 FALSE);
531 dbdma_start(mace.tx_dbdma, mace.tx_dma);
532 return;
533
534 }
535
536 static void
537 waitForDBDMADone(char * msg)
538 {
539 {
540 /* wait for tx dma completion */
541 dbdma_regmap_t * dmap = mace.tx_dbdma;
542 int i;
543 volatile unsigned long val;
544
545 i = 0;
546 do {
547 val = dbdma_ld4_endian(&dmap->d_status); eieio();
548 delay(50);
549 i++;
550 } while ((i < 100000) && (val & DBDMA_CNTRL_ACTIVE));
551 if (i == 100000)
552 printf("mace(%s): kdp_mace_tx_dbdma poll timed out 0x%x", msg, val);
553 }
554 }
555
556 int
557 kdp_mace_recv_pkt(funcptr pktfunc, void * p)
558 {
559 vm_offset_t address;
560 struct mace_board * board;
561 long bytes;
562 int done = 0;
563 int doContinue = 0;
564 mace_t * m;
565 unsigned long resid;
566 unsigned short status;
567 int tail;
568
569 m = &mace;
570 board = m->ereg;
571
572 /* remember where the tail was */
573 tail = m->rv_tail;
574 for (done = 0; (done == 0) && (m->rv_head != tail);) {
575 dbdma_command_t * dmaHead;
576
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 */
582
583 if ((status & DBDMA_ETHERNET_EOP) == 0) {
584 /* no packets are ready yet */
585 break;
586 }
587 doContinue = 1;
588 /* if the packet is good, pass it up */
589 if (bytes >= (ETHER_MIN_PACKET - 4)) {
590 char * dmaPacket;
591 dmaPacket = (char *)&m->rv_dma_area[m->rv_head * ETHERNET_BUF_SIZE];
592 done = (*pktfunc)(dmaPacket, bytes, p);
593 }
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,
598 sizeof(*dmaHead),
599 FALSE);
600 eieio();
601
602 /* make the tail an available dma'able entry */
603 {
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;
612 eieio();
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));
618 eieio();
619 flush_dcache((vm_offset_t)dmaTail,
620 sizeof(*dmaTail),
621 FALSE);
622 }
623 /* head becomes the tail */
624 m->rv_tail = m->rv_head;
625
626 /* advance the head */
627 m->rv_head++;
628 if (m->rv_head == (ETHER_RX_NUM_DBDMA_BUFS + 1))
629 m->rv_head = 0;
630 }
631 if (doContinue) {
632 sync();
633 dbdma_continue(m->rv_dbdma);
634 }
635 return (done);
636 }
637
638 static int
639 kdp_mace_copy(char * pktBuf, int len, void * p)
640 {
641 struct kdp_mace_copy_desc * cp = (struct kdp_mace_copy_desc *)p;
642
643 bcopy((char *)pktBuf, (char *)cp->data, len);
644 *cp->len = len;
645 return (1); /* signal that we're done */
646 }
647
648 /* kdb debugger routines */
649 static void
650 polled_send_pkt(char * data, int len)
651 {
652 waitForDBDMADone("mace: polled_send_pkt start");
653 kdp_mace_tx_dbdma(data, len);
654 waitForDBDMADone("mace: polled_send_pkt end");
655 return;
656 }
657
658 static void
659 polled_receive_pkt(char *data, int *len, int timeout_ms)
660 {
661 struct kdp_mace_copy_desc cp;
662
663 cp.len = len;
664 cp.data = data;
665
666 timeout_ms *= 1000;
667 *len = 0;
668 while (kdp_mace_recv_pkt(kdp_mace_copy, (void *)&cp) == 0) {
669 if (timeout_ms <= 0)
670 break;
671 delay(50);
672 timeout_ms -= 50;
673 }
674 return;
675 }