Annotation of XNU/osfmk/kdp/pe/POWERMAC/kdp_mace.c, revision 1.1

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(&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
        !           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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.