Annotation of kernel/bsd/if/ppc/if_en.c, revision 1.1

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

unix.superglobalmegacorp.com

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