|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * DRI: Michael Burg ! 26: */ ! 27: ! 28: ! 29: #include <IOKit/IOLib.h> ! 30: #include <IOKit/IOService.h> ! 31: #include <IOKit/IODeviceMemory.h> ! 32: #include <IOKit/IOPlatformExpert.h> ! 33: ! 34: #include "AppleIntelClassicPIC.h" ! 35: ! 36: #define outb(port, datum) \ ! 37: __asm__ volatile("outb %b0, %1" : : "a" ((unsigned char)(datum)), "i" ((unsigned short)port)) ! 38: ! 39: #define send_duel_eoi(port1, port2) \ ! 40: __asm__ volatile("outb %b0, %1 ; outb %b0, %2" : : "a" (kEOICommand), "i" ((unsigned short)port1), "i" ((unsigned short)port2)) ! 41: ! 42: ! 43: #define kIntelReservedIntVectors 0x40 ! 44: ! 45: extern "C" { ! 46: /* HACK, HACK, HACK.. for rtclock on intel.. FIXME */ ! 47: extern void (*IOKitRegisterInterruptHook)(void *, int, int); ! 48: }; ! 49: ! 50: static AppleIntelClassicPIC *picObjectHook; ! 51: ! 52: IOInterruptController *gIntelInterruptController; ! 53: ! 54: extern OSSymbol *gIntelPICName; ! 55: ! 56: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 57: ! 58: #undef super ! 59: #define super IOInterruptController ! 60: ! 61: OSDefineMetaClassAndStructors(AppleIntelClassicPIC, IOInterruptController); ! 62: ! 63: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ ! 64: ! 65: bool AppleIntelClassicPIC::start(IOService *provider) ! 66: { ! 67: IOInterruptAction handler; ! 68: int cnt; ! 69: ! 70: if (!super::start(provider)) ! 71: return false; ! 72: ! 73: ! 74: // Allocate the memory for the vectors. ! 75: vectors = (IOInterruptVector *)IOMalloc(kNumVectors * ! 76: sizeof(IOInterruptVector)); ! 77: if (vectors == NULL) return false; ! 78: ! 79: bzero(vectors, kNumVectors * sizeof(IOInterruptVector)); ! 80: ! 81: ! 82: // Allocate locks for the vectors. ! 83: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 84: vectors[cnt].interruptLock = IOLockAlloc(); ! 85: if (vectors[cnt].interruptLock == NULL) { ! 86: for (cnt = 0; cnt < kNumVectors; cnt++) { ! 87: if (vectors[cnt].interruptLock != NULL) ! 88: IOLockFree(vectors[cnt].interruptLock); ! 89: } ! 90: return false; ! 91: } ! 92: } ! 93: ! 94: maskInterrupts = 0xffff & ~(1<<kPICSlaveID); /* Mask out the interrupts except for the casacde line */ ! 95: ! 96: /* Setup the interrupt controller.. */ ! 97: /* Original code taken from FreeBSD's sys/i386/isa/intr_machdep.c */ ! 98: ! 99: /* initialize 8259's */ ! 100: outb(kPIC1BasePort, 0x11); /* reset; program device, four bytes */ ! 101: ! 102: /* starting at this vector index */ ! 103: outb(kPIC1BasePort+kPICDataPortOffset, kIntelReservedIntVectors); ! 104: ! 105: outb(kPIC1BasePort+kPICDataPortOffset, kPICSlaveIRQID); /* slave on line 7 */ ! 106: ! 107: outb(kPIC1BasePort+kPICDataPortOffset, 1); /* 8086 mode */ ! 108: ! 109: outb(kPIC1BasePort+kPICDataPortOffset, 0xff); /* leave interrupts masked */ ! 110: outb(kPIC1BasePort, 0x0a); /* default to IRR on read */ ! 111: outb(kPIC1BasePort, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ ! 112: ! 113: outb(kPIC2BasePort, 0x11); /* reset; program device, four bytes */ ! 114: outb(kPIC2BasePort+kPICDataPortOffset, kIntelReservedIntVectors+8); /* staring at this vector index */ ! 115: outb(kPIC2BasePort+kPICDataPortOffset, kPICSlaveID); /* my slave id is 7 */ ! 116: outb(kPIC2BasePort+kPICDataPortOffset,1); /* 8086 mode */ ! 117: outb(kPIC2BasePort+kPICDataPortOffset, 0xff); /* leave interrupts masked */ ! 118: outb(kPIC2BasePort, 0x0a); /* default to IRR on read */ ! 119: ! 120: // Primary interrupt controller ! 121: getPlatform()->setCPUInterruptProperties(provider); ! 122: ! 123: // setup clock interrupt back door hook ! 124: IOKitRegisterInterruptHook = getRegisterInterruptHookAddress(); ! 125: picObjectHook = this; ! 126: ! 127: // register the interrupt handler so it can receive interrupts. ! 128: handler = getInterruptHandlerAddress(); ! 129: if (provider->registerInterrupt(0, this, handler, 0) != kIOReturnSuccess) ! 130: panic("AppleIntelClassicPIC: Failed to install platform interrupt handler"); ! 131: provider->enableInterrupt(0); ! 132: ! 133: // Register this interrupt controller so clients can find it. ! 134: getPlatform()->registerInterruptController(gIntelPICName, this) ; ! 135: gIntelInterruptController = this; ! 136: ! 137: return true; ! 138: } ! 139: ! 140: IOReturn AppleIntelClassicPIC::getInterruptType(IOService */*nub*/, ! 141: int /*source*/, ! 142: int *interruptType) ! 143: { ! 144: if (interruptType == 0) return kIOReturnBadArgument; ! 145: ! 146: *interruptType = kIOInterruptTypeEdge; ! 147: ! 148: return kIOReturnSuccess; ! 149: } ! 150: ! 151: IOInterruptAction AppleIntelClassicPIC::getInterruptHandlerAddress(void) ! 152: { ! 153: void *value; ! 154: ! 155: value = (void *) &AppleIntelClassicPIC::handleInterrupt; ! 156: ! 157: return (IOInterruptAction)(value); ! 158: } ! 159: ! 160: IOReturn AppleIntelClassicPIC::handleInterrupt(void *savedState, ! 161: IOService */*nub*/, ! 162: int vectorNumber) ! 163: { ! 164: IOInterruptVector *vector; ! 165: typedef void (*IntelClockFuncType)(void *); ! 166: IntelClockFuncType clockFunc; ! 167: ! 168: vectorNumber -= kIntelReservedIntVectors; ! 169: ! 170: if (vectorNumber >= kNumVectors) return kIOReturnSuccess; ! 171: ! 172: maskInterrupts |= (1 << vectorNumber); ! 173: ! 174: if (vectorNumber > 7) { ! 175: /* Mask out interrupt */ ! 176: outb(kPIC2BasePort+kPICDataPortOffset, maskInterrupts >> 8); ! 177: ! 178: /* Acknowledge interrupt */ ! 179: send_duel_eoi(kPIC2BasePort+kPICCmdPortOffset, kPIC1BasePort+kPICCmdPortOffset); ! 180: } else { ! 181: outb(kPIC1BasePort+kPICDataPortOffset, maskInterrupts & 0xff); ! 182: outb(kPIC1BasePort+kPICCmdPortOffset, kEOICommand); ! 183: } ! 184: ! 185: vector = &vectors[vectorNumber]; ! 186: ! 187: vector->interruptActive = 1; ! 188: if (!vector->interruptDisabledSoft) { ! 189: if (vector->interruptRegistered) { ! 190: if (vectorNumber == kClockIRQ) { ! 191: clockFunc = (IntelClockFuncType) vector->handler; ! 192: clockFunc(savedState); ! 193: } else { ! 194: vector->handler(vector->target, vector->refCon, ! 195: vector->nub, vector->source); ! 196: } ! 197: maskInterrupts &= ~(1 << vectorNumber); ! 198: } ! 199: } else { ! 200: printf("*** DISABLING INT %d\n", vectorNumber); ! 201: // Hard disable the source. ! 202: vector->interruptDisabledHard = 1; ! 203: disableVectorHard(vectorNumber, vector); ! 204: } ! 205: ! 206: if (vectorNumber > 7) ! 207: outb(kPIC2BasePort+kPICDataPortOffset, maskInterrupts >> 8); ! 208: else ! 209: outb(kPIC1BasePort+kPICDataPortOffset, maskInterrupts & 0xff ); ! 210: ! 211: ! 212: vector->interruptActive = 0; ! 213: ! 214: return kIOReturnSuccess; ! 215: } ! 216: ! 217: bool AppleIntelClassicPIC::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/) ! 218: { ! 219: /* FIXME! Need to account for PCI sharable interrupts */ ! 220: return false; ! 221: } ! 222: ! 223: void AppleIntelClassicPIC::initVector(long /*vectorNumber*/, ! 224: IOInterruptVector * /*vector*/) ! 225: { ! 226: /* Do nothing.. */ ! 227: } ! 228: ! 229: void AppleIntelClassicPIC::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/) ! 230: { ! 231: if (vectorNumber == kPICSlaveID) /* Sorry, cacade interrupt cannot be disable */ ! 232: return; ! 233: ! 234: maskInterrupts |= (1<<vectorNumber); ! 235: ! 236: /* Load up mask interrupts */ ! 237: if (vectorNumber > 7) ! 238: outb(kPIC2BasePort + kPICDataPortOffset, maskInterrupts >> 8); ! 239: else ! 240: outb(kPIC1BasePort + kPICDataPortOffset, maskInterrupts & 0xff); ! 241: } ! 242: ! 243: void AppleIntelClassicPIC::enableVector(long vectorNumber, ! 244: IOInterruptVector *vector) ! 245: { ! 246: maskInterrupts &= ~(1<<vectorNumber); ! 247: ! 248: /* Load up mask interrupts */ ! 249: if (vectorNumber > 7) ! 250: outb(kPIC2BasePort + kPICDataPortOffset, maskInterrupts >> 8); ! 251: else ! 252: outb(kPIC1BasePort + kPICDataPortOffset, maskInterrupts & 0xff); ! 253: } ! 254: ! 255: static void AppleIntelClassicPICRegisterHook(void *func, int source, int isclock) ! 256: { ! 257: picObjectHook->registerInterruptHook(func, source, isclock); ! 258: } ! 259: ! 260: void AppleIntelClassicPIC::registerInterruptHook(void *func, int source, int isclock) ! 261: { ! 262: IOInterruptVector *vector; ! 263: ! 264: vector = &vectors[source]; ! 265: ! 266: vector->handler = (IOInterruptHandler) func; ! 267: vector->interruptRegistered = TRUE; ! 268: vector->interruptDisabledSoft = FALSE; ! 269: vector->interruptDisabledHard = FALSE; ! 270: ! 271: enableVector(source, vector); ! 272: } ! 273: ! 274: ! 275: IOKitInterruptHookType ! 276: AppleIntelClassicPIC::getRegisterInterruptHookAddress(void) ! 277: { ! 278: void *value; ! 279: value = (void *) AppleIntelClassicPICRegisterHook; ! 280: return (IOKitInterruptHookType) value; ! 281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.