|
|
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(×tamp); ! 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.