Annotation of XNU/bsd/if/ppc/if_en.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: #import <machdep/ppc/dbdma.h>
        !            64: #import <kern/kdp_en_debugger.h>
        !            65: 
        !            66: #define RECEIVE_INT    DBDMA_INT_ALWAYS
        !            67: 
        !            68: #import <sys/types.h>
        !            69: #import <sys/systm.h>
        !            70: #import <sys/param.h>
        !            71: #import <sys/errno.h>
        !            72: #import <sys/socket.h>
        !            73: #import <net/if.h>
        !            74: #import <net/etherdefs.h>
        !            75: #import        <netinet/if_ether.h>
        !            76: #import        <sys/sockio.h>
        !            77: #import        <netinet/in_var.h>
        !            78: #import        <netinet/in.h>
        !            79: #import <sys/mbuf.h>
        !            80: #import <mach/mach_types.h>
        !            81: #import <ppc/powermac.h>
        !            82: #import <ppc/interrupts.h>
        !            83: #import <ppc/proc_reg.h>
        !            84: #import <libkern/libkern.h>
        !            85: #import <kern/thread_call.h>
        !            86: #import "if_en.h"
        !            87: #import "mace.h"
        !            88: 
        !            89: extern int kdp_flag;
        !            90: 
        !            91: #if NBPFILTER > 0
        !            92: #import <net/bpf.h>
        !            93: #endif
        !            94: 
        !            95: static void polled_send_pkt(char * data, int len);
        !            96: static void polled_receive_pkt(char *data, int *len, int timeout_ms);
        !            97: void mace_dbdma_rx_intr(int unit, void *, void *);
        !            98: void mace_dbdma_tx_intr(int, void *, void *);
        !            99: void mace_pci_intr(int, void *);
        !           100: void mace_service_queue(struct ifnet * ifp);
        !           101: 
        !           102: #ifdef MACE_DEBUG
        !           103: static int mace_watchdog();
        !           104: #endif
        !           105: 
        !           106: static __inline__ vm_offset_t
        !           107: KVTOPHYS(vm_offset_t v)
        !           108: {
        !           109:     return (v);
        !           110: }
        !           111: 
        !           112: typedef int (*funcptr)(char *, int, 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: #endif
        !           126: 
        !           127: static __inline__ int
        !           128: isprint(unsigned char c)
        !           129: {
        !           130:     return (c >= 0x20 && c <= 0x7e);
        !           131: }
        !           132: 
        !           133: static void
        !           134: printEtherHeader(enet_addr_t * dh, enet_addr_t * sh, u_short etype)
        !           135: {
        !           136:     u_char * dhost = dh->ether_addr_octet; 
        !           137:     u_char * shost = sh->ether_addr_octet;
        !           138: 
        !           139:     printf("Dst: %x:%x:%x:%x:%x:%x Src: %x:%x:%x:%x:%x:%x Type: 0x%x\n", 
        !           140:            dhost[0], dhost[1], dhost[2], dhost[3], dhost[4], dhost[5],
        !           141:            shost[0], shost[1], shost[2], shost[3], shost[4], shost[5],
        !           142:            etype);
        !           143: }
        !           144: 
        !           145: static void
        !           146: printData(u_char * data_p, int n_bytes)
        !           147: {
        !           148: #define CHARS_PER_LINE         16
        !           149:     char               line_buf[CHARS_PER_LINE + 1];
        !           150:     int                        line_pos;
        !           151:     int                        offset;
        !           152: 
        !           153:     for (line_pos = 0, offset = 0; offset < n_bytes; offset++, data_p++) {
        !           154:        if (line_pos == 0) {
        !           155:            printf("%04d ", offset);
        !           156:        }
        !           157: 
        !           158:        line_buf[line_pos] = isprint(*data_p) ? *data_p : '.';
        !           159:        printf(" %02x", *data_p);
        !           160:        line_pos++;
        !           161:        if (line_pos == CHARS_PER_LINE) {
        !           162:            line_buf[CHARS_PER_LINE] = '\0';
        !           163:            printf("  %s\n", line_buf);
        !           164:            line_pos = 0;
        !           165:        }
        !           166:     }
        !           167:     if (line_pos) { /* need to finish up the line */
        !           168:        for (; line_pos < CHARS_PER_LINE; line_pos++) {
        !           169:            printf("   ");
        !           170:            line_buf[line_pos] = ' ';
        !           171:        }
        !           172:        line_buf[CHARS_PER_LINE] = '\0';
        !           173:        printf("  %s\n", line_buf);
        !           174:     }
        !           175: }
        !           176: 
        !           177: static void
        !           178: printEtherPacket(enet_addr_t * dhost, enet_addr_t * shost, u_short type, 
        !           179:                 u_char * data_p, int n_bytes)
        !           180: {
        !           181:     printEtherHeader(dhost, shost, type);
        !           182:     printData(data_p, n_bytes);
        !           183: }
        !           184: 
        !           185: void
        !           186: printContiguousEtherPacket(u_char * data_p, int n_bytes)
        !           187: {
        !           188:     printEtherPacket((enet_addr_t *)data_p, 
        !           189:                     (enet_addr_t *)(data_p + NUM_EN_ADDR_BYTES), 
        !           190:                     *((u_short *)(data_p + (NUM_EN_ADDR_BYTES * 2))),
        !           191:                     data_p, n_bytes);
        !           192: }
        !           193: 
        !           194: mace_t mace;
        !           195: 
        !           196: #define MACE_DMA_AREA_SIZE (ETHER_RX_NUM_DBDMA_BUFS * ETHERNET_BUF_SIZE + PG_SIZE)
        !           197: static unsigned long mace_rx_dma_area[(MACE_DMA_AREA_SIZE + sizeof(long))/sizeof(long)];
        !           198: 
        !           199: static unsigned long mace_tx_dma_area[(ETHERNET_BUF_SIZE + PG_SIZE + sizeof(long))/sizeof(long)];
        !           200: 
        !           201: /*
        !           202:  * mace_get_hwid
        !           203:  *
        !           204:  *     This function computes the Ethernet Hardware address
        !           205:  *     from PROM. (Its best not to ask how this is done.)
        !           206:  */
        !           207: 
        !           208: unsigned char
        !           209: mace_swapbits(unsigned char bits)
        !           210: {
        !           211:        unsigned char   mask = 0x1, i, newbits = 0;
        !           212: 
        !           213:        for (i = 0x80; i; mask <<= 1, i >>=1) {
        !           214:                if (bits & mask)
        !           215:                        newbits |= i;
        !           216:        }
        !           217: 
        !           218:        return newbits;
        !           219: }
        !           220:        
        !           221: void
        !           222: mace_get_hwid(unsigned char *hwid_addr, mace_t * m)
        !           223: {
        !           224:        int             i;
        !           225: 
        !           226:        for (i = 0; i < NUM_EN_ADDR_BYTES; i++, hwid_addr += 16) {
        !           227:            m->macaddr[i] = mace_swapbits(*hwid_addr);
        !           228:        }
        !           229: }
        !           230: 
        !           231: /*
        !           232:  * mace_reset
        !           233:  *
        !           234:  * Reset the board..
        !           235:  */
        !           236: 
        !           237: void
        !           238: mace_reset()
        !           239: {
        !           240:     dbdma_reset(DBDMA_ETHERNET_RV);
        !           241:     dbdma_reset(DBDMA_ETHERNET_TX);
        !           242: }
        !           243: 
        !           244: 
        !           245: /*
        !           246:  * mace_geteh:
        !           247:  *
        !           248:  *     This function gets the ethernet address (array of 6 unsigned
        !           249:  *     bytes) from the MACE board registers.
        !           250:  *
        !           251:  */
        !           252: 
        !           253: void
        !           254: mace_geteh(char *ep)
        !           255: {
        !           256:     int        i;
        !           257:     unsigned char ep_temp;
        !           258: 
        !           259:     mace.ereg->iac = IAC_PHYADDR; eieio();
        !           260:        
        !           261:     for (i = 0; i < ETHER_ADD_SIZE; i++) {
        !           262:        ep_temp = mace.ereg->padr; eieio();
        !           263:        *ep++ = ep_temp;
        !           264:     }
        !           265: }
        !           266: 
        !           267: /*
        !           268:  * mace_seteh:
        !           269:  *
        !           270:  *     This function sets the ethernet address (array of 6 unsigned
        !           271:  *     bytes) on the MACE board. 
        !           272:  */
        !           273: 
        !           274: static void
        !           275: mace_seteh(char *ep)
        !           276: {
        !           277:     int        i;
        !           278:     unsigned char      status;
        !           279: 
        !           280:     if (mace.chip_id != MACE_REVISION_A2) {
        !           281:        mace.ereg->iac = IAC_ADDRCHG|IAC_PHYADDR; eieio();
        !           282: 
        !           283:        while ((status = mace.ereg->iac)) {
        !           284:            if ((status & IAC_ADDRCHG) == 0) {
        !           285:                eieio();
        !           286:                break;
        !           287:            }
        !           288:            eieio();
        !           289:        }
        !           290:     }
        !           291:     else {
        !           292:        /* start to load the address.. */
        !           293:        mace.ereg->iac = IAC_PHYADDR; eieio();
        !           294:     }
        !           295: 
        !           296:     for (i = 0; i < NUM_EN_ADDR_BYTES; i++) {
        !           297:        mace.ereg->padr = *(ep+i); eieio();
        !           298:     }
        !           299:     return;
        !           300: }
        !           301: 
        !           302: /*
        !           303:  * mace_setup_dbdma
        !           304:  *
        !           305:  * Setup various dbdma pointers.
        !           306:  */
        !           307: 
        !           308: void
        !           309: mace_setup_dbdma()
        !           310: {
        !           311:     mace_t *           m = &mace;
        !           312:     int                        i;
        !           313:     dbdma_command_t *  d;
        !           314:     vm_offset_t                address;
        !           315:     dbdma_regmap_t *   regmap;
        !           316: 
        !           317: #define ALIGN_MASK     0xfffffffcUL
        !           318:     if (m->rv_dma_area == 0) {
        !           319:        m->rv_dma_area = (unsigned char *)
        !           320:            ((((unsigned long)mace_rx_dma_area) + 3) & ALIGN_MASK);
        !           321:        m->rv_dma = dbdma_alloc(ETHER_RX_NUM_DBDMA_BUFS + 2);
        !           322:        m->tx_dma = dbdma_alloc(TX_NUM_DBDMA);
        !           323:        m->tx_dma_area = (unsigned char *)
        !           324:            ((((unsigned long)mace_tx_dma_area) + 3) & ALIGN_MASK);
        !           325:     }
        !           326: 
        !           327:     /* set up a ring of buffers */
        !           328:     d = m->rv_dma;
        !           329:     for (i = 0; i < ETHER_RX_NUM_DBDMA_BUFS; i++, d++) {
        !           330:        address = (vm_offset_t) KVTOPHYS((vm_offset_t)&m->rv_dma_area[i*ETHERNET_BUF_SIZE]);
        !           331:        DBDMA_BUILD(d, DBDMA_CMD_IN_LAST, 0, ETHERNET_BUF_SIZE,
        !           332:                    address, RECEIVE_INT,
        !           333:                    DBDMA_WAIT_NEVER, 
        !           334:                    DBDMA_BRANCH_NEVER);
        !           335:     }
        !           336: 
        !           337:     /* stop when we hit the end of the list */
        !           338:     DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, RECEIVE_INT,
        !           339:                DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
        !           340:     d++;
        !           341: 
        !           342:     /* branch to command at "address" ie. element 0 of the "array" */
        !           343:     DBDMA_BUILD(d, DBDMA_CMD_NOP, 0, 0, 0, DBDMA_INT_NEVER,
        !           344:                DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
        !           345:     address = (vm_offset_t) KVTOPHYS((vm_offset_t)m->rv_dma);
        !           346:     dbdma_st4_endian(&d->d_cmddep, address);
        !           347: 
        !           348:     m->rv_head = 0;
        !           349:     m->rv_tail = ETHER_RX_NUM_DBDMA_BUFS; /* always contains DBDMA_CMD_STOP */
        !           350: 
        !           351:     /* stop/init/restart dma channel */
        !           352:     dbdma_reset(DBDMA_ETHERNET_RV);
        !           353:     dbdma_reset(DBDMA_ETHERNET_TX);
        !           354: 
        !           355:     /* Set the wait value.. */
        !           356:     regmap = DBDMA_REGMAP(DBDMA_ETHERNET_RV);
        !           357:     dbdma_st4_endian(&regmap->d_wait, DBDMA_SET_CNTRL(0x00));
        !           358: 
        !           359:     /* Set the tx wait value */
        !           360:     regmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
        !           361:     dbdma_st4_endian(&regmap->d_wait, DBDMA_SET_CNTRL(0x20));
        !           362: 
        !           363:     flush_cache_v((vm_offset_t)m->rv_dma, 
        !           364:                  sizeof(dbdma_command_t) * (ETHER_RX_NUM_DBDMA_BUFS + 2));
        !           365:     /* start receiving */
        !           366:     dbdma_start(DBDMA_ETHERNET_RV, m->rv_dma);
        !           367: }
        !           368: 
        !           369: #ifdef MACE_DEBUG
        !           370: static unsigned char testBuffer[PG_SIZE * 4];
        !           371: static unsigned char testMsg[] = "mace ethernet interface test";
        !           372: 
        !           373: static void
        !           374: send_test_packet()
        !           375: {
        !           376:     unsigned char * tp;
        !           377: 
        !           378:     bzero(testBuffer, sizeof(testBuffer));
        !           379: 
        !           380:     tp = testBuffer;
        !           381: 
        !           382:     /* send self-addressed packet */
        !           383:     bcopy(&mace.macaddr[0], tp, NUM_EN_ADDR_BYTES);
        !           384:     tp += NUM_EN_ADDR_BYTES;
        !           385:     bcopy(&mace.macaddr[0], tp, NUM_EN_ADDR_BYTES);
        !           386:     tp += NUM_EN_ADDR_BYTES;
        !           387:     *tp++ = 0;
        !           388:     *tp++ = 0;
        !           389:     bcopy(testMsg, tp, sizeof(testMsg));
        !           390:     polled_send_pkt(testBuffer, 80);
        !           391:     return;
        !           392: }
        !           393: #endif
        !           394: 
        !           395: /*
        !           396:  * Function: init_mace
        !           397:  *
        !           398:  * Purpose:
        !           399:  *   Called early on, initializes the adapter and readies it for
        !           400:  *   kdb kernel debugging. 
        !           401:  */
        !           402: void
        !           403: init_mace()
        !           404: {
        !           405:     unsigned char      status;
        !           406:     mace_t *           m = &mace;
        !           407:     struct mace_board * ereg;
        !           408:     int                mpc = 0;
        !           409: 
        !           410:     /*
        !           411:      * Only use in-kernel driver for early debugging (bootargs: kdp=1 or kdp=3)
        !           412:      */
        !           413:     if ( (kdp_flag & 1) == 0 )
        !           414:     {
        !           415:       return;
        !           416:     }
        !           417: 
        !           418:     bzero(&mace, sizeof(mace));
        !           419: 
        !           420:     /* get the ethernet registers' mapped address */
        !           421:     ereg = m->ereg 
        !           422:        = (struct mace_board *) POWERMAC_IO(PCI_ETHERNET_BASE_PHYS);
        !           423:     mace_get_hwid((unsigned char *)POWERMAC_IO(PCI_ETHERNET_ADDR_PHYS), m);
        !           424: 
        !           425:     /* Reset the board & AMIC.. */
        !           426:     mace_reset();
        !           427: 
        !           428:     /* grab the MACE chip rev  */
        !           429:     m->chip_id = (ereg->chipid2 << 8 | ereg->chipid1);
        !           430: 
        !           431:     /* don't auto-strip for 802.3 */
        !           432:     m->ereg->rcvfc &= ~(RCVFC_ASTRPRCV);
        !           433: 
        !           434:     /* set the ethernet address */
        !           435:     mace_seteh(mace.macaddr);
        !           436:     {
        !           437:        unsigned char macaddr[NUM_EN_ADDR_BYTES];
        !           438:        mace_geteh(macaddr);
        !           439:        printf("mace ethernet [%02x:%02x:%02x:%02x:%02x:%02x]\n",
        !           440:                macaddr[0], macaddr[1], macaddr[2], 
        !           441:                macaddr[3], macaddr[4], macaddr[5]);
        !           442:     }
        !           443: 
        !           444:     /* Now clear the Multicast filter */
        !           445:     if (m->chip_id != MACE_REVISION_A2) {
        !           446:        ereg->iac = IAC_ADDRCHG|IAC_LOGADDR; eieio();
        !           447: 
        !           448:        while ((status = ereg->iac)) {
        !           449:            if ((status & IAC_ADDRCHG) == 0)
        !           450:                break;
        !           451:            eieio();
        !           452:        }
        !           453:        eieio();
        !           454:     }
        !           455:     else {
        !           456:        ereg->iac = IAC_LOGADDR; eieio();
        !           457:     }
        !           458:     {
        !           459:        int i;
        !           460: 
        !           461:        for (i=0; i < 8; i++) 
        !           462:        {    ereg->ladrf = 0;
        !           463:             eieio();
        !           464:         }
        !           465:     }
        !           466: 
        !           467:     /* register interrupt routines */
        !           468:     mace_setup_dbdma();
        !           469: 
        !           470:     /* Start the chip... */
        !           471:     m->ereg->maccc = MACCC_ENXMT|MACCC_ENRCV; eieio();
        !           472:     {
        !           473:        volatile char ch =  mace.ereg->ir; eieio();
        !           474:     }
        !           475: 
        !           476:     delay(500); /* paranoia */
        !           477:     mace.ereg->imr = 0xfe; eieio();
        !           478: 
        !           479:     /* register our debugger routines */
        !           480:     kdp_register_send_receive((kdp_send_t)polled_send_pkt, 
        !           481:                              (kdp_receive_t)polled_receive_pkt);
        !           482: 
        !           483: #if 0
        !           484:     printf("Testing 1 2 3\n");
        !           485:     send_test_packet();
        !           486:     printf("Testing 1 2 3\n");
        !           487:     send_test_packet();
        !           488:     printf("Testing 1 2 3\n");
        !           489:     send_test_packet();
        !           490:     do {
        !           491:        static unsigned char buf[ETHERNET_BUF_SIZE];
        !           492:        int len;
        !           493:        int nmpc = mace.ereg->mpc; eieio();
        !           494: 
        !           495:        if (nmpc > mpc) {
        !           496:            mpc = nmpc;
        !           497:            printf("mpc %d\n", mpc);
        !           498:        }
        !           499:        polled_receive_pkt(buf, &len, 100);
        !           500:        if (len > 0) {
        !           501:            printf("rx %d\n", len);
        !           502:            printContiguousEtherPacket(buf, len);
        !           503:        }
        !           504:     } while(1);
        !           505: #endif
        !           506: 
        !           507:     return;
        !           508: }
        !           509: 
        !           510: #ifdef MACE_DEBUG
        !           511: static void
        !           512: txstatus(char * msg)
        !           513: {
        !           514:     volatile dbdma_regmap_t *  dmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
        !           515:     volatile unsigned long             status;
        !           516:     volatile unsigned long             intr;
        !           517:     volatile unsigned long             branch;
        !           518:     volatile unsigned long             wait;
        !           519: 
        !           520:     status = dbdma_ld4_endian(&dmap->d_status); eieio();
        !           521:     intr = dbdma_ld4_endian(&dmap->d_intselect); eieio();
        !           522:     branch = dbdma_ld4_endian(&dmap->d_branch); eieio();
        !           523:     wait = dbdma_ld4_endian(&dmap->d_wait); eieio();
        !           524:     printf("(%s s=0x%x i=0x%x b=0x%x w=0x%x)", msg, status, intr, branch,
        !           525:           wait);
        !           526:     return;
        !           527: }
        !           528: #endif
        !           529: 
        !           530: static void
        !           531: tx_dbdma(char * data, int len)
        !           532: {
        !           533:     unsigned long      count;
        !           534:     dbdma_command_t *  d;
        !           535:     unsigned long      page;
        !           536: 
        !           537:     d = mace.tx_dma;
        !           538:     page = ((unsigned long) data) & PG_MASK;
        !           539:     if ((page + len) <= PG_SIZE) { /* one piece dma */
        !           540:        DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0,
        !           541:                    len,
        !           542:                    (vm_offset_t) KVTOPHYS((vm_offset_t) data),
        !           543:                    DBDMA_INT_NEVER, 
        !           544:                    DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER);
        !           545:     }
        !           546:     else { /* two piece dma */
        !           547:        count = PG_SIZE - page;
        !           548:        DBDMA_BUILD(d, DBDMA_CMD_OUT_MORE, DBDMA_KEY_STREAM0,
        !           549:                    count,
        !           550:                    (vm_offset_t)KVTOPHYS((vm_offset_t) data),
        !           551:                    DBDMA_INT_NEVER, 
        !           552:                    DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
        !           553:        d++;
        !           554:        DBDMA_BUILD(d, DBDMA_CMD_OUT_LAST, DBDMA_KEY_STREAM0, 
        !           555:                    len - count, (vm_offset_t)
        !           556:                    KVTOPHYS((vm_offset_t)((unsigned char *)data + count)),
        !           557:                    DBDMA_INT_NEVER, 
        !           558:                    DBDMA_WAIT_IF_FALSE, DBDMA_BRANCH_NEVER);
        !           559:     }
        !           560:     d++;
        !           561:     DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM,
        !           562:                1, KVTOPHYS((vm_offset_t) &mace.ereg->xmtfs),DBDMA_INT_NEVER, 
        !           563:                DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
        !           564:     d++;
        !           565:     DBDMA_BUILD(d, DBDMA_CMD_LOAD_QUAD, DBDMA_KEY_SYSTEM,
        !           566:                1, KVTOPHYS((vm_offset_t) &mace.ereg->ir), DBDMA_INT_ALWAYS,
        !           567:                DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
        !           568:     d++;
        !           569:     DBDMA_BUILD(d, DBDMA_CMD_STOP, 0, 0, 0, 0, 0, 0);
        !           570:     flush_cache_v((vm_offset_t)mace.tx_dma, sizeof(dbdma_command_t) * TX_NUM_DBDMA);
        !           571:     dbdma_start(DBDMA_ETHERNET_TX, mace.tx_dma);
        !           572:     return;
        !           573: 
        !           574: }
        !           575: 
        !           576: static void
        !           577: waitForDBDMADone(char * msg)
        !           578: {
        !           579:     {
        !           580:        /* wait for tx dma completion */
        !           581:        volatile dbdma_regmap_t *       dmap = DBDMA_REGMAP(DBDMA_ETHERNET_TX);
        !           582:        int                             i;
        !           583:        volatile unsigned long          val;
        !           584: 
        !           585:        i = 0;
        !           586:        do {
        !           587:            val = dbdma_ld4_endian(&dmap->d_status); eieio();
        !           588:            delay(50);
        !           589:            i++;
        !           590:        } while ((i < 100000) && (val & DBDMA_CNTRL_ACTIVE));
        !           591:        if (i == 100000)
        !           592:            printf("mace(%s): tx_dbdma poll timed out 0x%x", msg, val);
        !           593:     }
        !           594: }
        !           595: 
        !           596: void
        !           597: mace_service_queue(struct ifnet * ifp)
        !           598: {
        !           599:     unsigned char *    buf_p;
        !           600:     struct mbuf *      m;
        !           601:     struct mbuf *       mp;
        !           602:     int                        len;
        !           603: 
        !           604:     if (mace.tx_busy) { /* transmit in progress? */
        !           605:        return;
        !           606:     }
        !           607: 
        !           608:     IF_DEQUEUE(&(ifp->if_snd), m);
        !           609:     if (m == 0) {
        !           610:         return;
        !           611:     }
        !           612: 
        !           613:     len = m->m_pkthdr.len;
        !           614: 
        !           615:     if (len > ETHERMAXPACKET) {
        !           616:        printf("mace_start: packet too big (%d), dropping\n", len);
        !           617:        m_freem(m);
        !           618:        return;
        !           619:        
        !           620:     }
        !           621:     buf_p = mace.tx_dma_area;
        !           622:     if (m->m_nextpkt) {
        !           623:        printf("mace: sending more than one mbuf\n");
        !           624:     }
        !           625:     for (mp = m; mp; mp = mp->m_next) {
        !           626:        if (mp->m_len == 0)
        !           627:            continue;
        !           628:        bcopy(mtod(mp, caddr_t), buf_p, min(mp->m_len, len));
        !           629:        len -= mp->m_len;
        !           630:        buf_p += mp->m_len;
        !           631:     }
        !           632:     m_freem(m);
        !           633: 
        !           634: #if NBPFILTER > 0
        !           635:     if (ifp->if_bpf)
        !           636:        BPF_TAP(ifp->if_bpf, mace.tx_dma_area, m->m_pkthdr.len);
        !           637: #endif
        !           638: 
        !           639: #if 0
        !           640:     printf("tx packet %d\n", m->m_pkthdr.len);
        !           641:     printContiguousEtherPacket(mace.tx_dma_area, m->m_pkthdr.len);
        !           642: #endif
        !           643: 
        !           644:     /* fill in the dbdma records and kick off the dma */
        !           645:     tx_dbdma(mace.tx_dma_area, m->m_pkthdr.len);
        !           646:     mace.tx_busy = 1;
        !           647:     return;
        !           648: }
        !           649: 
        !           650: #ifdef MACE_DEBUG
        !           651: static int
        !           652: mace_watchdog()
        !           653: {
        !           654:     struct ifnet * ifp = &mace.en_arpcom.ac_if;
        !           655:     int s;
        !           656: 
        !           657:     mace.txwatchdog++;
        !           658:     s = splnet();
        !           659:     if (mace.rxintr == 0) {
        !           660:       printf("rx is hung up\n");
        !           661:       rx_intr();
        !           662:     }
        !           663:     mace.rxintr = 0;
        !           664: #if 0
        !           665:     if (mace.txintr == 0 && ifp->if_snd.ifq_head) {
        !           666:        if (mace.tx_busy)
        !           667:            dbdma_stop(DBDMA_ETHERNET_TX);
        !           668:        mace.tx_busy = 0;
        !           669:        mace_service_queue(ifp);
        !           670:     }
        !           671:     mace.txintr = 0;
        !           672: #endif
        !           673:     timeout(mace_watchdog, 0, 10*hz); /* just in case we drop an interrupt */
        !           674:     return (0);
        !           675: }
        !           676: #endif /* MACE_DEBUG */
        !           677: 
        !           678: static int
        !           679: mace_start(struct ifnet        * ifp)
        !           680: {
        !           681: //    int i = mace.tx_busy;
        !           682: 
        !           683: //    printf("mace_start %s\n", mace.tx_busy ? "(txBusy)" : "");
        !           684:     mace_service_queue(ifp);
        !           685: 
        !           686: //    if (mace.tx_busy && !i)
        !           687: //     printf("(txStarted)\n");
        !           688:     return 0;
        !           689: }
        !           690: 
        !           691: int
        !           692: mace_recv_pkt(funcptr pktfunc, void * p)
        !           693: {
        !           694:     vm_offset_t                        address;
        !           695:     struct mace_board *                board;
        !           696:     long                       bytes;
        !           697:     int                                done = 0;
        !           698:     int                                doContinue = 0;
        !           699:     mace_t *                   m;
        !           700:     unsigned long              resid;
        !           701:     unsigned short             status;
        !           702:     int                                tail;
        !           703: 
        !           704:     m = &mace;
        !           705:     board = m->ereg;
        !           706: 
        !           707:     /* remember where the tail was */
        !           708:     tail = m->rv_tail;
        !           709:     for (done = 0; (done == 0) && (m->rv_head != tail);) {
        !           710:        dbdma_command_t *       dmaHead;
        !           711:        
        !           712:        dmaHead = &m->rv_dma[m->rv_head];
        !           713:        resid = dbdma_ld4_endian(&dmaHead->d_status_resid);
        !           714:        status = (resid >> 16);
        !           715:        bytes  = resid & 0xffff;
        !           716:        bytes = ETHERNET_BUF_SIZE - bytes - 8; /* strip off FCS/CRC */
        !           717: 
        !           718:        if ((status & DBDMA_ETHERNET_EOP) == 0)  {
        !           719:            /* no packets are ready yet */
        !           720:            break;
        !           721:        }
        !           722:        doContinue = 1;
        !           723:        /* if the packet is good, pass it up */
        !           724:        if (bytes >= (ETHER_MIN_PACKET - 4)) {
        !           725:            char * dmaPacket;
        !           726:            dmaPacket = &m->rv_dma_area[m->rv_head * ETHERNET_BUF_SIZE];
        !           727:            done = (*pktfunc)(dmaPacket, bytes, p);
        !           728:        }
        !           729:        /* mark the head as the new tail in the dma channel command list */
        !           730:        DBDMA_BUILD(dmaHead, DBDMA_CMD_STOP, 0, 0, 0, RECEIVE_INT,
        !           731:                    DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
        !           732:        flush_cache_v((vm_offset_t)dmaHead, sizeof(*dmaHead));
        !           733:        eieio();
        !           734: 
        !           735:        /* make the tail an available dma'able entry */
        !           736:        {
        !           737:            dbdma_command_t *           dmaTail;
        !           738:            dmaTail = &m->rv_dma[m->rv_tail];
        !           739:            address = KVTOPHYS((vm_offset_t) 
        !           740:                               &m->rv_dma_area[m->rv_tail*ETHERNET_BUF_SIZE]);
        !           741:            // this command is live so write it carefully
        !           742:            DBDMA_ST4_ENDIAN(&dmaTail->d_address, address);
        !           743:            dmaTail->d_status_resid = 0;
        !           744:            dmaTail->d_cmddep = 0;
        !           745:            eieio();
        !           746:            DBDMA_ST4_ENDIAN(&dmaTail->d_cmd_count,
        !           747:                            ((DBDMA_CMD_IN_LAST) << 28) | ((0) << 24) |
        !           748:                            ((RECEIVE_INT) << 20) |
        !           749:                            ((DBDMA_BRANCH_NEVER) << 18) | ((DBDMA_WAIT_NEVER) << 16) |
        !           750:                            (ETHERNET_BUF_SIZE));
        !           751:            eieio();
        !           752:            flush_cache_v((vm_offset_t)dmaTail, sizeof(*dmaTail));
        !           753:        }
        !           754:        /* head becomes the tail */
        !           755:        m->rv_tail = m->rv_head;
        !           756: 
        !           757:        /* advance the head */
        !           758:        m->rv_head++;
        !           759:        if (m->rv_head == (ETHER_RX_NUM_DBDMA_BUFS + 1))
        !           760:            m->rv_head = 0;
        !           761:     }
        !           762:     if (doContinue) {
        !           763:        sync();
        !           764:        dbdma_continue(DBDMA_ETHERNET_RV);
        !           765:     }
        !           766:     return (done);
        !           767: }
        !           768: 
        !           769: /* kdb handle buffer routines */
        !           770: struct kdbCopy {
        !           771:     int *      len;
        !           772:     char *     data;
        !           773: };
        !           774: 
        !           775: static int
        !           776: kdb_copy(char * pktBuf, int len, void * p)
        !           777: {
        !           778:     struct kdbCopy * cp = (struct kdbCopy *)p;
        !           779: 
        !           780:     bcopy(pktBuf, cp->data, len);
        !           781:     *cp->len = len;
        !           782:     return (1); /* signal that we're done */
        !           783: }
        !           784: 
        !           785: /* kdb debugger routines */
        !           786: static void
        !           787: polled_send_pkt(char * data, int len)
        !           788: {
        !           789:     waitForDBDMADone("mace: polled_send_pkt start");
        !           790:     tx_dbdma(data, len);
        !           791:     waitForDBDMADone("mace: polled_send_pkt end");
        !           792:     return;
        !           793: }
        !           794: 
        !           795: static void
        !           796: polled_receive_pkt(char *data, int *len, int timeout_ms)
        !           797: {
        !           798:     struct kdbCopy cp;
        !           799: 
        !           800:     cp.len = len;
        !           801:     cp.data = data;
        !           802: 
        !           803:     timeout_ms *= 1000;
        !           804:     *len = 0;
        !           805:     while (mace_recv_pkt(kdb_copy, (void *)&cp) == 0) {
        !           806:        if (timeout_ms <= 0)
        !           807:            break;
        !           808:        delay(50);
        !           809:        timeout_ms -= 50;
        !           810:     }
        !           811:     return;
        !           812: }
        !           813: 
        !           814: /* Bump to force ethernet data to be 4-byte aligned
        !           815:  *  (since the ethernet header is 14 bytes, and the 802.3 header is
        !           816:  *  22 = 14+8 bytes).  This assumes that m_data is word-aligned
        !           817:  *  (which it is).
        !           818:  */
        !           819: #define ETHER_DATA_ALIGN       2
        !           820: 
        !           821: /*
        !           822:  * Function: rxpkt
        !           823:  *
        !           824:  * Purpose:
        !           825:  *   Called from within mace_recv_pkt to deal with a packet of data.
        !           826:  *   rxpkt() allocates an mbuf(+cluser) and passes it up to the stacks.
        !           827:  * Returns:
        !           828:  *   0 if the packet was copied to an mbuf, 1 otherwise
        !           829:  */
        !           830: static int
        !           831: rxpkt(char * data, int len, void * p)
        !           832: {
        !           833:     struct ether_header *      eh_p = (struct ether_header *)data;
        !           834:     struct ifnet *             ifp = &mace.en_arpcom.ac_if;
        !           835:     struct mbuf *              m;
        !           836: 
        !           837:     int                                interesting;
        !           838: 
        !           839:     mace.rxintr++;
        !           840: 
        !           841:     /* mcast, bcast -- we're interested in either */
        !           842:     interesting = eh_p->ether_dhost[0] & 1;
        !           843: 
        !           844: #if NBPFILTER > 0
        !           845:     /*
        !           846:      * Check if there's a bpf filter listening on this interface.
        !           847:      * If so, hand off the raw packet to bpf_tap().
        !           848:      */
        !           849:     if (ifp->if_bpf) {
        !           850:        BPF_TAP(ifp->if_bpf, data, len);
        !           851: 
        !           852:        /*
        !           853:         * Keep the packet if it's a broadcast or has our
        !           854:         * physical ethernet address (or if we support
        !           855:         * multicast and it's one).
        !           856:         */
        !           857:        if ((interesting == 0) && bcmp(eh_p->ether_dhost, mace.macaddr,
        !           858:           sizeof(eh_p->ether_dhost)) != 0) {
        !           859:        return (1);
        !           860:     }
        !           861:     }
        !           862: #endif
        !           863: 
        !           864:     /*
        !           865:      * We "know" a full-sized packet fits in one cluster.  Set up the
        !           866:      *  packet header, and if the length is sufficient, attempt to allocate
        !           867:      *  a cluster.  If that fails, fall back to the old way (m_devget()).
        !           868:      *  Here, we take the simple approach of cluster vs. single mbuf.
        !           869:      */
        !           870:     MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           871:     if (m == 0) {
        !           872: #ifdef MACE_DEBUG
        !           873:        printf("mget failed\n");
        !           874: #endif
        !           875:        return (1);
        !           876:     }
        !           877: 
        !           878:     if (len > (MHLEN - ETHER_DATA_ALIGN))
        !           879:     {   MCLGET(m, M_DONTWAIT);
        !           880:        if (m->m_flags&M_EXT)   /* MCLGET succeeded */
        !           881:        {       m->m_data += ETHER_DATA_ALIGN;
        !           882:                bcopy(data, mtod(m, caddr_t), (unsigned)len);
        !           883:        } else
        !           884:        {
        !           885: #ifdef MACE_DEBUG
        !           886:                printf("no clusters\n");
        !           887: #endif
        !           888:                m_free(m);
        !           889:                m = (struct mbuf *)m_devget(data, len, 0, ifp, 0);
        !           890:                if (m == 0)
        !           891:                        return (1);
        !           892:        }
        !           893:     } else
        !           894:     {  m->m_data += ETHER_DATA_ALIGN;
        !           895:        bcopy(data, mtod(m, caddr_t), (unsigned)len);
        !           896:     }
        !           897: 
        !           898:     /*
        !           899:      * Current code up the line assumes that the media header's been
        !           900:      *  stripped, but we'd like to preserve it, just in case someone
        !           901:      *  wants to peek.
        !           902:      */
        !           903:     m->m_pkthdr.len = len;
        !           904:     m->m_len = len;
        !           905:     m->m_pkthdr.rcvif = ifp;
        !           906:     m->m_data += sizeof(*eh_p);
        !           907:     m->m_len -= sizeof (*eh_p);
        !           908:     m->m_pkthdr.len -= sizeof(*eh_p);
        !           909:     ether_input(ifp, eh_p, m);
        !           910: 
        !           911:     return (0);
        !           912: }
        !           913: 
        !           914: 
        !           915: static void
        !           916: rx_intr()
        !           917: {
        !           918:     mace_recv_pkt(rxpkt, 0);
        !           919: }
        !           920: 
        !           921: void
        !           922: mace_dbdma_rx_intr(int unit, void *ignored, void * arp)
        !           923: {
        !           924:     if (!mace.ready)
        !           925:        return;
        !           926: 
        !           927:     thread_call_func((thread_call_func_t)rx_intr, 0, TRUE);
        !           928: }
        !           929: 
        !           930: 
        !           931: int
        !           932: mace_ioctl(struct ifnet * ifp,u_long cmd, caddr_t data)
        !           933: {
        !           934:        struct arpcom *                 ar;
        !           935:        unsigned                        error = 0;
        !           936:        struct ifaddr *                 ifa = (struct ifaddr *)data;
        !           937:        struct ifreq *                  ifr = (struct ifreq *)data;
        !           938:        struct sockaddr_in *            sin;
        !           939: 
        !           940:        sin = (struct sockaddr_in *)(&((struct ifreq *)data)->ifr_addr);
        !           941:        ar = (struct arpcom *)ifp;
        !           942: 
        !           943:        switch (cmd) {
        !           944:          case SIOCAUTOADDR:
        !           945:            error = in_bootp(ifp, sin, &mace.en_arpcom.ac_enaddr);
        !           946:            break;
        !           947: 
        !           948:        case SIOCSIFADDR:
        !           949: #if NeXT
        !           950:                ifp->if_flags |= (IFF_UP | IFF_RUNNING);
        !           951: #else
        !           952:                ifp->if_flags |= IFF_UP;
        !           953: #endif
        !           954:                switch (ifa->ifa_addr->sa_family) {
        !           955:                case AF_INET:
        !           956:                        /*
        !           957:                         * See if another station has *our* IP address.
        !           958:                         * i.e.: There is an address conflict! If a
        !           959:                         * conflict exists, a message is sent to the
        !           960:                         * console.
        !           961:                         */
        !           962:                        if (IA_SIN(ifa)->sin_addr.s_addr != 0) { /* don't bother for 0.0.0.0 */
        !           963:                        ar->ac_ipaddr = IA_SIN(ifa)->sin_addr;
        !           964:                        arpwhohas(ar, &IA_SIN(ifa)->sin_addr);
        !           965:                        }
        !           966:                        break;
        !           967:                default:
        !           968:                        break;
        !           969:                }
        !           970:                break;
        !           971: 
        !           972:        case SIOCSIFFLAGS:
        !           973:                /*
        !           974:                 * If interface is marked down and it is running, then stop it
        !           975:                 */
        !           976:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           977:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !           978:                        /*
        !           979:                         * If interface is marked down and it is running, then
        !           980:                         * stop it.
        !           981:                         */
        !           982:                        ifp->if_flags &= ~IFF_RUNNING;
        !           983:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !           984:                           (ifp->if_flags & IFF_RUNNING) == 0) {
        !           985:                        /*
        !           986:                         * If interface is marked up and it is stopped, then
        !           987:                         * start it.
        !           988:                         */
        !           989:                        ifp->if_flags |= IFF_RUNNING;
        !           990:                }
        !           991: 
        !           992:                /*
        !           993:                 * If the state of the promiscuous bit changes, the
        !           994:                 * interface must be reset to effect the change.
        !           995:                 */
        !           996:                if (((ifp->if_flags ^ mace.promisc) & IFF_PROMISC) &&
        !           997:                    (ifp->if_flags & IFF_RUNNING)) {
        !           998:                        mace.promisc = ifp->if_flags & IFF_PROMISC;
        !           999:                        mace_sync_promisc(ifp);
        !          1000:                }
        !          1001: 
        !          1002:                break;
        !          1003: 
        !          1004:        case SIOCADDMULTI:
        !          1005:                if ((error = ether_addmulti(ifr, ar)) == ENETRESET)
        !          1006:                {       if ((error = mace_addmulti(ifr, ar)) != 0)
        !          1007:                        {       error = 0;
        !          1008:                                mace_sync_mcast(ifp);
        !          1009:                        }
        !          1010:                }
        !          1011:                break;
        !          1012: 
        !          1013:        case SIOCDELMULTI:
        !          1014:                { 
        !          1015:                    struct ether_addr enaddr[2]; /* [0] - addrlo, [1] - addrhi */
        !          1016: 
        !          1017:                    if ((error = ether_delmulti(ifr, ar, enaddr)) == ENETRESET) {
        !          1018:                        if ((error = mace_delmulti(ifr, ar, enaddr)) != 0) {
        !          1019:                            error = 0;
        !          1020:                            mace_sync_mcast(ifp);
        !          1021:                        }
        !          1022:                    }
        !          1023:                }
        !          1024:                break;
        !          1025: 
        !          1026:        default:
        !          1027:            error = EINVAL;
        !          1028:            break;
        !          1029:     }
        !          1030:     return (error);
        !          1031: }
        !          1032: 
        !          1033: void
        !          1034: mace_init()
        !          1035: {
        !          1036:     struct ifnet * ifp = &mace.en_arpcom.ac_if;
        !          1037: 
        !          1038:     /*
        !          1039:      * Only use in-kernel driver for early debugging (bootargs: kdp=1|3)
        !          1040:      */
        !          1041:     if ( (kdp_flag & 1) == 0 )
        !          1042:     {
        !          1043:       return;
        !          1044:     }
        !          1045: 
        !          1046:     mace.tx_busy = 0;
        !          1047:     mace.txintr = 0;
        !          1048:     mace.promisc = 0;
        !          1049: 
        !          1050:     bzero((caddr_t)ifp, sizeof(struct ifnet));
        !          1051:     bcopy(&mace.macaddr, &mace.en_arpcom.ac_enaddr, NUM_EN_ADDR_BYTES);
        !          1052: 
        !          1053:     ifp->if_name = "en";
        !          1054:     ifp->if_unit = 0;
        !          1055:     ifp->if_private = 0;
        !          1056:     ifp->if_ioctl = mace_ioctl;
        !          1057:     ifp->if_start = mace_start;
        !          1058:     ifp->if_flags =
        !          1059:        IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
        !          1060: #if NBPFILTER > 0
        !          1061:     bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
        !          1062: #endif
        !          1063:     if_attach(ifp);
        !          1064:     ether_ifattach(ifp);
        !          1065: 
        !          1066:     mace.rxintr = 0;
        !          1067: 
        !          1068:     /* wire in the interrupt routines */
        !          1069:     pmac_register_int(PMAC_DMA_ETHERNET_RX, SPLNET,
        !          1070:                      mace_dbdma_rx_intr, 0);
        !          1071:     pmac_register_int(PMAC_DMA_ETHERNET_TX, SPLNET,
        !          1072:                      mace_dbdma_tx_intr, 0);
        !          1073: 
        !          1074: //    pmac_register_int(PMAC_DEV_ETHERNET, SPLNET, mace_pci_intr);
        !          1075:     mace.ready = 1;
        !          1076: #ifdef MACE_DEBUG
        !          1077:     timeout(mace_watchdog, 0, 10*hz); /* just in case we drop an interrupt */
        !          1078: #endif
        !          1079:     return;
        !          1080: }
        !          1081: 
        !          1082: /*
        !          1083:  * mace_pci_intr
        !          1084:  *
        !          1085:  * Service MACE interrupt
        !          1086:  */
        !          1087: 
        !          1088: void
        !          1089: mace_pci_intr(int device, void *ssp)
        !          1090: {
        !          1091:     unsigned char      ir, retry, frame, packet, length;
        !          1092: 
        !          1093:     ir = mace.ereg->ir; eieio();       /* Clear Interrupt */
        !          1094:     packet = mace.ereg->mpc; eieio();
        !          1095:     length = mace.ereg->rntpc; eieio();
        !          1096: 
        !          1097:     printf("(txI)");
        !          1098: 
        !          1099:     if (ir & IR_XMTINT) {
        !          1100:        retry = mace.ereg->xmtrc; eieio();      /* Grab transmit retry count */
        !          1101:        frame = mace.ereg->xmtfs; eieio();
        !          1102: //     if (mace.ready)
        !          1103: //         mace_dbdma_tx_intr(device, ssp);
        !          1104:     }
        !          1105:     return;
        !          1106: }
        !          1107: 
        !          1108: static void
        !          1109: tx_intr()
        !          1110: {
        !          1111:     mace.txintr++;
        !          1112:     mace.tx_busy = 0;
        !          1113:     mace_service_queue(&mace.en_arpcom.ac_if);
        !          1114: }
        !          1115: 
        !          1116: /* 
        !          1117:  * mace_dbdma_tx_intr
        !          1118:  *
        !          1119:  * DBDMA interrupt routine
        !          1120:  */
        !          1121: void
        !          1122: mace_dbdma_tx_intr(int unit, void *ignored, void * arg)
        !          1123: {
        !          1124:     if (!mace.ready)
        !          1125:        return;
        !          1126: 
        !          1127:     thread_call_func((thread_call_func_t)tx_intr, 0, TRUE);
        !          1128:     return;
        !          1129: }

unix.superglobalmegacorp.com

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