Annotation of XNU/bsd/if/ppc/if_en.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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