|
|
1.1 root 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 ([email protected]) 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 ([email protected]) 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 ([email protected]) Tue May 20 10:29:29 PDT 1997
38: * - Added multicast support
39: *
40: * Dieter Siegmund ([email protected]) 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 ([email protected]) 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 ([email protected]) 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:
76: struct kdp_mace_copy_desc {
77: int * len;
78: char * data;
79: };
80: static mace_t mace;
81:
82: #define MACE_DMA_AREA_SIZE \
83: (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE)
84: static unsigned long
85: mace_rx_dma_area[(MACE_DMA_AREA_SIZE +
86: sizeof(long))/sizeof(long)];
87: static unsigned long
88: mace_tx_dma_area[(ETHERNET_BUF_SIZE + PG_SIZE +
89: sizeof(long))/sizeof(long)];
90:
91: #ifdef MACE_DEBUG
92: static unsigned char testBuffer[PG_SIZE * 4];
93: static unsigned char testMsg[] = "mace ethernet interface test";
94: #endif
95:
96: static void polled_send_pkt(char * data, int len);
97: static void polled_receive_pkt(char *data, int *len, int timeout_ms);
98:
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);
103: #ifdef MACE_DEBUG
104: static void printContiguousEtherPacket(u_char *, int);
105: static void send_test_packet(void);
106: #endif
107:
108: typedef int (*funcptr)(char *, int, void *);
109: int kdp_mace_recv_pkt(funcptr , void *);
110:
111: #ifdef MACE_DEBUG
112: static int
113: macAddrsEqual(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:
123: static __inline__ int
124: isprint(unsigned char c)
125: {
126: return (c >= 0x20 && c <= 0x7e);
127: }
128:
129: static void
130: printEtherHeader(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:
141: static void
142: printData(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:
173: static void
174: printEtherPacket(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:
181: static void
182: printContiguousEtherPacket(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: */
197: void
198: kdp_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: */
212: void
213: kdp_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: */
232: static void
233: mace_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: */
265: void
266: kdp_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(®map->d_wait, DBDMA_SET_CNTRL(0x00));
315:
316: /* Set the tx wait value */
317: regmap = m->tx_dbdma;
318: dbdma_st4_endian(®map->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
328: static void
329: send_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: */
357: boolean_t
358: kdp_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
463: static void
464: kdp_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:
482: static void
483: kdp_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:
533: static void
534: waitForDBDMADone(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:
553: int
554: kdp_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:
635: static int
636: kdp_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 */
646: static void
647: polled_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:
655: static void
656: polled_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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.