|
|
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: /*
26: * Copyright (c) 1993, 1994 NeXT Computer, Inc.
27: *
28: * Kernel Device Object.
29: *
30: * HISTORY
31: *
32: * 1 Jul 1994 ? at NeXT
33: * Modifications for shared interrupts.
34: * 27 Feb 1994 ? at NeXT
35: * Major rewrite.
36: * 3 Oct 1993 ? at NeXT
37: * Created.
38: */
39:
40: #import <mach/mach_types.h>
41:
42: #import <objc/List.h>
43:
44: #import <driverkit/kernelDriver.h>
45: #import <driverkit/interruptMsg.h>
46: #import <driverkit/KernDevice.h>
47: #import <driverkit/KernDevicePrivate.h>
48: #import <driverkit/KernBusInterrupt.h>
49: #import <driverkit/KernDeviceDescription.h>
50: #import <driverkit/KernLock.h>
51:
52: #import <kernserv/machine/spl.h>
53:
54: @implementation KernDevice
55:
56: - initWithDeviceDescription: deviceDescription
57: {
58: if (deviceDescription == nil)
59: return [self free];
60:
61: [super init];
62:
63: _deviceDescription = deviceDescription;
64:
65: return self;
66: }
67:
68: - init
69: {
70: return [self free];
71: }
72:
73: - free
74: {
75: [self detachInterruptPort];
76:
77: return [super free];
78: }
79:
80: - deviceDescription
81: {
82: return _deviceDescription;
83: }
84:
85: - attachInterruptPort: (port_t)interruptPort
86: {
87: ipc_port_t port;
88: id interrupts;
89: int i, numInterrupts;
90:
91: if (_interruptPort != IP_NULL)
92: return nil;
93:
94: if (ipc_object_copyin(current_task()->itk_space,
95: interruptPort, MACH_MSG_TYPE_MAKE_SEND,
96: &port))
97: return nil;
98:
99: interrupts = [_deviceDescription interrupts];
100: if (interrupts == nil) {
101: ipc_port_release_send(port);
102: return self;
103: }
104:
105: numInterrupts = [interrupts count];
106: if (numInterrupts == 0) {
107: ipc_port_release_send(port);
108: return self;
109: }
110:
111: _interruptPort = port;
112:
113: _interrupts = [[List alloc] initCount:numInterrupts];
114:
115: for (i = 0; i < numInterrupts; i++) {
116: if (![_interrupts addObject:
117: [[KernDeviceInterrupt alloc]
118: initWithInterruptPort:_interruptPort]]) {
119: [self _detachInterruptSources];
120: ipc_port_release_send(_interruptPort);
121: _interruptPort = IP_NULL;
122: return nil;
123: }
124: }
125:
126: return self;
127: }
128:
129: - detachInterruptPort
130: {
131: if (_interruptPort == IP_NULL)
132: return self;
133:
134: [self _detachInterruptSources];
135:
136: ipc_port_release_send(_interruptPort);
137: _interruptPort = IP_NULL;
138:
139: return self;
140: }
141:
142: - interrupt: (int)index
143: {
144: return [_interrupts objectAt:index];
145: }
146:
147: - interrupts
148: {
149: return _interrupts;
150: }
151:
152: @end
153:
154: @implementation KernDevice(Private)
155:
156: - (void)_detachInterruptSources
157: {
158: if (_interrupts != nil) {
159: [[_interrupts freeObjects] free];
160:
161: _interrupts = nil;
162: }
163: }
164:
165: @end
166:
167: @implementation KernDeviceInterrupt
168:
169: - initWithInterruptPort: (void *)port
170: {
171: [super init];
172:
173: _lock = [[KernLock alloc] initWithLevel:IPLHIGH];
174:
175: _ipcMessage = _KernDeviceInterruptMsgCreate(port);
176:
177: return self;
178: }
179:
180: - free
181: {
182: [self detach];
183:
184: [_lock free];
185:
186: _KernDeviceInterruptMsgDestroy(_ipcMessage);
187:
188: return [super free];
189: }
190:
191: - attachToBusInterrupt: busInterrupt
192: withArgument: (void *)argument
193: {
194: [_lock acquire];
195:
196: if (_busInterrupt) {
197: [_lock release];
198: return nil;
199: }
200:
201: _busInterrupt = busInterrupt;
202:
203: [_lock release];
204:
205: [busInterrupt suspend];
206:
207: if (![busInterrupt attachDeviceInterrupt:self]) {
208: [busInterrupt resume];
209:
210: [_lock acquire];
211: _busInterrupt = nil;
212: [_lock release];
213:
214: return nil;
215: }
216:
217: [_lock acquire];
218:
219: _handler = IOSendInterrupt;
220: _handlerArgument = argument;
221:
222: [_lock release];
223:
224: [busInterrupt resume];
225:
226: return self;
227: }
228:
229: - attachToBusInterrupt: busInterrupt
230: withSpecialHandler: (void *)handler
231: argument: (void *)argument
232: atLevel: (int)level
233: {
234: [_lock acquire];
235:
236: if (_busInterrupt) {
237: [_lock release];
238: return nil;
239: }
240:
241: _busInterrupt = busInterrupt;
242:
243: [_lock release];
244:
245: [busInterrupt suspend];
246:
247: if (![_busInterrupt attachDeviceInterrupt:self atLevel:level]) {
248: [busInterrupt resume];
249:
250: [_lock acquire];
251: _busInterrupt = nil;
252: [_lock release];
253:
254: return nil;
255: }
256:
257: [_lock acquire];
258:
259: _handler = handler;
260: _handlerArgument = argument;
261:
262: [_lock release];
263:
264: [busInterrupt resume];
265:
266: return self;
267: }
268:
269: - detach
270: {
271: id busInterrupt;
272: BOOL isSuspended;
273:
274: [_lock acquire];
275:
276: if (!_busInterrupt) {
277: [_lock release];
278: return nil;
279: }
280:
281: busInterrupt = _busInterrupt; _busInterrupt = nil;
282: isSuspended = _isSuspended; _isSuspended = NO;
283:
284: [_lock release];
285:
286: if (!isSuspended)
287: [busInterrupt suspend];
288:
289: [busInterrupt detachDeviceInterrupt:self];
290:
291: [busInterrupt resume];
292:
293: return self;
294: }
295:
296: - suspend
297: {
298: id busInterrupt;
299: BOOL isSuspended;
300:
301: [_lock acquire];
302:
303: if (!_busInterrupt) {
304: [_lock release];
305: return nil;
306: }
307:
308: busInterrupt = _busInterrupt;
309: isSuspended = _isSuspended; _isSuspended = YES;
310:
311: [_lock release];
312:
313: if (!isSuspended)
314: [busInterrupt suspend];
315:
316: return self;
317: }
318:
319: - resume
320: {
321: id busInterrupt;
322: BOOL isSuspended;
323:
324: [_lock acquire];
325:
326: if (!_busInterrupt) {
327: [_lock release];
328: return nil;
329: }
330:
331: busInterrupt = _busInterrupt;
332: isSuspended = _isSuspended; _isSuspended = NO;
333:
334: [_lock release];
335:
336: if (isSuspended)
337: [busInterrupt resume];
338:
339: return self;
340: }
341:
342: @end
343:
344: static
345: KernDeviceInterruptMsg *
346: _KernDeviceInterruptMsgCreate(
347: ipc_port_t interruptPort
348: )
349: {
350: KernDeviceInterruptMsg *msg;
351:
352: msg = (void *)kalloc(sizeof (*msg));
353: *msg = (KernDeviceInterruptMsg) { 0 };
354:
355: msg->lock = [[KernLock alloc] initWithLevel:IPLSCHED];
356:
357: ipc_port_reference(interruptPort);
358: msg->iport = interruptPort;
359:
360: msg->callout.func = (thread_call_func_t)_KernDeviceInterruptCallout;
361: msg->callout.spec_proto = msg;
362: msg->callout.status = IDLE;
363:
364: ikm_init_special(&msg->kmsg, IKM_SIZE_DEVICE);
365:
366: ipc_port_reference(msg->iport);
367:
368: return msg;
369: }
370:
371: static
372: void
373: _KernDeviceInterruptMsgDestroy(
374: KernDeviceInterruptMsg *msg
375: )
376: {
377: KernLockAcquire(msg->lock);
378: if (msg->queued || msg->pending) {
379: msg->destroy = YES;
380: KernLockRelease(msg->lock);
381: return;
382: }
383: KernLockRelease(msg->lock);
384:
385: ipc_port_release(msg->iport);
386: ipc_port_release(msg->iport);
387:
388: [msg->lock free];
389:
390: kfree(msg, sizeof (*msg));
391: }
392:
393: void
394: KernDeviceInterruptMsgRelease(
395: void *m
396: )
397: {
398: KernDeviceInterruptMsg *msg = m;
399:
400: ipc_port_reference(msg->iport);
401:
402: KernLockAcquire(msg->lock);
403: msg->queued = FALSE;
404: if (msg->destroy) {
405: KernLockRelease(msg->lock);
406: _KernDeviceInterruptMsgDestroy(msg);
407: }
408: else
409: KernLockRelease(msg->lock);
410: }
411: #if sparc
412: int
413: #else
414: void
415: #endif
416: KernDeviceInterruptDispatch(
417: KernDeviceInterrupt *_interrupt,
418: void *state
419: )
420: {
421: KernDeviceInterrupt_ *interrupt =
422: (KernDeviceInterrupt_ *)_interrupt;
423: #if sparc
424: int (*handler)() = interrupt->_handler;
425: return((*handler)(interrupt, state, interrupt->_handlerArgument));
426: #else
427: void (*handler)() = interrupt->_handler;
428: (*handler)(interrupt, state, interrupt->_handlerArgument);
429:
430: #endif
431:
432: }
433:
434: void
435: KernDeviceInterruptDispatchShared(
436: KernDeviceInterrupt *_interrupt,
437: void *state
438: )
439: {
440: KernDeviceInterrupt_ *interrupt =
441: (KernDeviceInterrupt_ *)_interrupt;
442: void (*handler)() = interrupt->_handler;
443:
444: IODisableInterrupt(interrupt);
445:
446: (*handler)(interrupt, state, interrupt->_handlerArgument);
447: }
448:
449: void
450: IOEnableInterrupt(
451: void *_interrupt
452: )
453: {
454: KernDeviceInterrupt_ *interrupt =
455: (KernDeviceInterrupt_ *)_interrupt;
456: KernBusInterrupt *busInterrupt;
457: BOOL isSuspended;
458:
459: KernLockAcquire(interrupt->_lock);
460:
461: busInterrupt = interrupt->_busInterrupt;
462: isSuspended = interrupt->_isSuspended; interrupt->_isSuspended = NO;
463:
464: KernLockRelease(interrupt->_lock);
465:
466: if (isSuspended)
467: KernBusInterruptResume(busInterrupt);
468: }
469:
470: void
471: IODisableInterrupt(
472: void *_interrupt
473: )
474: {
475: KernDeviceInterrupt_ *interrupt =
476: (KernDeviceInterrupt_ *)_interrupt;
477: KernBusInterrupt *busInterrupt;
478: BOOL isSuspended;
479:
480: KernLockAcquire(interrupt->_lock);
481:
482: busInterrupt = interrupt->_busInterrupt;
483: isSuspended = interrupt->_isSuspended; interrupt->_isSuspended = YES;
484:
485: KernLockRelease(interrupt->_lock);
486:
487: if (!isSuspended)
488: KernBusInterruptSuspend(busInterrupt);
489: }
490:
491: /*
492: * Template for creating interrupt messages.
493: */
494:
495: typedef struct _InterruptMsg {
496: mach_msg_header_t header;
497: } InterruptMsg;
498:
499: static InterruptMsg interruptMsgTemplate = {
500: {
501: MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0),
502: sizeof (InterruptMsg),
503: MACH_PORT_NULL,
504: MACH_PORT_NULL,
505: 0,
506: IO_DEVICE_INTERRUPT_MSG
507: }
508: };
509:
510: void
511: IOSendInterrupt(
512: void *_interrupt,
513: void *state,
514: unsigned int msgId
515: )
516: {
517: KernDeviceInterrupt_ *interrupt = _interrupt;
518: KernDeviceInterruptMsg *msg = interrupt->_ipcMessage;
519: InterruptMsg *imsg;
520: mach_msg_return_t result;
521:
522: if (curipl() > IPLSCHED)
523: return;
524:
525: KernLockAcquire(msg->lock);
526: if (msg->queued || msg->pending) {
527: KernLockRelease(msg->lock);
528: return;
529: }
530: msg->queued = YES;
531: KernLockRelease(msg->lock);
532:
533: imsg = (InterruptMsg *)&msg->kmsg.ikm_header;
534: *imsg = interruptMsgTemplate;
535: imsg->header.msgh_id = msgId;
536: imsg->header.msgh_remote_port = (mach_port_t)msg->iport;
537:
538: result = ipc_mqueue_send_interrupt(&msg->kmsg);
539: if (result != MACH_MSG_SUCCESS) {
540: KernLockAcquire(msg->lock);
541: msg->queued = NO;
542: msg->pending = YES;
543: KernLockRelease(msg->lock);
544:
545: thread_call_enter(&msg->callout);
546: }
547: }
548:
549: static
550: void
551: _KernDeviceInterruptCallout(
552: KernDeviceInterruptMsg *msg
553: )
554: {
555: mach_msg_return_t result;
556:
557: KernLockAcquire(msg->lock);
558: msg->pending = NO;
559: msg->queued = YES;
560: KernLockRelease(msg->lock);
561:
562: result = ipc_mqueue_send(
563: &msg->kmsg,
564: MACH_SEND_ALWAYS | MACH_SEND_TIMEOUT,
565: 0, IMQ_NULL_CONTINUE);
566: if (result != MACH_MSG_SUCCESS) {
567: ipc_port_release(msg->iport);
568: KernDeviceInterruptMsgRelease(msg);
569: }
570: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.