|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * Author: David B. Golub, Carnegie Mellon University
28: * Date: 3/89
29: */
30:
31: #include <mach/port.h>
32: #include <mach/vm_param.h>
33:
34: #include <kern/queue.h>
1.1.1.2 root 35: #include <kern/slab.h>
1.1 root 36:
37: #include <device/device_types.h>
38: #include <device/dev_hdr.h>
39: #include <device/conf.h>
40: #include <device/param.h> /* DEV_BSIZE, as default */
41:
42: #include <ipc/ipc_port.h>
43: #include <kern/ipc_kobject.h>
44:
1.1.1.2 root 45: #include <device/device_emul.h>
1.1.1.3 root 46: #include <device/ds_routines.h>
1.1 root 47:
48: /*
49: * Device structure routines: reference counting, port->device.
50: */
51:
52: /*
53: * Lookup/enter by device number.
54: */
55: #define NDEVHASH 8
56: #define DEV_NUMBER_HASH(dev) ((dev) & (NDEVHASH-1))
57: queue_head_t dev_number_hash_table[NDEVHASH];
58:
59: /*
60: * Lock for device-number to device lookup.
61: * Must be held before device-ref_count lock.
62: */
63: decl_simple_lock_data(,
64: dev_number_lock)
65:
1.1.1.2 root 66: struct kmem_cache dev_hdr_cache;
1.1 root 67:
68: /*
69: * Enter device in the number lookup table.
70: * The number table lock must be held.
71: */
72: void
73: dev_number_enter(device)
1.1.1.3 root 74: const mach_device_t device;
1.1 root 75: {
1.1.1.2 root 76: queue_t q;
1.1 root 77:
78: q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
79: queue_enter(q, device, mach_device_t, number_chain);
80: }
81:
82: /*
83: * Remove device from the device-number lookup table.
84: * The device-number table lock must be held.
85: */
86: void
87: dev_number_remove(device)
1.1.1.3 root 88: const mach_device_t device;
1.1 root 89: {
1.1.1.2 root 90: queue_t q;
1.1 root 91:
92: q = &dev_number_hash_table[DEV_NUMBER_HASH(device->dev_number)];
93: queue_remove(q, device, mach_device_t, number_chain);
94: }
95:
96: /*
97: * Lookup a device by device operations and minor number.
98: * The number table lock must be held.
99: */
100: mach_device_t
101: dev_number_lookup(ops, devnum)
1.1.1.3 root 102: const dev_ops_t ops;
1.1 root 103: int devnum;
104: {
1.1.1.2 root 105: queue_t q;
106: mach_device_t device;
1.1 root 107:
108: q = &dev_number_hash_table[DEV_NUMBER_HASH(devnum)];
109: queue_iterate(q, device, mach_device_t, number_chain) {
110: if (device->dev_ops == ops && device->dev_number == devnum) {
111: return (device);
112: }
113: }
114: return (MACH_DEVICE_NULL);
115: }
116:
117: /*
118: * Look up a device by name, and create the device structure
119: * if it does not exist. Enter it in the dev_number lookup
120: * table.
121: */
122: mach_device_t
1.1.1.3 root 123: device_lookup(char *name)
1.1 root 124: {
125: dev_ops_t dev_ops;
126: int dev_minor;
1.1.1.2 root 127: mach_device_t device;
128: mach_device_t new_device;
1.1 root 129:
130: /*
131: * Get the device and unit number from the name.
132: */
133: if (!dev_name_lookup(name, &dev_ops, &dev_minor))
134: return (MACH_DEVICE_NULL);
135:
136: /*
137: * Look up the device in the hash table. If it is
138: * not there, enter it.
139: */
140: new_device = MACH_DEVICE_NULL;
141: simple_lock(&dev_number_lock);
142: while ((device = dev_number_lookup(dev_ops, dev_minor))
143: == MACH_DEVICE_NULL) {
144: /*
145: * Must unlock to allocate the structure. If
146: * the structure has appeared after we have allocated,
147: * release the new structure.
148: */
149: if (new_device != MACH_DEVICE_NULL)
150: break; /* allocated */
151:
152: simple_unlock(&dev_number_lock);
153:
1.1.1.2 root 154: new_device = (mach_device_t) kmem_cache_alloc(&dev_hdr_cache);
1.1 root 155: simple_lock_init(&new_device->ref_lock);
156: new_device->ref_count = 1;
157: simple_lock_init(&new_device->lock);
158: new_device->state = DEV_STATE_INIT;
159: new_device->flag = 0;
160: new_device->open_count = 0;
161: new_device->io_in_progress = 0;
162: new_device->io_wait = FALSE;
163: new_device->port = IP_NULL;
164: new_device->dev_ops = dev_ops;
165: new_device->dev_number = dev_minor;
166: new_device->bsize = DEV_BSIZE; /* change later */
167:
168: simple_lock(&dev_number_lock);
169: }
170:
171: if (device == MACH_DEVICE_NULL) {
172: /*
173: * No existing device structure. Insert the
174: * new one.
175: */
176: assert(new_device != MACH_DEVICE_NULL);
177: device = new_device;
178:
179: dev_number_enter(device);
180: simple_unlock(&dev_number_lock);
181: }
182: else {
183: /*
184: * Have existing device.
185: */
186: mach_device_reference(device);
187: simple_unlock(&dev_number_lock);
188:
189: if (new_device != MACH_DEVICE_NULL)
1.1.1.2 root 190: kmem_cache_free(&dev_hdr_cache, (vm_offset_t)new_device);
1.1 root 191: }
192:
193: return (device);
194: }
195:
196: /*
197: * Add a reference to the device.
198: */
199: void
1.1.1.3 root 200: mach_device_reference(mach_device_t device)
1.1 root 201: {
202: simple_lock(&device->ref_lock);
203: device->ref_count++;
204: simple_unlock(&device->ref_lock);
205: }
206:
207: /*
208: * Remove a reference to the device, and deallocate the
209: * structure if no references are left.
210: */
211: void
1.1.1.3 root 212: mach_device_deallocate(mach_device_t device)
1.1 root 213: {
214: simple_lock(&device->ref_lock);
215: if (--device->ref_count > 0) {
216: simple_unlock(&device->ref_lock);
217: return;
218: }
219: device->ref_count = 1;
220: simple_unlock(&device->ref_lock);
221:
222: simple_lock(&dev_number_lock);
223: simple_lock(&device->ref_lock);
224: if (--device->ref_count > 0) {
225: simple_unlock(&device->ref_lock);
226: simple_unlock(&dev_number_lock);
227: return;
228: }
229:
230: dev_number_remove(device);
231: simple_unlock(&device->ref_lock);
232: simple_unlock(&dev_number_lock);
233:
1.1.1.2 root 234: kmem_cache_free(&dev_hdr_cache, (vm_offset_t)device);
1.1 root 235: }
236:
237: /*
238:
239: */
240: /*
241: * port-to-device lookup routines.
242: */
243:
244: /*
245: * Enter a port-to-device mapping.
246: */
247: void
1.1.1.3 root 248: dev_port_enter(mach_device_t device)
1.1 root 249: {
250: mach_device_reference(device);
1.1.1.2 root 251:
1.1 root 252: ipc_kobject_set(device->port,
253: (ipc_kobject_t) &device->dev, IKOT_DEVICE);
254: device->dev.emul_data = device;
255: {
256: extern struct device_emulation_ops mach_device_emulation_ops;
257:
258: device->dev.emul_ops = &mach_device_emulation_ops;
259: }
260: }
261:
262: /*
263: * Remove a port-to-device mapping.
264: */
265: void
1.1.1.3 root 266: dev_port_remove(mach_device_t device)
1.1 root 267: {
268: ipc_kobject_set(device->port, IKO_NULL, IKOT_NONE);
269: mach_device_deallocate(device);
270: }
271:
272: /*
273: * Lookup a device by its port.
274: * Doesn't consume the naked send right; produces a device reference.
275: */
276: device_t
1.1.1.3 root 277: dev_port_lookup(ipc_port_t port)
1.1 root 278: {
1.1.1.2 root 279: device_t device;
1.1 root 280:
281: if (!IP_VALID(port))
282: return (DEVICE_NULL);
283:
284: ip_lock(port);
285: if (ip_active(port) && (ip_kotype(port) == IKOT_DEVICE)) {
286: device = (device_t) port->ip_kobject;
287: if (device->emul_ops->reference)
288: (*device->emul_ops->reference)(device->emul_data);
289: }
290: else
291: device = DEVICE_NULL;
292:
293: ip_unlock(port);
294: return (device);
295: }
296:
297: /*
298: * Get the port for a device.
299: * Consumes a device reference; produces a naked send right.
300: */
301: ipc_port_t
302: convert_device_to_port(device)
1.1.1.3 root 303: const device_t device;
1.1 root 304: {
305: if (device == DEVICE_NULL)
306: return IP_NULL;
307:
308: return (*device->emul_ops->dev_to_port) (device->emul_data);
309: }
310:
311: /*
312: * Call a supplied routine on each device, passing it
313: * the port as an argument. If the routine returns TRUE,
314: * stop the search and return TRUE. If none returns TRUE,
315: * return FALSE.
316: */
317: boolean_t
1.1.1.3 root 318: dev_map(
319: boolean_t (*routine)(),
320: mach_port_t port)
1.1 root 321: {
1.1.1.2 root 322: int i;
323: queue_t q;
324: mach_device_t dev, prev_dev;
1.1 root 325:
326: for (i = 0, q = &dev_number_hash_table[0];
327: i < NDEVHASH;
328: i++, q++) {
329: prev_dev = MACH_DEVICE_NULL;
330: simple_lock(&dev_number_lock);
331: queue_iterate(q, dev, mach_device_t, number_chain) {
332: mach_device_reference(dev);
333: simple_unlock(&dev_number_lock);
334: if (prev_dev != MACH_DEVICE_NULL)
335: mach_device_deallocate(prev_dev);
336:
337: if ((*routine)(dev, port)) {
338: /*
339: * Done
340: */
341: mach_device_deallocate(dev);
342: return (TRUE);
343: }
344:
345: simple_lock(&dev_number_lock);
346: prev_dev = dev;
347: }
348: simple_unlock(&dev_number_lock);
349: if (prev_dev != MACH_DEVICE_NULL)
350: mach_device_deallocate(prev_dev);
351: }
352: return (FALSE);
353: }
354:
355: /*
356: * Initialization
357: */
358: void
1.1.1.3 root 359: dev_lookup_init(void)
1.1 root 360: {
1.1.1.2 root 361: int i;
1.1 root 362:
363: simple_lock_init(&dev_number_lock);
364:
365: for (i = 0; i < NDEVHASH; i++)
366: queue_init(&dev_number_hash_table[i]);
367:
1.1.1.2 root 368: kmem_cache_init(&dev_hdr_cache, "mach_device",
1.1.1.4 ! root 369: sizeof(struct mach_device), 0, NULL, 0);
1.1 root 370: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.