1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved.
30 *
31 *  DRI: Josh de Cesare
32 */
33
34#include <IOKit/IOPlatformExpert.h>
35
36#include "GenericInterruptController.h"
37
38/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
39
40#undef  super
41#define super IOInterruptController
42
43IODefineMetaClassAndStructors(GenericInterruptController,
44			      IOInterruptController);
45
46/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47
48
49bool GenericInterruptController::start(IOService *provider)
50{
51  IOInterruptAction    handler;
52  IOSymbol             *interruptControllerName;
53
54  // If needed call the parents start.
55  if (!super::start(provider))
56    return false;
57
58  // Map the device's memory and initalize its state.
59
60  // For now you must allocate storage for the vectors.
61  // This will probably changed to something like: initVectors(numVectors).
62  // In the mean time something like this works well.
63#if 0
64  // Allocate the memory for the vectors.
65  vectors = (IOInterruptVector *)IOMalloc(numVectors *
66					  sizeof(IOInterruptVector));
67  if (vectors == NULL) return false;
68  bzero(vectors, numVectors * sizeof(IOInterruptVector));
69
70  // Allocate locks for the vectors.
71  for (cnt = 0; cnt < numVectors; cnt++) {
72    vectors[cnt].interruptLock = IOLockAlloc();
73    if (vectors[cnt].interruptLock == NULL) {
74      for (cnt = 0; cnt < numVectors; cnt++) {
75	if (vectors[cnt].interruptLock != NULL)
76	  IOLockFree(vectors[cnt].interruptLock);
77      }
78    }
79  }
80#endif
81
82  // If you know that this interrupt controller is the primary
83  // interrupt controller, use this to set it nub properties properly.
84  // This may be done by the nub's creator.
85  getPlatform()->setCPUInterruptProperties(provider);
86
87  // register the interrupt handler so it can receive interrupts.
88  handler = getInterruptHandlerAddress();
89  provider->registerInterrupt(0, this, handler, 0);
90
91  // Just like any interrupt source, you must enable it to receive interrupts.
92  provider->enableInterrupt(0);
93
94  // Set interruptControllerName to the proper symbol.
95  //interruptControllerName = xxx;
96
97  // Register this interrupt controller so clients can find it.
98  getPlatform()->registerInterruptController(interruptControllerName, this);
99
100  // All done, so return true.
101  return true;
102}
103
104IOReturn GenericInterruptController::getInterruptType(IOService *nub,
105						      int source,
106						      int *interruptType)
107{
108  if (interruptType == 0) return kIOReturnBadArgument;
109
110  // Given the nub and source, set interruptType to level or edge.
111
112  return kIOReturnSuccess;
113}
114
115// Sadly this just has to be replicated in every interrupt controller.
116IOInterruptAction GenericInterruptController::getInterruptHandlerAddress(void)
117{
118  return (IOInterruptAction)handleInterrupt;
119}
120
121// Handle all current interrupts.
122IOReturn GenericInterruptController::handleInterrupt(void * refCon,
123						     IOService * nub,
124						     int source)
125{
126  IOInterruptVector *vector;
127  int               vectorNumber;
128
129  while (1) {
130    // Get vectorNumber from hardware some how and clear the event.
131
132    // Break if there are no more vectors to handle.
133    if (vectorNumber == 0/*kNoVector*/) break;
134
135    // Get the vector's date from the controller's array.
136    vector = &vectors[vectorNumber];
137
138    // Set the vector as active. This store must compleat before
139    // moving on to prevent the disableInterrupt fuction from
140    // geting out of sync.
141    vector->interruptActive = 1;
142    //sync();
143    //isync();
144
145    // If the vector is not disabled soft, handle it.
146    if (!vector->interruptDisabledSoft) {
147      // Prevent speculative exacution as needed on your processor.
148      //isync();
149
150      // Call the handler if it exists.
151      if (vector->interruptRegistered) {
152	vector->handler(vector->target, vector->refCon,
153			vector->nub, vector->source);
154      }
155    } else {
156      // Hard disable the vector if is was only soft disabled.
157      vector->interruptDisabledHard = 1;
158      disableVectorHard(vectorNumber, vector);
159    }
160
161    // Done with this vector so, set it back to inactive.
162    vector->interruptActive = 0;
163  }
164
165  return kIOReturnSuccess;
166}
167
168bool GenericInterruptController::vectorCanBeShared(long vectorNumber,
169						   IOInterruptVector *vector)
170{
171  // Given the vector number and the vector data, return if it can be shared.
172  return true;
173}
174
175void GenericInterruptController::initVector(long vectorNumber,
176					    IOInterruptVector *vector)
177{
178  // Given the vector number and the vector data,
179  // get the hardware ready for the vector to generate interrupts.
180  // Make sure the vector is left disabled.
181}
182
183void GenericInterruptController::disableVectorHard(long vectorNumber,
184						   IOInterruptVector *vector)
185{
186  // Given the vector number and the vector data,
187  // disable the vector at the hardware.
188}
189
190void GenericInterruptController::enableVector(long vectorNumber,
191					      IOInterruptVector *vector)
192{
193  // Given the vector number and the vector data,
194  // enable the vector at the hardware.
195}
196
197void GenericInterruptController::causeVector(long vectorNumber,
198					     IOInterruptVector *vector)
199{
200  // Given the vector number and the vector data,
201  // Set the vector pending and cause an interrupt at the parent controller.
202
203  // cause the interrupt at the parent controller.  Source is usually zero,
204  // but it could be different for your controller.
205  getPlatform()->causeInterrupt(0);
206}
207