|
|
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) 1991 NeXT Computer, Inc. All rights reserved.
25: *
26: * ConfigUtils.c - common utility functions for Config server.
27: *
28: * HISTORY
29: * 12-Apr-91 Doug Mitchell at NeXT
30: * Created.
31: */
32:
33: #import <bsd/sys/types.h>
34: #import <bsd/libc.h>
35: #import <mach/mach_types.h>
36: #import <driverkit/userConfigServer.h>
37: #import "ConfigPrivate.h"
38: #import "ConfigUtils.h"
39: #import <mach/kern_return.h>
40: #import <mach/mach.h>
41: #import <mach/mach_error.h>
42: #import <kernserv/queue.h>
43: #import <driverkit/generalFuncs.h>
44:
45: IONamedValue search_keys[] = {
46: {SK_DRIVER_PORT, "Driver Port" },
47: {SK_DEV_PORT, "Device Port" },
48: {SK_SIG_PORT, "Driver Sig Port" },
49: {SK_DEVNUM, "dev_number" },
50: {SK_FID, "FID" },
51: {SK_DEV_INDEX, "deviceIndex" },
52: {0, NULL },
53: };
54:
55: IONamedValue dev_returns[] = {
56: {IO_R_SUCCESS, "Success" },
57: {IO_R_PRIVILEGE, "port/device access denied" },
58: {IO_R_NO_CHANNELS, "no DMA channels available" },
59: {IO_R_NO_SPACE, "no address space available for mapping"},
60: {IO_R_NO_DEVICE, "no more dev_numbers" },
61: {0, NULL },
62: };
63:
64: IONamedValue config_returns[] = {
65: {IO_CNF_SUCCESS, "Success" },
66: {IO_CNF_NOT_REGISTERED, "port not registered" },
67: {IO_CNF_NOT_FOUND, "slot_id/dev_type not found" },
68: {IO_CNF_BUSY, "Config Busy" },
69: {IO_CNF_REGISTERED, "driver_port already registered" },
70: {IO_CNF_RESOURCE, "System Resource Shortage" },
71: {IO_CNF_ACCESS, "Device Access Denied" },
72: {0, NULL },
73: };
74:
75: /*
76: * Get a driver_entry_t (and possibly a dev_entry_t) from driver_list
77: * matching the specified parameter. *dev_entry is only returned if the
78: * specified search_key necessitates searching through a driver_entry's
79: * dev_list.
80: * Returns NULL if specified driver_entry not found.
81: * driver_list_lock must be held on entry.
82: */
83: driver_entry_t *get_driver_entry(
84: dev_search_key_t search_key,
85: port_t search_port,
86: IODeviceNumber dev_number,
87: file_id_t fid,
88: IODeviceType device_type, // only deviceIndex is used
89: IOSlotId slot_id,
90: dev_entry_t **dev_entry_pp)
91: {
92: driver_entry_t *driver_entry;
93: boolean_t found = FALSE;
94: dev_entry_t *dev_entry;
95:
96: #if DDM_DEBUG
97: xpr_common("get_driver_port: search key %s\n",
98: IOFindNameForValue(search_key, search_keys), 2,3,4,5);
99: #endif DDM_DEBUG
100: driver_entry = (driver_entry_t *)queue_first(&driver_list);
101: while(!queue_end(&driver_list, (queue_t)driver_entry)) {
102: switch(search_key) {
103: case SK_DRIVER_PORT:
104: if(driver_entry->driver_port == search_port)
105: found = TRUE;
106: break;
107: case SK_DEV_PORT:
108: case SK_DEVNUM:
109: case SK_DEV_INDEX:
110: /*
111: * Search this driver's dev_list for this dev_port
112: * or dev_number.
113: */
114: dev_entry = get_dev_entry(
115: search_key,
116: driver_entry,
117: search_port,
118: dev_number,
119: device_type,
120: slot_id);
121: if(dev_entry != NULL) {
122: found = TRUE;
123: if(dev_entry) {
124: *dev_entry_pp = dev_entry;
125: }
126: }
127: break;
128:
129: case SK_SIG_PORT:
130: if(driver_entry->driver_sig_port == search_port)
131: found = TRUE;
132: break;
133:
134: case SK_FID:
135: if(driver_entry->executable_fid == fid)
136: found = TRUE;
137: break;
138:
139: default:
140: printf("BOGUS SEARCH KEY IN get_driver_entry()\n");
141: driver_entry = NULL;
142: found = TRUE;
143: break;
144: }
145: if(found)
146: break;
147: /*
148: * Try next entry.
149: */
150: driver_entry = (driver_entry_t *)driver_entry->link.next;
151: }
152: if(found) {
153: xpr_common("get_driver_port: found driver_entry 0x%x\n",
154: driver_entry, 2,3,4,5);
155: if(driver_entry->filename) {
156: xpr_common(" filename = %s\n",
157: IOCopyString(driver_entry->filename), 2,3,4,5);
158: }
159: }
160: else {
161: driver_entry = NULL;
162: xpr_common("get_driver_port: driver_entry not found\n",
163: 1,2,3,4,5);
164: }
165: return(driver_entry);
166: }
167:
168: /*
169: * Get a dev_entry_t from specified driver_entry's dev_list matching the
170: * specified parameter.
171: * Returns NULL if dev_entry not found.
172: * driver_list_lock must be held on entry.
173: */
174: dev_entry_t *get_dev_entry(
175: dev_search_key_t search_key,
176: driver_entry_t *driver_entry,
177: port_t search_port,
178: IODeviceNumber dev_number,
179: IODeviceType dev_type,
180: IOSlotId slot_id)
181: {
182: dev_entry_t *dev_entry;
183: boolean_t found = FALSE;
184:
185: dev_entry = (dev_entry_t *)queue_first(&driver_entry->dev_list);
186: while(!queue_end(&driver_entry->dev_list, (queue_t)dev_entry)) {
187: switch(search_key) {
188: case SK_DEV_PORT:
189: if(dev_entry->dev_port == search_port)
190: found = TRUE;
191: break;
192: case SK_DEVNUM:
193: if(dev_entry->dev_number == dev_number)
194: found = TRUE;
195: break;
196: case SK_DEV_INDEX:
197: if((dev_entry->dev_type == dev_type) &&
198: (dev_entry->slot_id == slot_id)) {
199: found = TRUE;
200: }
201: break;
202: default:
203: printf("get_dev_entry: BOGUS SEARCH_KEY\n");
204: dev_entry = NULL;
205: found = TRUE;
206: break;
207: }
208: if(found)
209: break;
210:
211: /*
212: * Try next dev_entry.
213: */
214: dev_entry = (dev_entry_t *)dev_entry->link.next;
215: }
216: if(found)
217: return(dev_entry);
218: else
219: return(NULL);
220: }
221:
222: /*
223: * Create a new driver_entry_t, add it to driver_list. Caller must hold
224: * driver_list_lock. No ports are allocated here (that's done in
225: * exec_driver().
226: */
227: driver_entry_t *create_driver_entry(
228: file_id_t fid,
229: filename_t filename)
230: {
231: driver_entry_t *driver_entry;
232:
233: xpr_common("create_driver_entry: filename %s\n",
234: IOCopyString(filename), 2,3,4,5);
235: driver_entry = malloc(sizeof(*driver_entry));
236: queue_init(&driver_entry->dev_list);
237: driver_entry->executable_fid = fid;
238: strncpy(driver_entry->filename, filename, FILENAME_SIZE);
239: driver_entry->driver_port = PORT_NULL;
240: driver_entry->driver_sig_port = PORT_NULL;
241: driver_entry->boot_requestor = PORT_NULL;
242: driver_entry->running = FALSE;
243: queue_enter(&driver_list,
244: driver_entry,
245: driver_entry_t *,
246: link);
247: return(driver_entry);
248: }
249:
250: /*
251: * Release all state associated with specified driver_entry_t. Inform kernel
252: * that all associated dev_ports are to be destroyed.
253: *
254: * This is used by driver_delete() and upon port death notification of a
255: * driver_port.
256: *
257: * driver_list_lock must be held on entry.
258: */
259: IOConfigReturn free_driver_entry(
260: driver_entry_t *driver_entry)
261: {
262: dev_entry_t *dev_entry, *dev_entry_next;
263: IOConfigReturn crtn = IO_CNF_SUCCESS;
264:
265: xpr_common("free_driver_entry driver_entry 0x%x\n",
266: driver_entry, 2,3,4,5);
267: xpr_common(" filename %s\n",
268: IOCopyString(driver_entry->filename), 2,3,4,5);
269: dev_entry = (dev_entry_t *)queue_first(&driver_entry->dev_list);
270:
271: /*
272: * First delete all of this driver's dev_ports.
273: */
274: while(!queue_end(&driver_entry->dev_list, (queue_t)dev_entry)) {
275: dev_entry_next = (dev_entry_t *)dev_entry->link.next;
276: if(free_dev_entry(dev_entry))
277: crtn = IO_CNF_ACCESS;
278: dev_entry = dev_entry_next;
279: }
280:
281: /*
282: * Now free up internal state.
283: */
284: if(driver_entry->driver_sig_port != PORT_NULL)
285: port_deallocate(task_self(), driver_entry->driver_sig_port);
286: if(driver_entry->boot_requestor != PORT_NULL)
287: port_deallocate(task_self(), driver_entry->boot_requestor);
288: queue_remove(&driver_list,
289: driver_entry,
290: driver_entry_t *,
291: link);
292: free(driver_entry);
293: return(crtn);
294: }
295:
296: /*
297: * Create a new dev_entry_t, add it to driver_entry's dev_list. This is the
298: * only place where we ask the kernel to create a dev_port.
299: */
300: dev_entry_t *create_dev_entry(
301: driver_entry_t *driver_entry,
302: IODeviceNumber dev_number,
303: IODeviceType dev_type,
304: IOSlotId slot_id)
305: {
306: dev_entry_t *dev_entry;
307: IOReturn drtn;
308:
309: xpr_common("create_dev_entry: dev_number %d dev_type 0x%x\n",
310: dev_number, dev_type, 3,4,5);
311: xpr_common(" slot_id 0x%x filename %s\n",
312: slot_id, IOCopyString(driver_entry->filename), 3,4,5);
313: dev_entry = malloc(sizeof(*dev_entry));
314: drtn = _IOCreateDevicePort(device_master_port,
315: task_self(),
316: dev_number,
317: &dev_entry->dev_port);
318: if(drtn) {
319: IOLog("Config: _IOCreateDevicePort() returned %s\n",
320: IOFindNameForValue(drtn, dev_returns), 2,3,4,5);
321: free(dev_entry);
322: return(NULL);
323: }
324: dev_entry->dev_type = dev_type;
325: dev_entry->slot_id = slot_id;
326: dev_entry->dev_number = dev_number;
327: dev_entry->driver_entry = driver_entry;
328: queue_enter(&driver_entry->dev_list,
329: dev_entry,
330: dev_entry_t *,
331: link);
332: return(dev_entry);
333: }
334:
335:
336: /*
337: * Destroy state associated with specified dev_entry.
338: */
339: IOConfigReturn free_dev_entry(
340: dev_entry_t *dev_entry)
341: {
342: IOReturn drtn;
343: IOConfigReturn crtn = IO_CNF_SUCCESS;
344:
345: xpr_common("deleting dev_entry 0x%x\n", dev_entry, 2,3,4,5);
346: xpr_common(" dev_type 0x%x slot_id 0x%x\n",
347: dev_entry->dev_type, dev_entry->slot_id, 3,4,5);
348: if(dev_entry->dev_port != PORT_NULL) {
349: drtn = _IODestroyDevicePort(device_master_port,
350: dev_entry->dev_port);
351: if(drtn) {
352: xpr_common("free_dev_entry: _IODestroyDevicePort() "
353: "returned %s\n",
354: IOFindNameForValue(drtn, dev_returns),
355: 2,3,4,5);
356: crtn = IO_CNF_ACCESS;
357: }
358: }
359:
360: /*
361: * Delete the dev_entry_t itself.
362: */
363: queue_remove(&dev_entry->driver_entry->dev_list,
364: dev_entry,
365: dev_entry_t *,
366: link);
367: free(dev_entry);
368: return(crtn);
369: }
370:
371: /*
372: * Get/release driver_list_lock as a sleep lock.
373: */
374: void get_driver_list_lock()
375: {
376: mutex_lock(driver_list_lock);
377: while(driver_list_locked)
378: condition_wait(driver_list_cond, driver_list_lock);
379: driver_list_locked = TRUE;
380: mutex_unlock(driver_list_lock);
381: }
382:
383: void release_driver_list_lock()
384: {
385: mutex_lock(driver_list_lock);
386: driver_list_locked = FALSE;
387: condition_signal(driver_list_cond);
388: mutex_unlock(driver_list_lock);
389: }
390:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.