Annotation of driverkit/libDriver/Kernel/IOEthernet.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: /*
        !            25:  * Copyright (c) 1992 NeXT Computer, Inc.
        !            26:  *
        !            27:  * Device independent abstract superclass for Ethernet.
        !            28:  *
        !            29:  * HISTORY
        !            30:  *
        !            31:  * 25 September 1992 David E. Bohman at NeXT
        !            32:  *     Created.
        !            33:  *
        !            34:  *  4 April 1993 Joel D. Greenblatt at NeXT
        !            35:  *     Integrated multicast & promiscuous mode support.
        !            36:  */
        !            37: 
        !            38: #define MACH_USER_API  1
        !            39: 
        !            40: #import <mach/mach_types.h>
        !            41: #import <mach/message.h>
        !            42: 
        !            43: #import <machkit/NXLock.h>
        !            44: 
        !            45: #import <driverkit/generalFuncs.h>
        !            46: #import <driverkit/interruptMsg.h>
        !            47: 
        !            48: #import <sys/errno.h>
        !            49: #import <sys/socket.h>
        !            50: #ifndef NEXT
        !            51: #define NEXT 1
        !            52: #endif
        !            53: #import <sys/sockio.h>
        !            54: 
        !            55: #import <driverkit/IOEthernet.h>
        !            56: #import <driverkit/IOEthernetPrivate.h>
        !            57: #import        <netinet/in_var.h>
        !            58: #import        <netinet/if_ether.h>
        !            59: 
        !            60: #import <net/bpf.h>
        !            61: 
        !            62: #define min(a, b)      (((a) < (b)) ? (a) : (b))
        !            63: 
        !            64: /*
        !            65:  * Allowable values for _net_buf_type
        !            66:  */
        !            67: enum {
        !            68:        _NET_BUF_TYPE_NETBUF,   // netbuf
        !            69:        _NET_BUF_TYPE_MBUF,             // mbuf
        !            70: };
        !            71: 
        !            72: static void
        !            73: IOEthernetTimeout(IOEthernet   *device);
        !            74: 
        !            75: static char    IOEthernetDeviceName[] = "en",
        !            76:                IOEthernetDeviceType[] = "Ethernet";
        !            77: static int     IOEthernetDeviceCount = 0;
        !            78: 
        !            79: 
        !            80: @interface DriverCmd:Object
        !            81: {
        !            82: @private
        !            83:     port_t             _driverPort_kern;
        !            84:     id                 _interLock;
        !            85: #define DONE           1
        !            86: #define BUSY           2
        !            87: #define IDLE           3
        !            88:     int                        _oper;
        !            89: #define RESET_ON               1
        !            90: #define RESET_OFF              2
        !            91: #define TERMINATE              4
        !            92: #define PROMISC_ENABLE         5
        !            93: #define        PROMISC_DISABLE         6
        !            94: #define        MULTICAST_ENABLE        7 
        !            95: #define        MULTICAST_DISABLE       8 
        !            96:     int                        _ret;
        !            97:     void *             _param;
        !            98: }
        !            99: @end
        !           100: 
        !           101: @implementation DriverCmd
        !           102: 
        !           103: - initPort:(port_t)port
        !           104: {
        !           105:     [super init];
        !           106: 
        !           107:     _interLock = [[NXConditionLock alloc] initWith:IDLE];
        !           108:     
        !           109:     _driverPort_kern = IOGetKernPort(port);
        !           110:     
        !           111:     return self;
        !           112: }
        !           113: 
        !           114: - free
        !           115: {
        !           116:     [_interLock free];
        !           117:     
        !           118:     port_release(_driverPort_kern);
        !           119:     
        !           120:     return [super free];
        !           121: }
        !           122: 
        !           123: - (int)oper
        !           124: {
        !           125:     return (_oper);
        !           126: }
        !           127: 
        !           128: - (void *)param
        !           129: {
        !           130:     return (_param);
        !           131: }
        !           132: 
        !           133: - (void)done:(int)ret
        !           134: {
        !           135:     if ([_interLock condition] == BUSY) {
        !           136:        [_interLock lock];
        !           137:        _ret = ret;
        !           138:        [_interLock unlockWith:DONE];
        !           139:     }
        !           140: }
        !           141: 
        !           142: - (int)send:(int)oper withParam:(void *)param
        !           143: 
        !           144: {
        !           145:     msg_header_t       msg = { 0 };
        !           146:     int                        result;
        !           147:     
        !           148:     [_interLock lockWhen:IDLE];
        !           149:         
        !           150:     _oper = oper;
        !           151:     _param = param;
        !           152:     
        !           153:     msg.msg_size = sizeof (msg);
        !           154:     msg.msg_remote_port = _driverPort_kern;
        !           155:     msg.msg_id =  IO_COMMAND_MSG;
        !           156:     
        !           157:     [_interLock unlockWith:BUSY];
        !           158:     
        !           159:     result = msg_send_from_kernel(&msg, MSG_OPTION_NONE, 0);
        !           160:     if (result == SEND_SUCCESS) {
        !           161:        [_interLock lockWhen:DONE];
        !           162:        result = _ret;
        !           163:     }
        !           164:     else
        !           165:        [_interLock lock];
        !           166:     
        !           167:     [_interLock unlockWith:IDLE];
        !           168:     
        !           169:     return (result);
        !           170: }
        !           171: 
        !           172: - (int)send:(int)oper
        !           173: {
        !           174:     return( [self send:oper withParam:0]);
        !           175: }
        !           176: 
        !           177: @end
        !           178: 
        !           179: @implementation IOEthernet
        !           180: 
        !           181: - initFromDeviceDescription:(IODeviceDescription *)devDesc
        !           182: {
        !           183:     char       devName[8];
        !           184:     int                unit;
        !           185:     
        !           186:     if ([super initFromDeviceDescription:devDesc] == nil)
        !           187:        return nil;
        !           188:        
        !           189:     if ([self startIOThread] != IO_R_SUCCESS) {
        !           190:        [self free]; 
        !           191:        return nil;
        !           192:     }
        !           193: 
        !           194:     if( (en_arpcom = IOMalloc( sizeof( *en_arpcom))) == NULL) {
        !           195:         [self free];
        !           196:         return nil;
        !           197:     }
        !           198:     bzero( en_arpcom, sizeof( *en_arpcom));
        !           199: 
        !           200:     _driverCmd = [[DriverCmd alloc] initPort:[self interruptPort]];
        !           201: 
        !           202:     queue_init(&_multicastQueue);
        !           203: 
        !           204:     if ([self respondsTo:@selector(mbufsPlease)]) {
        !           205:                _net_buf_type = _NET_BUF_TYPE_MBUF;
        !           206:                printf("IOEthernet: driver registered to use mbufs\n");
        !           207:     }
        !           208:     else {
        !           209:                _net_buf_type = _NET_BUF_TYPE_NETBUF;
        !           210:     }
        !           211: 
        !           212:     unit = IOEthernetDeviceCount++;
        !           213:     
        !           214:     sprintf(devName, "%s%d", IOEthernetDeviceName,unit);
        !           215:     [self setName:devName];
        !           216:     [self setDeviceKind:IOEthernetDeviceType];
        !           217:     [self setUnit:unit];
        !           218:     
        !           219:     [self registerDevice];
        !           220:     
        !           221:     return self;
        !           222: }
        !           223: 
        !           224: - free
        !           225: {
        !           226:     enetMulti_t                *multiAddr;
        !           227: 
        !           228:     [self clearTimeout];
        !           229:     if (_driverCmd) {
        !           230:        [_driverCmd send:TERMINATE];   
        !           231:        [_driverCmd free];
        !           232:     }
        !           233:     if (_netif)
        !           234:        [_netif free];
        !           235: 
        !           236:     if( en_arpcom)
        !           237:         IOFree( en_arpcom, sizeof( *en_arpcom));
        !           238: 
        !           239:     return [super free];
        !           240: }
        !           241: 
        !           242: - (BOOL)isRunning
        !           243: {
        !           244:     return (_isRunning);
        !           245: }
        !           246: 
        !           247: - (void)setRunning:(BOOL)running
        !           248: {
        !           249:     _isRunning = running;
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * Implement driver timeouts.
        !           254:  */
        !           255: - (unsigned int)relativeTimeout
        !           256: {
        !           257:     ns_time_t                  timestamp;
        !           258: 
        !           259:     if (_absTimeout == 0)      
        !           260:        return (0);
        !           261:     
        !           262:     IOGetTimestamp(&timestamp);
        !           263:     
        !           264:     if (_absTimeout <= timestamp) {
        !           265:        _absTimeout = 0; return (0);
        !           266:     }
        !           267:        
        !           268:     return ((unsigned int) ((_absTimeout - timestamp) / (1000 * 1000)));
        !           269: }
        !           270: 
        !           271: - (void)setRelativeTimeout:(unsigned int)timeout
        !           272: {
        !           273:     if (_absTimeout > 0)
        !           274:        (void)ns_untimeout((func)IOEthernetTimeout, self);
        !           275: 
        !           276:     IOGetTimestamp(&_absTimeout);
        !           277:     
        !           278:     _absTimeout += ((ns_time_t)timeout * (1000 * 1000));
        !           279:     
        !           280:     ns_abstimeout(
        !           281:        (func)IOEthernetTimeout, self, _absTimeout, CALLOUT_PRI_THREAD);
        !           282: }
        !           283: 
        !           284: - (void)clearTimeout
        !           285: {
        !           286:     if (_absTimeout > 0) {
        !           287:        (void)ns_untimeout((func)IOEthernetTimeout, self);
        !           288:        _absTimeout = 0;
        !           289:     }
        !           290: }
        !           291: 
        !           292: //
        !           293: // Multicast Methods
        !           294: //
        !           295: 
        !           296: /*
        !           297:  * Determine if specified packet passes thru multicast filter. Returns
        !           298:  * YES if packet should be dropped (because it is an unregistered multicast
        !           299:  * packet), else returns NO.
        !           300:  * Must be called from command thread.
        !           301:  */
        !           302: - (BOOL)isUnwantedMulticastPacket:(ether_header_t *)header
        !           303: {
        !           304:        int i;
        !           305:        enetMulti_t *multi;
        !           306:        BOOL    isBroadcastPacket = YES;
        !           307: 
        !           308:     if ((header->ether_dhost[EA_GROUP_BYTE] & EA_GROUP_BIT) &&
        !           309:            !_promiscEnabled) {
        !           310:                
        !           311:                
        !           312:        for (i = 0 ; i < NUM_EN_ADDR_BYTES ; ++i) {
        !           313:                if (header->ether_dhost[i] != 0xff) {
        !           314:                        isBroadcastPacket = NO;
        !           315:                        break;
        !           316:                }
        !           317:        }
        !           318: 
        !           319:        /*
        !           320:         * Always accept the all-ones broadcast.
        !           321:         */
        !           322:        if (isBroadcastPacket)  
        !           323:            return NO;
        !           324:                        
        !           325:        /*
        !           326:         * Is this address registered as a multicast address?
        !           327:         *
        !           328:         * CAREFUL - this assumes that the bytes in
        !           329:         * the packet are in the same format as the
        !           330:         * bytes in an enet_addr_t...
        !           331:         */
        !           332:        multi = [self searchMulti:(enet_addr_t *)&header->ether_dhost];
        !           333:        if (multi == NULL) {
        !           334:            /*
        !           335:             * We don't want this.
        !           336:             */
        !           337:            return YES;
        !           338:        } 
        !           339:     }           
        !           340:     
        !           341:     /*
        !           342:      * Not a group packet (or is a registered multicast pckt),
        !           343:      * must be for us.
        !           344:      */
        !           345:     return NO;
        !           346: }
        !           347: 
        !           348: 
        !           349: /* 
        !           350:  * Determine if the outgoing packet should be received by the current 
        !           351:  * interface (either because it's a broadcast packet or a multicast 
        !           352:  * packet for which we are enabled); if so, send a copy of the packet 
        !           353:  * up the pipe.
        !           354:  */
        !           355: /*
        !           356:  * DWS 7/25/97
        !           357:  *
        !           358:  * In BSD 4.4, the layer above already takes care of looping back packets:
        !           359:  * see bsd/net/if_ethersubr.c.
        !           360:  */
        !           361: - (void)performLoopback : (netbuf_t)pkt
        !           362: {
        !           363: }
        !           364: 
        !           365: #import <sys/param.h>
        !           366: #import <sys/mbuf.h>
        !           367: 
        !           368: //
        !           369: // Implement the IONetworkDeviceMethods protocol.
        !           370: //
        !           371: // NOTE: Stop the unneeded copies and proc calls.
        !           372: // Also: we want to "guarantee" that the media header is still
        !           373: //      in the mbuf; the new code makes it clear.
        !           374: //
        !           375: -(int) inputPacket: (netbuf_t)pkt  extra:(void *)extra
        !           376: {
        !           377:        struct ether_header *eh;
        !           378:        struct ifnet *ifp;
        !           379:        struct mbuf *m;
        !           380:        
        !           381:        ifp = (struct ifnet *)&en_arpcom->ac_if;
        !           382:        ifp->if_ipackets += 1;
        !           383:        m = (struct mbuf *)pkt;
        !           384:        m->m_pkthdr.rcvif = ifp;
        !           385: 
        !           386:        if (ifp->if_bpf)
        !           387:                BPF_MTAP(ifp->if_bpf, m);
        !           388: 
        !           389:        eh = (struct ether_header *)m->m_data;
        !           390:        m->m_len -= sizeof (struct ether_header);
        !           391:        m->m_data += sizeof (struct ether_header);
        !           392: 
        !           393:     if (_net_buf_type == _NET_BUF_TYPE_NETBUF) { 
        !           394:                /* guaranteed one-piece packet */
        !           395:                m->m_pkthdr.len = m->m_len;
        !           396:     }
        !           397:     else {
        !           398:                m->m_pkthdr.len -= sizeof(struct ether_header);
        !           399:     }
        !           400: 
        !           401:        ether_input(ifp, eh, (struct mbuf *)pkt);
        !           402:        
        !           403:        return 0;
        !           404: }
        !           405: 
        !           406: - (int)finishInitialization
        !           407: {
        !           408:     return [_driverCmd send:RESET_ON];
        !           409: }
        !           410: 
        !           411: - (int)outputPacket:(netbuf_t)pkt address:(void *)addrs
        !           412: {
        !           413:     ether_header_t     *header;
        !           414:     enet_addr_t                *ea;
        !           415:     int                        length;
        !           416: 
        !           417:     if (!_isRunning) {
        !           418:        nb_free(pkt);
        !           419:        return 0;
        !           420:     }
        !           421:     
        !           422:     /*
        !           423:      * Setup the Ethernet header
        !           424:      */
        !           425:     header = (ether_header_t *)nb_map(pkt);
        !           426: 
        !           427:     /*
        !           428:      * Insert the destination address
        !           429:      */
        !           430:     ea = (enet_addr_t *)header->ether_dhost;
        !           431:     *ea = *(enet_addr_t *)addrs;
        !           432: 
        !           433:     /*
        !           434:      * Insert our source address
        !           435:      */  
        !           436:     ea = (enet_addr_t *)header->ether_shost;
        !           437:     *ea = _ethernetAddress;
        !           438: 
        !           439:     /*
        !           440:      * Insure that the packet meets minimum length requirements        
        !           441:      */
        !           442:     length = nb_size(pkt);
        !           443:     if (length < (ETHERMINPACKET - ETHERCRC))
        !           444:        nb_grow_bot(pkt, ETHERMINPACKET - ETHERCRC - length);
        !           445:        
        !           446:     [self transmit:pkt];
        !           447:     
        !           448:     return (0);
        !           449: }
        !           450: 
        !           451: - (netbuf_t)allocateNetbuf
        !           452: {
        !           453:     return (nb_alloc(ETHERMAXPACKET));
        !           454: }
        !           455: 
        !           456: 
        !           457: - (int)performCommand:(const char *)command data:(void *)data
        !           458: {
        !           459:     return (0);
        !           460: }
        !           461: - (id)getDriverCmd
        !           462: {
        !           463:        return(_driverCmd);
        !           464: }
        !           465: 
        !           466: - (struct ifnet *)allocateIfnet
        !           467: {
        !           468:        return(&en_arpcom->ac_if);
        !           469: }
        !           470: 
        !           471: //
        !           472: // Methods which implement the
        !           473: // IOEthernet(DriverInterface) category.
        !           474: //
        !           475: - (BOOL)resetAndEnable:(BOOL)enable
        !           476: {
        !           477:     return (TRUE);
        !           478: }
        !           479: 
        !           480: IOEthernet_ioctl(struct ifnet * ifp,u_long cmd, caddr_t data)
        !           481: {
        !           482:        struct arpcom *                 ar;
        !           483:        id                              device = ifp->if_private;
        !           484:        id                              dcmd;
        !           485:        unsigned                        error = 0;
        !           486:        struct ifaddr *                 ifa = (struct ifaddr *)data;
        !           487:        struct ifreq *                  ifr = (struct ifreq *)data;
        !           488:        unsigned                        ioctl_command;
        !           489:        void *                          ioctl_data;
        !           490:        int                             s;
        !           491: // R E M E M B E R
        !           492: // sockaddr_in comes from bsd/netinet/in.h
        !           493:        struct sockaddr_in *            sin;
        !           494: 
        !           495:        sin = (struct sockaddr_in *)(&((struct ifreq *)data)->ifr_addr);
        !           496: 
        !           497:        ar = (struct arpcom *)ifp;
        !           498: 
        !           499:        dcmd = [device getDriverCmd];
        !           500:        switch (cmd) {
        !           501:          case SIOCAUTOADDR:
        !           502:            error = in_bootp(ifp, sin, 
        !           503:                             &((struct IOEthernet *)device)->_ethernetAddress);
        !           504:            break;
        !           505: 
        !           506:        case SIOCSIFADDR:
        !           507: #if NeXT
        !           508:                ifp->if_flags |= (IFF_UP | IFF_RUNNING);
        !           509: #else
        !           510:                ifp->if_flags |= IFF_UP;
        !           511: #endif
        !           512:                switch (ifa->ifa_addr->sa_family) {
        !           513:                case AF_INET:
        !           514:                        [dcmd send:RESET_ON];
        !           515:                        /*
        !           516:                         * See if another station has *our* IP address.
        !           517:                         * i.e.: There is an address conflict! If a
        !           518:                         * conflict exists, a message is sent to the
        !           519:                         * console.
        !           520:                         */
        !           521:                        if (IA_SIN(ifa)->sin_addr.s_addr != 0) { /* don't bother for 0.0.0.0 */
        !           522:                            ar->ac_ipaddr = IA_SIN(ifa)->sin_addr;
        !           523:                            arpwhohas(ar, &IA_SIN(ifa)->sin_addr);
        !           524:                        }
        !           525:                        break;
        !           526:                default:
        !           527:                        [dcmd send:RESET_ON];
        !           528:                        break;
        !           529:                }
        !           530:                break;
        !           531: 
        !           532:        case SIOCSIFFLAGS:
        !           533:                /*
        !           534:                 * If interface is marked down and it is running, then stop it
        !           535:                 */
        !           536:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           537:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !           538:                        /*
        !           539:                         * If interface is marked down and it is running, then
        !           540:                         * stop it.
        !           541:                         */
        !           542:                        ifp->if_flags &= ~IFF_RUNNING;
        !           543:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !           544:                           (ifp->if_flags & IFF_RUNNING) == 0) {
        !           545:                        /*
        !           546:                         * If interface is marked up and it is stopped, then
        !           547:                         * start it.
        !           548:                         */
        !           549:                        [dcmd send:RESET_ON];
        !           550:                        ifp->if_flags |= IFF_RUNNING;
        !           551:                } else {
        !           552:                        /*
        !           553:                         * Reset the interface to pick up changes in any other
        !           554:                         * flags that affect hardware registers.
        !           555:                         */
        !           556:                        [dcmd send:RESET_ON];
        !           557:                }
        !           558:                /*
        !           559:                 * Set or clear promiscuous mode as appropriate
        !           560:                 */
        !           561:                if (ifp->if_flags & IFF_RUNNING) {
        !           562:                        BOOL isProm = ((struct IOEthernet *)device)->_promiscEnabled;
        !           563:                        if (isProm && !(ifp->if_flags & IFF_PROMISC))
        !           564:                                [dcmd send:PROMISC_DISABLE];
        !           565:                        else if (!isProm && (ifp->if_flags & IFF_PROMISC))
        !           566:                                [dcmd send:PROMISC_ENABLE];
        !           567: 
        !           568:                }
        !           569:                break;
        !           570: 
        !           571:        case SIOCADDMULTI:
        !           572:            error = ether_addmulti(ifr, ar);
        !           573:            if (error == ENETRESET) {
        !           574:                error = 0;
        !           575:                [device enableMulticast:
        !           576:                 (enet_addr_t *)ar->ac_multiaddrs->enm_addrlo];
        !           577:            }
        !           578:            break;
        !           579:        case SIOCDELMULTI:         
        !           580:            { 
        !           581:                struct ether_addr enaddr[2]; /* 0 - addrlo, 1 - addrhi */
        !           582: 
        !           583:                error = ether_delmulti(ifr, ar, enaddr);
        !           584:                if (error == ENETRESET) {
        !           585:                    error = 0;
        !           586:                    [device disableMulticast:enaddr]; /* XXX assume addrlo == addrhi */
        !           587:                }
        !           588:            }
        !           589:            break;
        !           590: 
        !           591:        default:
        !           592:            error = EINVAL;
        !           593:            break;
        !           594:     }
        !           595:     return (error);
        !           596: //     return [device performCommand:cmd data:data];
        !           597:        
        !           598: 
        !           599: }
        !           600: 
        !           601: #include <sys/mbuf.h>
        !           602: 
        !           603: static int
        !           604: IOEthernet_transmitPacket(
        !           605:     struct ifnet        *ifp
        !           606: )
        !           607: {
        !           608:     void               *buf_p;
        !           609:     id                 device = ifp->if_private;
        !           610:     IOEthernet  *eth = (IOEthernet *)device;
        !           611:     struct mbuf                *m, *mp;
        !           612:     int                        mLen;
        !           613:     netbuf_t           pkt;
        !           614:     int                        pktSize;
        !           615:        
        !           616:     if (device == nil) {
        !           617:        return -1;
        !           618:     }
        !           619: 
        !           620:     IF_DEQUEUE(&(ifp->if_snd), m);
        !           621: 
        !           622:     if (m == 0)
        !           623:         return 0;
        !           624:        
        !           625:        if ((m->m_flags & M_PKTHDR) == 0) {
        !           626:                IOLog("IOEthernet: M_PKTHDR flag not set (%04x)\n", m->m_flags);
        !           627:                m_freem(m);
        !           628:                return -1;
        !           629:        }
        !           630: 
        !           631:     if (ifp->if_bpf)
        !           632:        BPF_MTAP(ifp->if_bpf, m);
        !           633: 
        !           634:     if (eth->_net_buf_type == _NET_BUF_TYPE_MBUF)
        !           635:                [device transmit:(netbuf_t)m];
        !           636:     else {
        !           637:        /* old compat interface uses netbufs */
        !           638:     pkt = [device allocateNetbuf]; /* call the driver's allocation routine */
        !           639:     if (pkt == 0) {
        !           640:        m_freem(m);
        !           641:         return 0;
        !           642:     }
        !           643: 
        !           644:     mLen = m->m_pkthdr.len;
        !           645:     buf_p = nb_map(pkt);
        !           646:     pktSize = nb_size(pkt);
        !           647:     if (pktSize < mLen) {
        !           648:        IOLog("IOEthernet: %s driver packet size too small (%d < %d)\n",
        !           649:              [device name], pktSize, mLen);
        !           650:        m_freem(m);
        !           651:        nb_free(pkt);
        !           652:        return 0;
        !           653:     }
        !           654: 
        !           655:     { /* copy the mbuf to the netbuf */
        !           656:        int             len = mLen;
        !           657:        struct mbuf *   m_pkt;
        !           658: 
        !           659:        for (mp = m; mp; mp = mp->m_next) {
        !           660:             if (mp->m_len == 0)
        !           661:                continue;
        !           662:             bcopy(mtod(mp, caddr_t), buf_p, min(len, mp->m_len));
        !           663:             buf_p += mp->m_len;
        !           664:             len -= mp->m_len;
        !           665:        }
        !           666:        m_pkt = (struct mbuf *)pkt;
        !           667:        m_pkt->m_len = mLen;
        !           668:        m_pkt->m_pkthdr.len = mLen;
        !           669:     }
        !           670:     m_freem(m);
        !           671:     [device transmit:pkt];
        !           672:     }
        !           673: 
        !           674:     return 0;
        !           675: }
        !           676: 
        !           677: 
        !           678: static void
        !           679: null_func()
        !           680: {
        !           681: }
        !           682: 
        !           683: - (IONetwork *)attachToNetworkWithAddress:(enet_addr_t)addrs
        !           684: {
        !           685:     struct ifnet *ifp;
        !           686: 
        !           687:     _ethernetAddress = addrs;
        !           688:     bcopy(&addrs,en_arpcom->ac_enaddr,6);
        !           689:  
        !           690:     _netif = [[IONetwork alloc] initForNetworkDevice:self
        !           691:                    name:IOEthernetDeviceName unit:[self unit]
        !           692:                    type:IFTYPE_ETHERNET
        !           693:                    maxTransferUnit:ETHERMTU
        !           694:                    flags:0];
        !           695:        ifp = [_netif  getIONetworkIfnet];
        !           696:        ifp->if_unit = [self unit];
        !           697:        ifp->if_name = "en";
        !           698: 
        !           699:        /*
        !           700:         *
        !           701:         * Fix the start and WD functions
        !           702:         */
        !           703:        ifp->if_output = ether_output;
        !           704:        ifp->if_ioctl = IOEthernet_ioctl;
        !           705:        ifp->if_start = IOEthernet_transmitPacket;
        !           706:        ifp->if_watchdog = (void *) null_func;
        !           707: 
        !           708:        ifp->if_flags =
        !           709:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
        !           710:        bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
        !           711:        if_attach(ifp);
        !           712:        ether_ifattach(ifp);
        !           713:                    
        !           714:     [self registerAsDebuggerDevice];
        !           715:         
        !           716:     IOLog("%s: Ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n",
        !           717:        [self name],
        !           718:        _ethernetAddress.ether_addr_octet[0],
        !           719:        _ethernetAddress.ether_addr_octet[1],
        !           720:        _ethernetAddress.ether_addr_octet[2],
        !           721:        _ethernetAddress.ether_addr_octet[3],
        !           722:        _ethernetAddress.ether_addr_octet[4],
        !           723:        _ethernetAddress.ether_addr_octet[5]);
        !           724:     
        !           725:     return _netif;
        !           726: }
        !           727: 
        !           728: - (void)transmit:(netbuf_t)pkt
        !           729: {
        !           730:     nb_free(pkt);
        !           731: }
        !           732: 
        !           733: - (void)receivePacket:(void *)pkt
        !           734:                length:(unsigned int *)pkt_len
        !           735:                timeout:(unsigned int)timeout
        !           736: {
        !           737:     *pkt_len = 0;
        !           738: }
        !           739:                
        !           740: - (void)sendPacket:(void *)pkt
        !           741:                length:(unsigned int)pkt_len
        !           742: {
        !           743: }
        !           744: 
        !           745: - (BOOL)enablePromiscuousMode
        !           746: {
        !           747:     return YES;
        !           748: }
        !           749: 
        !           750: - (void)disablePromiscuousMode
        !           751: {
        !           752: }
        !           753: 
        !           754: - (void)addMulticastAddress:(enet_addr_t *)addr
        !           755: {
        !           756: }
        !           757: 
        !           758: - (void)removeMulticastAddress:(enet_addr_t *)addr
        !           759: {
        !           760: 
        !           761: }
        !           762: 
        !           763: - (BOOL)enableMulticastMode
        !           764: {
        !           765:     return YES;
        !           766: }
        !           767: - (void)disableMulticastMode
        !           768: {
        !           769: }
        !           770: 
        !           771: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
        !           772: {
        !           773:     [_netif property_IODeviceClass:classes length:maxLen];
        !           774:     strcat( classes, " "IOClassEthernet);
        !           775:     return( self);
        !           776: }
        !           777: 
        !           778: @end
        !           779: 
        !           780: @implementation IOEthernet(PrivateMethods)
        !           781: 
        !           782: //
        !           783: // Used to handle a synchronous
        !           784: // command sent by another thread
        !           785: // to the driver thread.
        !           786: //
        !           787: - (void)commandRequestOccurred
        !           788: {
        !           789:     int                oper = [_driverCmd oper];
        !           790:     int                result = 0;
        !           791:     enet_addr_t * multiAddr;
        !           792: 
        !           793:     switch (oper) {
        !           794:     
        !           795:     case RESET_ON:
        !           796:        if (!_isRunning) {
        !           797:            if (![self resetAndEnable:TRUE])
        !           798:                result = EIO;
        !           799:        }
        !           800:        [_driverCmd done:result];
        !           801:        break;
        !           802:        
        !           803:     case RESET_OFF:
        !           804:        [self resetAndEnable:FALSE];
        !           805:        [_driverCmd done:result];
        !           806:        break;
        !           807:     
        !           808:     case TERMINATE:
        !           809:         while (!queue_empty(&_multicastQueue)) {
        !           810:             enetMulti_t                *multiAddr;
        !           811:             queue_remove_first(&_multicastQueue,multiAddr,enetMulti_t *,link);
        !           812:             IOFree(multiAddr,sizeof(*multiAddr));
        !           813:         }
        !           814:        [_driverCmd done:result];
        !           815:        IOExitThread();
        !           816:        break;
        !           817:    
        !           818:     case PROMISC_ENABLE:
        !           819:        if ([self enablePromiscuousMode]) 
        !           820:            _promiscEnabled = TRUE;
        !           821:        else {
        !           822:            _promiscEnabled = FALSE;
        !           823:            result = 1;
        !           824:        }
        !           825:        [_driverCmd done:result];
        !           826:        break;
        !           827:     
        !           828:     case PROMISC_DISABLE:
        !           829:        [self disablePromiscuousMode];
        !           830:        _promiscEnabled = FALSE;
        !           831:        [_driverCmd done:result];
        !           832:        break;
        !           833: 
        !           834:     case MULTICAST_ENABLE:
        !           835:         multiAddr = (enet_addr_t *) [_driverCmd param];
        !           836: #ifdef DEBUG
        !           837:        printf("%s: enabling multicast address %x:%x:%x:%x:%x:%x\n", 
        !           838:               [self name],
        !           839:               multiAddr->ether_addr_octet[0],
        !           840:               multiAddr->ether_addr_octet[1],
        !           841:               multiAddr->ether_addr_octet[2],
        !           842:               multiAddr->ether_addr_octet[3],
        !           843:               multiAddr->ether_addr_octet[4],
        !           844:               multiAddr->ether_addr_octet[5]);
        !           845: #endif DEBUG
        !           846:         [self enqueueMulticast:multiAddr];
        !           847:        [self addMulticastAddress:multiAddr];
        !           848:        [self enableMulticastMode];
        !           849:        [_driverCmd done:result];
        !           850:        break;
        !           851: 
        !           852:     case MULTICAST_DISABLE:
        !           853:         multiAddr = (enet_addr_t *) [_driverCmd param];
        !           854: #ifdef DEBUG
        !           855:        printf("%s: removing multicast address %x:%x:%x:%x:%x:%x\n", 
        !           856:               [self name],
        !           857:               multiAddr->ether_addr_octet[0],
        !           858:               multiAddr->ether_addr_octet[1],
        !           859:               multiAddr->ether_addr_octet[2],
        !           860:               multiAddr->ether_addr_octet[3],
        !           861:               multiAddr->ether_addr_octet[4],
        !           862:               multiAddr->ether_addr_octet[5]);
        !           863: #endif DEBUG
        !           864:         [self dequeueMulticast:multiAddr];
        !           865:        [self removeMulticastAddress:multiAddr];
        !           866:        if (queue_empty(&_multicastQueue)) {
        !           867:            [self disableMulticastMode];
        !           868:        }
        !           869:        [_driverCmd done:result];
        !           870:        break;
        !           871:     }
        !           872: 
        !           873: }
        !           874: 
        !           875: - (queue_head_t *)multicastQueue
        !           876: {
        !           877:     return &_multicastQueue;
        !           878: }
        !           879: 
        !           880: /*
        !           881:  * Add a multicast address to the class queue.
        !           882:  * Invoked from our i/o thread
        !           883:  */
        !           884: - (void)enqueueMulticast:(enet_addr_t *)addrs
        !           885: {
        !           886:     enetMulti_t *multi;
        !           887: 
        !           888:     /*
        !           889:      * Paranoia check to make sure group bit is on.
        !           890:      */
        !           891:     if (!(addrs->ether_addr_octet[EA_GROUP_BYTE] & EA_GROUP_BIT)) {
        !           892:        return;
        !           893:     }
        !           894: 
        !           895:     multi = [self searchMulti:addrs];
        !           896:     if (multi) {
        !           897:        /*
        !           898:         * Just bump the reference count since the hardware should
        !           899:         * already be configured.
        !           900:         */
        !           901:        if (++multi->refCount < 0)
        !           902:            multi->refCount--;
        !           903:        return;
        !           904:     }
        !           905:     
        !           906:     /*
        !           907:      * New entry, so queue it
        !           908:      */
        !           909:     multi = IOMalloc(sizeof(*multi));
        !           910:     multi->address = *addrs;   
        !           911:     multi->refCount = 1;
        !           912:     queue_enter(&_multicastQueue, multi, enetMulti_t *, link);
        !           913: }
        !           914: 
        !           915: /*
        !           916:  * Pass multicast address to the command thread.
        !           917:  */
        !           918: 
        !           919: - (void)enableMulticast:(enet_addr_t *)addrs
        !           920: {
        !           921:     [_driverCmd send:MULTICAST_ENABLE withParam:addrs];
        !           922: }
        !           923: 
        !           924: /*
        !           925:  * Disable a multicast address.
        !           926:  */
        !           927: - (void)dequeueMulticast:(enet_addr_t *)addrs
        !           928: {
        !           929:     enetMulti_t *multi;
        !           930: 
        !           931:     multi = [self searchMulti:addrs];
        !           932:     if (multi) {
        !           933:        /*
        !           934:         * Found it, now remove it if there are no remaining
        !           935:         * references.
        !           936:         */
        !           937:        if (multi->refCount > 0)
        !           938:            multi->refCount--;
        !           939:        if (multi->refCount <= 0) {
        !           940:            queue_remove(&_multicastQueue, multi, enetMulti_t *, link);
        !           941:            IOFree(multi, sizeof(*multi));
        !           942:        }
        !           943:     }
        !           944: }
        !           945: 
        !           946: - (void)disableMulticast:(enet_addr_t *)addrs
        !           947: {
        !           948:     [_driverCmd send:MULTICAST_DISABLE withParam:addrs];
        !           949: }
        !           950: 
        !           951: /*
        !           952:  * See if a given enet_addr_t is present in _multicastQueue. If so, return
        !           953:  * the enetMulti_t of the entry in _multicastQueue; else return NULL.
        !           954:  * Must be called from command thread.
        !           955:  */
        !           956: - (enetMulti_t *)searchMulti : (enet_addr_t *)addrs
        !           957: {
        !           958:     enetMulti_t *multi;
        !           959:     int i;
        !           960: 
        !           961:     queue_iterate(&_multicastQueue,multi,enetMulti_t *,link) {
        !           962: 
        !           963:        if (memcmp(&multi->address.ether_addr_octet[0], 
        !           964:                        &addrs->ether_addr_octet[0], NUM_EN_ADDR_BYTES) == 0)
        !           965:                        return multi;
        !           966:        }
        !           967: 
        !           968:     return NULL;
        !           969: }
        !           970: 
        !           971: @end
        !           972: 
        !           973: static void
        !           974: IOEthernetTimeout(IOEthernet *device)
        !           975: {
        !           976:     msg_header_t       msg = { 0 };
        !           977:     
        !           978:     if (device->_absTimeout > 0) {     
        !           979:        device->_absTimeout = 0;
        !           980:        
        !           981:     
        !           982:        msg.msg_size = sizeof (msg);
        !           983:        msg.msg_remote_port = IOGetKernPort([device interruptPort]);
        !           984:        msg.msg_id =  IO_TIMEOUT_MSG;
        !           985:        
        !           986:        msg_send_from_kernel(&msg, MSG_OPTION_NONE, 0);
        !           987:     }
        !           988: }

unix.superglobalmegacorp.com

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