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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: /*
                     25:  * 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.