|
|
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: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
26: *
27: * autoconfCommon.m - machine-independent driverkit-style
28: * autoconfiguration routines.
29: *
30: * HISTORY
31: * 23-Jan-93 Doug Mitchell at NeXT
32: * Created.
33: */
34:
35: #import <mach/mach_types.h>
36:
37: #import <driverkit/autoconfCommon.h>
38: #import <driverkit/Device_ddm.h>
39: #import <driverkit/generalFuncs.h>
40: #import <driverkit/kernelDriver.h>
41: #import <machkit/NXLock.h>
42: #import <driverkit/driverTypes.h>
43: #import <driverkit/volCheck.h>
44:
45: #import <vm/vm_kern.h>
46:
47: #import <sys/param.h>
48: #import <sys/proc.h>
49: #import <sys/user.h>
50: #import <sys/buf.h>
51: #import <sys/systm.h>
52: #import <dev/busvar.h>
53:
54: extern task_t IOTask_kern; // kernel internal version of IOTask
55: extern port_t IOTask; // IOTask port name in IOTask space.
56:
57: /*
58: * Static data.
59: */
60: static id autoconfLock;
61:
62: /*
63: * Static routines.
64: */
65: static void registerIndirClasses();
66: static void autoconfInt();
67: static void probePseudoDevices();
68:
69: /* Forward declaration */
70: extern port_name_t _io_task_get_port(void *kport);
71:
72: /*
73: * Top-level autoconf routine.
74: */
75: void autoconf(void)
76: {
77: struct pseudo_init *pi;
78: static void IOTaskInit(void);
79:
80: xpr_conf("autoconf\n", 1,2,3,4,5);
81: IOTaskInit();
82: IOInitGeneralFuncs();
83: volCheckInit();
84: xpr_conf("autoconf: libIO initialized\n", 1,2,3,4,5);
85:
86: /*
87: * Early startup for bsd pseudodevices.
88: */
89: for (pi = pseudo_inits; pi->ps_func; pi++)
90: (*pi->ps_func) (pi->ps_count);
91:
92: /*
93: * Set up a lock so we know when autoconf is complete.
94: */
95: autoconfLock = [NXConditionLock alloc];
96: [autoconfLock initWith:NO];
97: xpr_conf("autoconf: forking off thread\n", 1,2,3,4,5);
98:
99: /*
100: * Note since we are not currently in the IOTask context, we
101: * can't use IOForkThread.
102: */
103: kernel_thread(IOTask_kern, autoconfInt, (void *)0);
104: [autoconfLock lockWhen:YES];
105: [autoconfLock free];
106: }
107:
108: /*
109: * One-time only init for this module.
110: */
111: #ifdef i386
112: extern queue_head_t dmaBufQueue;
113: #endif i386
114:
115: static void IOTaskInit(void)
116: {
117: kern_return_t krtn;
118: extern task_t IOTask_kern;
119: extern port_name_t IOTask;
120:
121: #ifdef i386
122: queue_init(&dmaBufQueue);
123: #endif i386
124:
125: /*
126: * Start up IOTask. No threads needed yet, just the task.
127: */
128: #undef task_create
129: krtn = task_create(kernel_task,
130: FALSE,
131: &IOTask_kern);
132: if(krtn != KERN_SUCCESS) {
133: IOLog("IOLibIOInit task_create returned %d\n", krtn);
134: return;
135: }
136: task_deallocate(IOTask_kern); // extra ref for convert_task_to_port()
137: (void) vm_map_deallocate(IOTask_kern->map);
138: IOTask_kern->map = kernel_map;
139:
140: /*
141: * This allows use of mach RPCs as if from user space, while running
142: * in the kernel's pmap.
143: */
144: IOTask_kern->kernel_vm_space = TRUE;
145:
146: IOTask_kern->proc = kernproc;
147:
148: (void) processor_set_policy_enable(&default_pset, POLICY_FIXEDPRI);
149:
150: /*
151: * Get IOTask's task port in its own IPC space.
152: */
153: IOTask = _io_task_get_port(IOTask_kern->itk_sself);
154: }
155:
156: void *_io_vm_task_buf(
157: struct buf *bp
158: )
159: {
160: task_t task;
161:
162: if((bp->b_flags & (B_PHYS|B_KERNSPACE)) == B_PHYS) {
163: /*
164: * Physical I/O to user space.
165: */
166: task = bp->b_proc->task;
167: }
168: else {
169: /*
170: * Either block I/O (always kernel space) or physical I/O
171: * to kernel space (e.g., loadable file system).
172: */
173: task = IOTask_kern;
174: }
175:
176: return task->map;
177: }
178:
179: void *_io_vm_task_self(void)
180: {
181: return (IOTask_kern->map);
182: }
183:
184: void *_io_vm_task_current(void)
185: {
186: return (current_task()->map);
187: }
188:
189: void *_io_vm_task(
190: task_t task
191: )
192: {
193: return (task->map);
194: }
195:
196: void *_io_vm_task_pmap(
197: vm_map_t map
198: )
199: {
200: return (vm_map_pmap(map));
201: }
202:
203: port_name_t _io_task_get_port(
204: void * kport
205: )
206: {
207: /* External references to the mach system */
208: extern void port_reference();
209: extern void object_copyout();
210:
211: port_name_t port_name;
212:
213: port_reference(kport);
214: object_copyout(IOTask_kern,
215: kport,
216: MSG_TYPE_PORT,
217: &port_name);
218:
219: return (port_name);
220: }
221:
222: void *_io_get_kern_port(
223: port_name_t port
224: )
225: {
226: /* External references to the mach system */
227: extern boolean_t object_copyin();
228:
229: void * kport;
230:
231: if (!object_copyin(IOTask_kern,
232: port,
233: MSG_TYPE_PORT,
234: FALSE,
235: &kport))
236: return (0);
237:
238: return (kport);
239: }
240:
241: void *_io_convert_port_in(
242: port_name_t port
243: )
244: {
245: /* External references to the mach system */
246: extern boolean_t object_copyin();
247:
248: void * kport;
249:
250: if (!object_copyin(current_task(),
251: port,
252: MSG_TYPE_PORT,
253: FALSE,
254: &kport))
255: return (0);
256:
257: return (kport);
258: }
259:
260: port_name_t _io_convert_port_out(
261: void *kport
262: )
263: {
264: /* External references to the mach system */
265: extern void port_reference();
266: extern void object_copyout();
267:
268: port_name_t port_name;
269:
270: port_reference(kport);
271: object_copyout(current_task(),
272: kport,
273: MSG_TYPE_PORT,
274: &port_name);
275:
276: return (port_name);
277: }
278:
279: port_t _io_host_priv_self(void)
280: {
281: return _io_convert_port_out((void *)realhost.host_priv_self);
282: }
283:
284: /*
285: * This rest of this module runs as a thread in IOTask to allow for
286: * each driver's startup code to execute in an IOTask thread context,
287: * so standard Mach calls can be executed during probe.
288: *
289: * Note that all of the +probe: calls below may result in indirect classes
290: * being probed via IODevice's +connectToIndirectDevices method.
291: */
292:
293: static void autoconfInt(void)
294: {
295:
296: xpr_conf("autoconf_int: starting\n", 1,2,3,4,5);
297:
298: /*
299: * Register indirect device classes.
300: */
301: registerIndirClasses();
302:
303: /*
304: * Start up drivers for native devices.
305: */
306: probeNativeDevices();
307:
308: /*
309: * Perform machine dependent hardware probe/config.
310: */
311: probeHardware();
312:
313: /*
314: * Start up non-native direct drivers.
315: */
316: probeDirectDevices();
317:
318: /*
319: * Start up pseuododevices.
320: */
321: probePseudoDevices();
322:
323: /*
324: * Notify parent that we're finished, then terminate.
325: */
326: [autoconfLock lock];
327: [autoconfLock unlockWith:YES];
328: IOExitThread();
329: }
330:
331: static void registerIndirClasses(void)
332: {
333: char **indClassName = indirectDevList;
334: id indClassId;
335: for(indClassName=indirectDevList;
336: *indClassName;
337: indClassName++) {
338: indClassId = objc_getClass(*indClassName);
339: if(indClassId == nil) {
340: IOLog("registerIndirectClasses: Class %s does not "
341: "exist\n", *indClassName);
342: continue;
343: }
344: /*
345: * Objc runtime does an +initialize on the class here; the
346: * class must call registerClass at that time.
347: */
348: xpr_conf("init'ing indirect class %s\n", *indClassName,
349: 2,3,4,5);
350: [indClassId name];
351: }
352: }
353:
354: static void probePseudoDevices(void)
355: {
356: char **pseudoClassName;
357: id driverClass;
358:
359: for(pseudoClassName = pseudoDevList;
360: *pseudoClassName;
361: pseudoClassName++) {
362: xpr_conf("pseudo dev %s found\n",
363: *pseudoClassName, 2,3,4,5);
364: driverClass = objc_getClass(*pseudoClassName);
365: if(driverClass == nil) {
366: IOLog("probePseudoDevices: class %s not found\n",
367: *pseudoClassName);
368: continue;
369: }
370: [IODevice addLoadedClass:driverClass
371: description:nil];
372: }
373: }
374:
375: #import <driverkit/IODeviceParams.h>
376: #import <driverkit/IOPower.h>
377:
378: static void
379:
380: _io_sendPowerMessage(
381: SEL selector,
382: void *arg
383: )
384: {
385: IOObjectNumber i = 0;
386: id driverObject;
387: IOReturn rtn;
388:
389: /* Look for devices that conform to IOPower protocol */
390: while ((rtn = [IODevice lookupByObjectNumber:i++
391: instance:&driverObject]) != IO_R_NO_DEVICE) {
392: if (rtn == IO_R_OFFLINE)
393: continue;
394: if ([[driverObject class] conformsTo:@protocol(IOPower)]) {
395: [driverObject perform:selector with:arg];
396: }
397: }
398: }
399:
400:
401: void
402: _io_setDriverPowerState(
403: PMPowerState state
404: )
405: {
406: _io_sendPowerMessage(@selector(setPowerState:), (void *)state);
407: }
408:
409: void
410: _ioSetDriverPowerManagementState(
411: PMPowerManagementState state
412: )
413: {
414: _io_sendPowerMessage(@selector(setPowerManagement:), (void *)state);
415: }
416:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.