Annotation of driverkit/libDriver/Kernel/IOTokenRing.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: /*     Copyright (c) 1993 NeXT Computer, Inc.  All rights reserved. 
        !            25:  *
        !            26:  * TokenRing.m - TokenRing device-independent abstract superclass
        !            27:  *
        !            28:  *     The TokenRing superclass contains the device-independent functions
        !            29:  *     that are common to most token-ring drivers.  The hardware-specific
        !            30:  *     driver should be a subclass of TokenRing.
        !            31:  *
        !            32:  * HISTORY
        !            33:  * 25-Jan-93 Joel Greenblatt at NeXT 
        !            34:  *     created
        !            35:  *      
        !            36:  */
        !            37: 
        !            38:  
        !            39: #define MACH_USER_API  1
        !            40:  
        !            41: 
        !            42: #import <mach/mach_types.h>
        !            43: #import <mach/message.h>
        !            44: #import <machkit/NXLock.h>
        !            45: #import <driverkit/generalFuncs.h>
        !            46: #import <driverkit/interruptMsg.h>
        !            47: #import <driverkit/kernelDriver.h>
        !            48: #import <netinet/in.h>
        !            49: #import <kernserv/prototypes.h>
        !            50: #import <net/tokensr.h>
        !            51: #import <sys/errno.h>
        !            52: 
        !            53: #import <driverkit/IOTokenRing.h>
        !            54: 
        !            55: static void TokenRingTimeout(IOTokenRing *device);
        !            56: 
        !            57: static char    TRDeviceName[] = "tr";
        !            58: static char    TRDeviceType[] = "TokenRing";
        !            59: static int     TRDeviceCount = 0;
        !            60: 
        !            61: extern int ipforwarding; // flag in kernel to control ip lan-to-lan routing
        !            62: 
        !            63: /*
        !            64:  * Attach virtual drivers
        !            65:  */
        !            66: extern void vtrip_config(int unit, int flags, int mtu, int tokpri);
        !            67: 
        !            68: #define IP_SRCROUTING          0x1     /* enable IP source routing */
        !            69: 
        !            70: 
        !            71: /*
        !            72:  * Configuration strings in Instance.table
        !            73:  */
        !            74: static const char ITRingSpeed[] =              "Ring Speed";
        !            75: static const char ITNodeAddress[] =            "Node Address";
        !            76: static const char ITGroupAddress[] =           "Group Address";
        !            77: static const char ITFunctionalAddress[] =      "Functional Address";
        !            78: static const char ITEarlyToken[] =             "16Mb Early Token";
        !            79: static const char ITAutoRecovery[] =           "Auto Recovery";
        !            80: static const char ITIPAttach[] =               "IP Attach";
        !            81: static const char ITIPMtu[] =                  "IP Mtu";
        !            82: static const char ITIPTokenPriority[] =        "IP Token Priority";
        !            83: static const char ITIPSourceRouting[] =        "IP 802.5 Source Routing";
        !            84: 
        !            85: static const char ITipFowarding[] =            "IP LAN-to-LAN Routing";
        !            86: 
        !            87: 
        !            88: @interface DriverCmdtr:Object
        !            89: {
        !            90: @private
        !            91:     port_t     _driverPort_kern;
        !            92:     id         _interLock;
        !            93: #define OPDONE         1
        !            94: #define BUSY           2
        !            95: #define IDLE           3
        !            96:     int                _oper;
        !            97: #define RESET_ON       1
        !            98: #define RESET_OFF      2
        !            99: #define TERMINATE      4
        !           100:     int                _ret;
        !           101: }
        !           102: @end
        !           103: 
        !           104: @implementation DriverCmdtr
        !           105: 
        !           106: - initPort:(port_t)port
        !           107: {
        !           108:     [super init];
        !           109: 
        !           110:     _interLock = [[NXConditionLock alloc] initWith:IDLE];
        !           111:     _driverPort_kern = IOGetKernPort(port);
        !           112:     
        !           113:     return self;
        !           114: }
        !           115: 
        !           116:  
        !           117: - free
        !           118: {
        !           119:     [_interLock free];
        !           120:     
        !           121:     port_release(_driverPort_kern);
        !           122:     
        !           123:     return [super free];
        !           124: }
        !           125: 
        !           126: - (int)oper
        !           127: {
        !           128:     return (_oper);
        !           129: }
        !           130: 
        !           131: - (void)done:(int)ret
        !           132: {
        !           133:     if ([_interLock condition] == BUSY) {
        !           134:        [_interLock lock];
        !           135:        _ret = ret;
        !           136:        [_interLock unlockWith:OPDONE];
        !           137:     }
        !           138: }
        !           139: 
        !           140: - (int)send:(int)oper
        !           141: {
        !           142:     msg_header_t       msg = { 0 };
        !           143:     int                        result;
        !           144:     
        !           145:     [_interLock lockWhen:IDLE];
        !           146:         
        !           147:     _oper = oper;
        !           148:     
        !           149:     msg.msg_size = sizeof (msg);
        !           150:     msg.msg_remote_port = _driverPort_kern;
        !           151:     msg.msg_id =  IO_COMMAND_MSG;
        !           152:     
        !           153:     [_interLock unlockWith:BUSY];
        !           154:     
        !           155:     result = msg_send_from_kernel(&msg, MSG_OPTION_NONE, 0);
        !           156:     if (result == SEND_SUCCESS) {
        !           157:        [_interLock lockWhen:OPDONE];
        !           158:        result = _ret;
        !           159:     }
        !           160:     else
        !           161:        [_interLock lock];
        !           162:     
        !           163:     [_interLock unlockWith:IDLE];
        !           164:     
        !           165:     return (result);
        !           166: }
        !           167: 
        !           168: @end
        !           169: 
        !           170: @implementation IOTokenRing
        !           171: 
        !           172: /*
        !           173:  * Private Methods
        !           174:  */
        !           175:  
        !           176: /*
        !           177:  * Set maximum packet size based on ring speed.  Unfortunately, there may
        !           178:  * be different interpretations for token-ring.  Subclass can override if it
        !           179:  * disagrees, or must reduce due to implementation limitations.
        !           180:  */
        !           181: -(void)_set8025FrameSizes
        !           182: {
        !           183:     /*
        !           184:      * The maximum allowable packet size is a function of ring speed 
        !           185:      * (per IEEE 802.5 standard). 
        !           186:      */
        !           187:     if(_ringSpeed == 4) {
        !           188:        _maxInfoFieldSize = MAC_INFO_4MB; 
        !           189:     }   
        !           190:     if(_ringSpeed == 16) {
        !           191:        _maxInfoFieldSize = MAC_INFO_16MB;
        !           192:     }
        !           193: }
        !           194: 
        !           195: /*
        !           196:  * Get info from Instance.table (some params are just saved for
        !           197:  * optional subclass use).
        !           198:  */
        !           199: - (int)_getInstanceTable:(IODeviceDescription *)devDesc
        !           200: {
        !           201: 
        !           202:     IOConfigTable      *confTable;
        !           203:     const char         *s;
        !           204: 
        !           205:     confTable = [devDesc configTable];
        !           206:     if(confTable == nil) {
        !           207:        IOLog("%s: couldn't get Instance%d.table\n",
        !           208:            [self name], [self unit]);
        !           209:        return 1;
        !           210:     }
        !           211: 
        !           212:     /*
        !           213:        * MAC layer parms ...
        !           214:        */
        !           215: 
        !           216:     s = [confTable valueForStringKey: ITRingSpeed];            // ring speed
        !           217:     if (!strcmp(s, "4")) 
        !           218:        _ringSpeed = 4;
        !           219:     else if (strcmp(s, "16") == 0) 
        !           220:        _ringSpeed = 16;
        !           221:     else {
        !           222:        IOLog("%s: invalid ring speed in Instance.table\n", [self name]);
        !           223:        _ringSpeed = 16;
        !           224:     }
        !           225:     [confTable freeString:s];
        !           226: 
        !           227:     s = [confTable valueForStringKey: ITNodeAddress];  // Node address
        !           228: #if 0
        !           229:     /*
        !           230:      * Unsupported for now.  The subclass is free to access the config
        !           231:      * table directly to read the node address and use it.
        !           232:      */
        !           233:     if (strcmp(s, "")) {
        !           234:        //_nodeAddress
        !           235:        IOLog("%s: cannot override burned-in addr\n", [self name]);
        !           236:     } 
        !           237:     else 
        !           238:        IOLog("%s: will use burned-in node address\n", [self name]);
        !           239: #endif
        !           240:     [confTable freeString:s];
        !           241: 
        !           242: #if 0
        !           243:     s = [confTable valueForStringKey: ITGroupAddress]; // Group addr
        !           244:     if (strcmp(s, "")) {
        !           245:        //_groupAddress 
        !           246:        IOLog("%s: cannot set Group addr\n", [self name]);
        !           247:     } 
        !           248:     else 
        !           249:        IOLog("%s: no Group Addresses enabled\n", [self name]);
        !           250:     [confTable freeString:s];
        !           251: 
        !           252:     s = [confTable valueForStringKey: ITFunctionalAddress];    // Func addr
        !           253:     if (strcmp(s, "")) {
        !           254:        //_functionalAddress
        !           255:        IOLog("%s: cannot set Functional addr\n", [self name]);
        !           256:     } 
        !           257:     else 
        !           258:        IOLog("%s: no Functional Addresses enabled\n", [self name]);
        !           259:     [confTable freeString:s];
        !           260: #endif 0
        !           261: 
        !           262:     s = [confTable valueForStringKey: ITEarlyToken];   // early token
        !           263:     if (!strcmp(s, "YES")) 
        !           264:        _flags._isEarlyTokenEnabled = 1;
        !           265:     else 
        !           266:        _flags._isEarlyTokenEnabled = 0;
        !           267:     [confTable freeString:s];
        !           268: 
        !           269:     s = [confTable valueForStringKey: ITAutoRecovery]; // auto recov
        !           270:     if (!strcmp(s, "YES")) 
        !           271:        _flags._shouldAutoRecover = 1;
        !           272:     else 
        !           273:        _flags._shouldAutoRecover = 0;
        !           274:     [confTable freeString:s];
        !           275: 
        !           276: #if 0
        !           277:     /*
        !           278:      * IP params ...
        !           279:      */
        !           280: 
        !           281:     s = [confTable valueForStringKey: ITIPAttach];             // attach i/f
        !           282:     if (!strcmp(s, "YES")) 
        !           283:        _flags._shouldAttachIP = 1;
        !           284:     else 
        !           285:        _flags._shouldAttachIP = 0;
        !           286:     [confTable freeString:s];
        !           287: 
        !           288:     s = [confTable valueForStringKey: ITIPMtu];                // mtu
        !           289:     _ipMtu = strtol(s, 0, 10);
        !           290:     [confTable freeString:s];
        !           291: 
        !           292:     s = [confTable valueForStringKey: ITIPTokenPriority];      // token pri
        !           293:     if (!strcmp(s, "DEFAULT")) 
        !           294:        _ipTokenPriority = 8;
        !           295:     else 
        !           296:        _ipTokenPriority = strtol(s, 0, 10);
        !           297:     [confTable freeString:s];
        !           298: 
        !           299:     s = [confTable valueForStringKey: ITIPSourceRouting];      // source rtng
        !           300:     if (!strcmp(s, "YES")) 
        !           301:        _flags._doesIPSourceRouting = 1;
        !           302:     else 
        !           303:        _flags._doesIPSourceRouting = 0;
        !           304:     [confTable freeString:s];
        !           305: 
        !           306:     /*
        !           307:      * Allow fowarding of packets between interfaces in a multi-homed
        !           308:      * host (a don't care for hosts with single i-faces).  Note that
        !           309:      * if no param is specified we don't touch ipforwarding (as of
        !           310:      * this writing this parameter is left out of our Default.table).
        !           311:      */
        !           312:     s = [confTable valueForStringKey: ITipFowarding]; 
        !           313:     if (!strcmp(s, "YES")) 
        !           314:        ipforwarding = 1;
        !           315:     if (!strcmp(s, "NO")) 
        !           316:        ipforwarding = 0;
        !           317:     [confTable freeString:s];
        !           318: #endif 0
        !           319:   
        !           320:     /*
        !           321:      * Set these defaults here for now.  We'll support them in the instance
        !           322:      * table eventually.
        !           323:      */
        !           324:     _flags._shouldAttachIP = 1;
        !           325:     _ipMtu = 8100;
        !           326:     _ipTokenPriority = 8;
        !           327:     _flags._doesIPSourceRouting = 1;
        !           328:     ipforwarding = 0;
        !           329: 
        !           330:     return 0;
        !           331: }
        !           332: 
        !           333: 
        !           334: /*
        !           335:  * Public Methods
        !           336:  */
        !           337: 
        !           338: /*
        !           339:  * Normally invoked from subclass method of same name.
        !           340:  */
        !           341: - initFromDeviceDescription:(IODeviceDescription *)devDesc
        !           342: {
        !           343:     char       devName[8];
        !           344:     int        unit;
        !           345:     
        !           346:     if ([super initFromDeviceDescription:devDesc] == nil)
        !           347:        return nil;
        !           348: 
        !           349:     if ([self startIOThread] != IO_R_SUCCESS) {
        !           350:        [self free]; 
        !           351:        return nil;
        !           352:     }
        !           353:     
        !           354:     unit = TRDeviceCount++;
        !           355:   
        !           356:     sprintf(devName, "%s%d", TRDeviceName, unit);
        !           357:     [self setName:devName];
        !           358:     [self setDeviceKind:TRDeviceType];
        !           359:     [self setUnit:unit];
        !           360: 
        !           361:     if([self _getInstanceTable:devDesc]) {
        !           362:        [self free]; 
        !           363:        return nil;
        !           364:     }
        !           365: 
        !           366:     _driverCmd = [[DriverCmdtr alloc] initPort:[self interruptPort]];
        !           367: 
        !           368:     [self _set8025FrameSizes]; 
        !           369:     
        !           370:     return self;
        !           371: }
        !           372: 
        !           373: - free
        !           374: {
        !           375:     [self clearTimeout];
        !           376:     if (_driverCmd) {
        !           377:        [_driverCmd send:TERMINATE];
        !           378:        [_driverCmd free];
        !           379:     }
        !           380:     if (_netif)
        !           381:        [_netif free];
        !           382:     return [super free];
        !           383: }
        !           384: 
        !           385: /*
        !           386:  * Subclass must invoke this method to attach our networking interfaces
        !           387:  * (typically done after successful hardware init).
        !           388:  */
        !           389: - (IONetwork *)attachToNetworkWithAddress:(token_addr_t)addrs
        !           390: {
        !           391:     int        vtripf = 0; 
        !           392:     int                i;
        !           393: 
        !           394:     [self registerDevice];
        !           395: 
        !           396:     _nodeAddress = addrs;
        !           397:     
        !           398:     /*
        !           399:      * Netif for "real" (hdw) driver interface.
        !           400:      */
        !           401:     _netif = [[IONetwork alloc] initForNetworkDevice:self
        !           402:        name:TRDeviceName unit:[self unit]
        !           403:        type:IFTYPE_TOKENRING
        !           404:        maxTransferUnit:_maxInfoFieldSize   
        !           405:        flags:0];
        !           406: 
        !           407:     /*
        !           408:      * Netif for IP to get to us.
        !           409:      */
        !           410:     if(_flags._shouldAttachIP) {
        !           411:        if(_flags._doesIPSourceRouting) vtripf |= IP_SRCROUTING;
        !           412:        vtrip_config([self unit], vtripf, _ipMtu, _ipTokenPriority);
        !           413:     }
        !           414: 
        !           415:     /*
        !           416:      * Emit the node address
        !           417:      */
        !           418:      IOLog("%s: Token Ring Node address %02x:%02x:%02x:%02x:%02x:%02x\n",
        !           419:        [self name],
        !           420:        _nodeAddress.ta_byte[0],_nodeAddress.ta_byte[1],
        !           421:        _nodeAddress.ta_byte[2],_nodeAddress.ta_byte[3],
        !           422:        _nodeAddress.ta_byte[4],_nodeAddress.ta_byte[5]);
        !           423:     
        !           424: #if 0
        !           425:     /*
        !           426:      * Emit the group address, if non-zero
        !           427:      */
        !           428:     for (i = 2 ; i < 4 ; ++i) {
        !           429:        if (_groupAddress.ta_byte[i]) {
        !           430:            IOLog("%s: Token Ring Group address "
        !           431:                "%02x:%02x:%02x,%02x:%02x:%02x\n",
        !           432:                [self name],
        !           433:                _groupAddress.ta_byte[0], _groupAddress.ta_byte[1],
        !           434:                _groupAddress.ta_byte[2], _groupAddress.ta_byte[3],
        !           435:                _groupAddress.ta_byte[4], _groupAddress.ta_byte[5]);
        !           436:            break;
        !           437:        }
        !           438:     }
        !           439:     
        !           440:     /*
        !           441:      * Emit the functional address, if non-zero
        !           442:      */
        !           443:     
        !           444:     for (i = 2 ; i < 4 ; ++i) {
        !           445:        if (_functionalAddress.ta_byte[i]) {
        !           446:            IOLog("%s: Token Ring Functional address "
        !           447:                "%02x:%02x:%02x,%02x:%02x:%02x\n",
        !           448:                [self name],
        !           449:                _functionalAddress.ta_byte[0], _functionalAddress.ta_byte[1],
        !           450:                _functionalAddress.ta_byte[2], _functionalAddress.ta_byte[3],
        !           451:                _functionalAddress.ta_byte[4], _functionalAddress.ta_byte[5]);
        !           452:            break;
        !           453:        }
        !           454:     }
        !           455: #endif 0
        !           456:     return _netif;
        !           457: }
        !           458: 
        !           459: - (IONetwork *)networkInterface
        !           460: {
        !           461:     return _netif;
        !           462: }
        !           463: 
        !           464: - (BOOL)isRunning
        !           465: {
        !           466:     return (BOOL)_flags._isRunning;
        !           467: }
        !           468: 
        !           469: - (void)setRunning:(BOOL)running
        !           470: {
        !           471:     _flags._isRunning = running;
        !           472: }
        !           473: 
        !           474: /*
        !           475:  * Implement driver timeouts.
        !           476:  */
        !           477:  
        !           478: - (unsigned int)relativeTimeout
        !           479: {
        !           480:     ns_time_t                  timestamp;
        !           481: 
        !           482:     if (_absTimeout == 0)      
        !           483:        return (0);
        !           484:     
        !           485:     IOGetTimestamp(&timestamp);
        !           486:     
        !           487:     if (_absTimeout <= timestamp) {
        !           488:        _absTimeout = 0; return (0);
        !           489:     }
        !           490:        
        !           491:     return ((unsigned int) ((_absTimeout - timestamp) / (1000 * 1000)));
        !           492: }
        !           493: 
        !           494: - (void)setRelativeTimeout:(unsigned int)timeout
        !           495: {
        !           496:     if (_absTimeout > 0)
        !           497:        (void)ns_untimeout((func)TokenRingTimeout, self);
        !           498: 
        !           499:     IOGetTimestamp(&_absTimeout);
        !           500:     
        !           501:     _absTimeout += ((ns_time_t)timeout * (1000 * 1000));
        !           502:     
        !           503:     ns_abstimeout((func)TokenRingTimeout, self, 
        !           504:        _absTimeout, CALLOUT_PRI_THREAD);
        !           505: }
        !           506: 
        !           507: - (void)clearTimeout
        !           508: {
        !           509:     if (_absTimeout > 0) {
        !           510:        (void)ns_untimeout((func)TokenRingTimeout, self);
        !           511:        _absTimeout = 0;
        !           512:     }
        !           513: }
        !           514: 
        !           515: - (BOOL)earlyTokenEnabled
        !           516: {
        !           517:     return (BOOL)_flags._isEarlyTokenEnabled;
        !           518: }
        !           519: 
        !           520: - (BOOL)shouldAutoRecover
        !           521: {
        !           522:     return (BOOL)_flags._shouldAutoRecover;
        !           523: }
        !           524: 
        !           525: - (unsigned)ringSpeed
        !           526: {
        !           527:     return _ringSpeed;
        !           528: } 
        !           529: 
        !           530: - (unsigned)maxInfoFieldSize
        !           531: {
        !           532:     return _maxInfoFieldSize;
        !           533: }
        !           534: 
        !           535: - (void)setMaxInfoFieldSize:(unsigned)size
        !           536: {
        !           537:     //sanity check?
        !           538:     _maxInfoFieldSize = size;
        !           539: }
        !           540: 
        !           541: /*
        !           542:  * Hardware Address Methods
        !           543:  */
        !           544: 
        !           545: - (token_addr_t)nodeAddress
        !           546: {
        !           547:     return _nodeAddress;
        !           548: }
        !           549: 
        !           550: #if 0
        !           551: 
        !           552: - (token_addr_t)groupAddress
        !           553: {
        !           554:     return _groupAddress;
        !           555: }
        !           556: 
        !           557: - (token_addr_t)functionalAddress
        !           558: {
        !           559:     return _functionalAddress;
        !           560: }
        !           561: 
        !           562: #endif 0
        !           563: 
        !           564: /*
        !           565:  * Implement the IONetworkDeviceMethods protocol
        !           566:  */
        !           567:  
        !           568: - (int)finishInitialization
        !           569: {
        !           570:     int        result = 0;
        !           571: 
        !           572:     if (!_flags._isRunning)
        !           573:        result = [_driverCmd send:RESET_ON];
        !           574: 
        !           575:     return (result);
        !           576: }
        !           577: 
        !           578: - (BOOL)resetAndEnable:(BOOL)enable
        !           579: {
        !           580:     return YES;
        !           581: }
        !           582: 
        !           583: - (void)transmit:(netbuf_t)pkt
        !           584: {
        !           585:     nb_free(pkt);
        !           586: }
        !           587: 
        !           588: 
        !           589: /*
        !           590:  * Token-ring transmit.  Invokes [self transmit] in subclass 
        !           591:  * to do actual hardware-specific transmission.
        !           592:  */
        !           593: - (int)outputPacket :(netbuf_t)nb address:(void *)dest_addr
        !           594: {
        !           595: 
        !           596:     int                maclen;
        !           597:     tokenHeader_t      *th = (tokenHeader_t *)dest_addr;
        !           598: 
        !           599:     /* 
        !           600:      * Bail out if our hardware is down.
        !           601:      */
        !           602:     if(!_flags._isRunning) {
        !           603:        nb_free(nb);
        !           604:        return TRINGDOWN;
        !           605:     }
        !           606: 
        !           607:     /* 
        !           608:      * Return error if data-field too large (shouldn't happen by
        !           609:      * well behaved code, but we include for safety).
        !           610:      */
        !           611:     if(nb_size(nb) > _maxInfoFieldSize) {
        !           612:        IOLog("%s: netOutput bad frame size=%d\n",
        !           613:            [self name], nb_size(nb));
        !           614:        nb_free(nb);
        !           615:        return TBADFSIZE; 
        !           616:     }
        !           617: 
        !           618:     /*
        !           619:      * Get the callers MAC header length (which is variable, due
        !           620:      * to the source routing field).
        !           621:      */
        !           622:     maclen = get_8025_hdr_len(th); 
        !           623:     if(maclen < 0) {
        !           624:        IOLog("%s: bad mac header\n", [self name]);
        !           625:        nb_free(nb);
        !           626:        return TBADFSIZE;  
        !           627:     }
        !           628: 
        !           629:     /*
        !           630:      * Add the 802.5 MAC header to the net buffer.  Note that when
        !           631:      * we allocate buffers we reserve MAC_HDR_MAX (the largest possible
        !           632:      * MAC header).  Here we grow the buffer so that the actual MAC header
        !           633:      * just fits.  The packet data is therefore contiguous (as opposed to
        !           634:      * a gap between the unused portion of the MAC header and the data
        !           635:      * field).  This saves the subclass from needing to deal with
        !           636:      * fragmentation.  This is all great as long as the subclass
        !           637:      * hardware only requires even-aligned data.  Otherwise the subclass
        !           638:      * must implement its' own outputPacket method or copy the data
        !           639:      * (sorry).
        !           640:      */
        !           641:     nb_grow_top(nb, maclen);  // grow buffer so that mac header just fits
        !           642:     th = (tokenHeader_t *)nb_map(nb);
        !           643:     bcopy(dest_addr, th, maclen); /* copy da to tx buf */
        !           644:     th->ac &= 0xf0; /* mask all but token priority & mon bits */
        !           645: 
        !           646:     /*
        !           647:      * Subclass does hdw-specific transmit.
        !           648:      */
        !           649:     [self transmit:nb];         
        !           650: 
        !           651:     return 0;
        !           652: }
        !           653: 
        !           654: /*
        !           655:  * Netif get-buffer method.   
        !           656:  *
        !           657:  * This generic version doesn't insure buffer alignment or prevent page
        !           658:  * spanning.  Subclass should override if needed (as does TokenExpress).
        !           659:  */
        !           660: - (netbuf_t)allocateNetbuf
        !           661: {
        !           662:     netbuf_t nb;
        !           663: 
        !           664:     nb = nb_alloc(_maxInfoFieldSize + MAC_HDR_MAX);
        !           665:     if (nb)
        !           666:        nb_shrink_top(nb, MAC_HDR_MAX);  /* reserve space for max 802.5 hdr */
        !           667:            
        !           668:     return nb;         
        !           669: }
        !           670: 
        !           671: /*
        !           672:  * Netif command method.
        !           673:  */
        !           674: - (int)performCommand:(const char *)command data:(void *)data
        !           675: {
        !           676:     int        rtn = 0;
        !           677: 
        !           678:     if (strcmp(command, IFCONTROL_SETFLAGS) == 0) 
        !           679:        return(rtn);
        !           680: 
        !           681:     else if (strcmp(command, IFCONTROL_GETADDR) == 0) {
        !           682:        bcopy((void *)&_nodeAddress, data, sizeof(_nodeAddress));
        !           683:     } 
        !           684:     
        !           685:     else {
        !           686:        rtn = EINVAL;
        !           687:     }
        !           688: 
        !           689:     return (rtn);
        !           690: }
        !           691: 
        !           692: @end
        !           693: 
        !           694: @implementation IOTokenRing(PrivateMethods)
        !           695: 
        !           696: //
        !           697: // Used to handle a synchronous
        !           698: // command sent by another thread
        !           699: // to the driver thread.
        !           700: //
        !           701: - (void)commandRequestOccurred
        !           702: {
        !           703:     int                oper = [_driverCmd oper];
        !           704:     int                result = 0;
        !           705: 
        !           706:     switch (oper) {
        !           707:     
        !           708:     case RESET_ON:
        !           709:        if (!_flags._isRunning) {
        !           710:            if (![self resetAndEnable:TRUE])
        !           711:                result = EIO;
        !           712:        }
        !           713:        [_driverCmd done:result];
        !           714:        break;
        !           715:     
        !           716:     case RESET_OFF:
        !           717:        [self resetAndEnable:FALSE];
        !           718:        _flags._isRunning = FALSE;
        !           719:        [_driverCmd done:result];
        !           720:        break;
        !           721: 
        !           722:     case TERMINATE:
        !           723:        [_driverCmd done:result];
        !           724:        IOExitThread();
        !           725:        break;
        !           726:     }
        !           727: }
        !           728: 
        !           729: @end
        !           730: 
        !           731: static void
        !           732: TokenRingTimeout(IOTokenRing *device)
        !           733: {
        !           734:     msg_header_t       msg = { 0 };
        !           735:     
        !           736:     if (device->_absTimeout > 0) {     
        !           737:        device->_absTimeout = 0;
        !           738:        
        !           739:     
        !           740:        msg.msg_size = sizeof (msg);
        !           741:        msg.msg_remote_port = IOGetKernPort([device interruptPort]);
        !           742:        msg.msg_id =  IO_TIMEOUT_MSG;
        !           743:        
        !           744:        msg_send_from_kernel(&msg, MSG_OPTION_NONE, 0);
        !           745:     }
        !           746: }
        !           747: 

unix.superglobalmegacorp.com

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