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