Annotation of kernel/bsd/if/ppc/if_en.c, revision 1.1.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.