|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50:
51: /*
52: */
53:
54: /*
55: * Code to manipulate IO permission bitmaps.
56: */
57:
58:
59:
60: #include <mach/boolean.h>
61: #include <mach/kern_return.h>
62:
63: #include <ipc/ipc_port.h>
64:
65: #include <kern/kalloc.h>
66: #include <kern/lock.h>
67: #include <kern/queue.h>
68: #include <kern/thread.h>
69: #include <kern/misc_protos.h>
70:
71:
72: #include <i386/io_port.h>
73: #include <i386/iopb.h>
74: #include <i386/seg.h>
75: #include <i386/iopb_entries.h>
76:
77: void
78: iopb_init(void)
79: {
80: }
81:
82:
83: void
84: iopb_destroy(iopb_tss_t io_tss)
85: {
86: }
87:
88: #if 0 /* Code removed until better solution comes on board */
89: /*
90: * A set of ports for an IO device.
91: */
92: struct io_port {
93: device_t device; /* Mach device */
94: queue_chain_t dev_list; /* link in device list */
95: queue_chain_t io_use_list; /* List of threads that use it */
96: io_reg_t *io_port_list; /* list of IO ports that use it */
97: /* list ends with IO_REG_NULL */
98: };
99: typedef struct io_port *io_port_t;
100:
101: /*
102: * Lookup table for device -> io_port mapping
103: * (a linked list - I don't expect too many)
104: */
105: queue_head_t device_to_io_port_list;
106:
107: /*
108: * Cross-reference:
109: * all threads that have IO ports mapped
110: * all IO ports that have threads mapped
111: */
112: struct io_use {
113: queue_chain_t psq; /* Links from port set */
114: queue_chain_t tsq; /* links from tss */
115: io_port_t ps; /* Port set */
116: iopb_tss_t ts; /* Task segment */
117: };
118: typedef struct io_use *io_use_t;
119:
120: /*
121: * Big lock for the whole mess.
122: */
123: decl_simple_lock_data(,iopb_lock)
124:
125: /* Forward */
126:
127: extern void io_bitmap_init(
128: isa_iopb bp);
129: extern void io_bitmap_set(
130: isa_iopb bp,
131: io_reg_t *bit_list);
132: extern void io_bitmap_clear(
133: isa_iopb bp,
134: io_reg_t *bit_list);
135: extern io_port_t device_to_io_port_lookup(
136: device_t device);
137: extern void io_tss_init(
138: iopb_tss_t io_tss);
139:
140:
141: /*
142: * Initialize the package.
143: */
144: void
145: iopb_init(void)
146: {
147: queue_init(&device_to_io_port_list);
148: simple_lock_init(&iopb_lock, ETAP_IO_IOPB);
149: }
150:
151: /*
152: * Initialize bitmap (set all bits to OFF == 1)
153: */
154: void
155: io_bitmap_init(
156: isa_iopb bp)
157: {
158: register unsigned char *b;
159: register int s;
160:
161: s = sizeof(isa_iopb);
162: b = bp;
163:
164: do {
165: *b++ = ~0;
166: } while (--s >= 0);
167: }
168:
169: /*
170: * Set selected bits in bitmap to ON == 0
171: */
172: void
173: io_bitmap_set(
174: isa_iopb bp,
175: io_reg_t *bit_list)
176: {
177: io_reg_t io_bit;
178:
179: while ((io_bit = *bit_list++) != IO_REG_NULL) {
180: bp[io_bit>>3] &= ~(1 << (io_bit & 0x7));
181: }
182: }
183:
184: /*
185: * Set selected bits in bitmap to OFF == 1
186: */
187: void
188: io_bitmap_clear(
189: isa_iopb bp,
190: io_reg_t *bit_list)
191: {
192: io_reg_t io_bit;
193:
194: while ((io_bit = *bit_list++) != IO_REG_NULL) {
195: bp[io_bit>>3] |= (1 << (io_bit & 0x7));
196: }
197: }
198:
199: /*
200: * Lookup an io-port set by device
201: */
202: io_port_t
203: device_to_io_port_lookup(
204: device_t device)
205: {
206: register io_port_t io_port;
207:
208: queue_iterate(&device_to_io_port_list, io_port, io_port_t, dev_list) {
209: if (io_port->device == device) {
210: return io_port;
211: }
212: }
213: return 0;
214: }
215:
216: /*
217: * [exported]
218: * Create an io_port set
219: */
220: void
221: io_port_create(
222: device_t device,
223: io_reg_t *io_port_list)
224: {
225: register io_port_t io_port, old_io_port;
226:
227: io_port = (io_port_t) kalloc(sizeof(struct io_port));
228:
229: simple_lock(&iopb_lock);
230: if (device_to_io_port_lookup(device) != 0) {
231: simple_unlock(&iopb_lock);
232: kfree((vm_offset_t) io_port, sizeof(struct io_port));
233: return;
234: }
235:
236: io_port->device = device;
237: queue_init(&io_port->io_use_list);
238: io_port->io_port_list = io_port_list;
239:
240: /*
241: * Enter in lookup list.
242: */
243: queue_enter(&device_to_io_port_list, io_port, io_port_t, dev_list);
244:
245: simple_unlock(&iopb_lock);
246: }
247:
248: /*
249: * [exported]
250: * Destroy an io port set, removing any IO mappings.
251: */
252: void
253: io_port_destroy(
254: device_t device)
255: {
256: io_port_t io_port;
257: io_use_t iu;
258:
259: simple_lock(&iopb_lock);
260: io_port = device_to_io_port_lookup(device);
261: if (io_port == 0) {
262: simple_unlock(&iopb_lock);
263: return;
264: }
265:
266: queue_iterate(&io_port->io_use_list, iu, io_use_t, psq) {
267: iopb_tss_t io_tss;
268: io_tss = iu->ts;
269: io_bitmap_clear(io_tss->bitmap, io_port->io_port_list);
270: queue_remove(&io_tss->io_port_list, iu, io_use_t, tsq);
271: }
272: queue_remove(&device_to_io_port_list, io_port, io_port_t, dev_list);
273: simple_unlock(&iopb_lock);
274:
275: while (!queue_empty(&io_port->io_use_list)) {
276: iu = (io_use_t) queue_first(&io_port->io_use_list);
277: queue_remove(&io_port->io_use_list, iu, io_use_t, psq);
278: kfree((vm_offset_t)iu, sizeof(struct io_use));
279: }
280:
281: kfree((vm_offset_t)io_port, sizeof(struct io_port));
282: }
283:
284: /*
285: * Initialize an IO TSS.
286: */
287: void
288: io_tss_init(
289: iopb_tss_t io_tss)
290: {
291: vm_offset_t addr = (vm_offset_t) io_tss;
292: vm_size_t size = (char *)&io_tss->barrier - (char *)io_tss;
293:
294: bzero((char *)&io_tss->tss, sizeof(struct i386_tss));
295: io_tss->tss.io_bit_map_offset
296: = (char *)&io_tss->bitmap - (char *)io_tss;
297: io_tss->tss.ss0 = KERNEL_DS;
298: io_bitmap_init(io_tss->bitmap);
299: io_tss->barrier = ~0;
300: queue_init(&io_tss->io_port_list);
301: addr += LINEAR_KERNEL_ADDRESS;
302: io_tss->iopb_desc[0] = ((size-1) & 0xffff)
303: | ((addr & 0xffff) << 16);
304: io_tss->iopb_desc[1] = ((addr & 0x00ff0000) >> 16)
305: | ((ACC_TSS|ACC_PL_K|ACC_P) << 8)
306: | ((size-1) & 0x000f0000)
307: | (addr & 0xff000000);
308: }
309:
310: /*
311: * [exported]
312: * Create an IOPB_TSS
313: */
314: iopb_tss_t
315: iopb_create(void)
316: {
317: register iopb_tss_t ts;
318:
319: ts = (iopb_tss_t) kalloc(sizeof (struct iopb_tss));
320: io_tss_init(ts);
321: return (ts);
322: }
323:
324: /*
325: * [exported]
326: * Destroy an IOPB_TSS
327: */
328: void
329: iopb_destroy(
330: iopb_tss_t io_tss)
331: {
332: io_use_t iu;
333: io_port_t io_port;
334:
335: simple_lock(&iopb_lock);
336:
337: queue_iterate(&io_tss->io_port_list, iu, io_use_t, tsq) {
338: io_port = iu->ps;
339: /* skip bitmap clear - entire bitmap will vanish */
340: queue_remove(&io_port->io_use_list, iu, io_use_t, psq);
341: }
342:
343: simple_unlock(&iopb_lock);
344:
345: while (!queue_empty(&io_tss->io_port_list)) {
346: iu = (io_use_t) queue_first(&io_tss->io_port_list);
347: queue_remove(&io_tss->io_port_list, iu, io_use_t, tsq);
348: kfree((vm_offset_t)iu, sizeof(struct io_use));
349: }
350:
351: kfree((vm_offset_t)io_tss, sizeof(struct iopb_tss));
352: }
353:
354: /*
355: * Add an IO mapping to a thread.
356: */
357: kern_return_t
358: i386_io_port_add(
359: thread_t thread,
360: device_t device)
361: {
362: pcb_t pcb;
363: iopb_tss_t io_tss, new_io_tss;
364: io_port_t io_port;
365: io_use_t iu, old_iu;
366:
367: if (thread == THREAD_NULL
368: || device == DEVICE_NULL)
369: return KERN_INVALID_ARGUMENT;
370:
371: pcb = thread->top_act->mact.pcb;
372:
373: new_io_tss = 0;
374: iu = (io_use_t) kalloc(sizeof(struct io_use));
375:
376: Retry:
377: simple_lock(&iopb_lock);
378:
379: /* find the io_port_t for the device */
380: io_port = device_to_io_port_lookup(device);
381: if (io_port == 0) {
382: /*
383: * Device does not have IO ports available.
384: */
385: simple_unlock(&iopb_lock);
386: if (new_io_tss)
387: kfree((vm_offset_t)new_io_tss, sizeof(struct iopb_tss));
388: kfree((vm_offset_t) iu, sizeof(struct io_use));
389: return KERN_INVALID_ARGUMENT;
390: }
391:
392: /* Have the IO port. */
393:
394: /* Make sure the thread has a TSS. */
395:
396: simple_lock(&pcb->lock);
397: io_tss = pcb->ims.io_tss;
398: if (io_tss == 0) {
399: if (new_io_tss == 0) {
400: /*
401: * Allocate an IO-tss.
402: */
403: simple_unlock(&pcb->lock);
404: simple_unlock(&iopb_lock);
405:
406: new_io_tss = (iopb_tss_t) kalloc(sizeof(struct iopb_tss));
407: io_tss_init(new_io_tss);
408:
409: goto Retry;
410: }
411: io_tss = new_io_tss;
412: pcb->ims.io_tss = io_tss;
413: new_io_tss = 0;
414: }
415:
416: /*
417: * Have io_port and io_tss.
418: * See whether device is already mapped.
419: */
420: queue_iterate(&io_tss->io_port_list, old_iu, io_use_t, tsq) {
421: if (old_iu->ps == io_port) {
422: /*
423: * Already mapped.
424: */
425: simple_unlock(&pcb->lock);
426: simple_unlock(&iopb_lock);
427:
428: kfree((vm_offset_t)iu, sizeof(struct io_use));
429: if (new_io_tss)
430: kfree((vm_offset_t)new_io_tss, sizeof(struct iopb_tss));
431: return KERN_SUCCESS;
432: }
433: }
434:
435: /*
436: * Add mapping.
437: */
438: iu->ps = io_port;
439: iu->ts = io_tss;
440: queue_enter(&io_port->io_use_list, iu, io_use_t, psq);
441: queue_enter(&io_tss->io_port_list, iu, io_use_t, tsq);
442: io_bitmap_set(io_tss->bitmap, io_port->io_port_list);
443:
444: simple_unlock(&pcb->lock);
445: simple_unlock(&iopb_lock);
446:
447: if (new_io_tss)
448: kfree((vm_offset_t)new_io_tss, sizeof(struct iopb_tss));
449: return KERN_SUCCESS;
450:
451: }
452:
453: /*
454: * Remove an IO mapping from a thread.
455: */
456: kern_return_t
457: i386_io_port_remove(
458: thread_t thread,
459: device_t device)
460: {
461: pcb_t pcb;
462: iopb_tss_t io_tss;
463: io_port_t io_port;
464: io_use_t iu;
465:
466: if (thread == THREAD_NULL
467: || device == DEVICE_NULL)
468: return KERN_INVALID_ARGUMENT;
469:
470: pcb = thread->top_act->mact.pcb;
471:
472: simple_lock(&iopb_lock);
473:
474: /* find the io_port_t for the device */
475:
476: io_port = device_to_io_port_lookup(device);
477: if (io_port == 0) {
478: /*
479: * Device does not have IO ports available.
480: */
481: simple_unlock(&iopb_lock);
482: return KERN_INVALID_ARGUMENT;
483: }
484:
485: simple_lock(&pcb->lock);
486: io_tss = pcb->ims.io_tss;
487: if (io_tss == 0) {
488: simple_unlock(&pcb->lock);
489: simple_unlock(&iopb_lock);
490: return KERN_INVALID_ARGUMENT; /* not mapped */
491: }
492:
493: /*
494: * Find the mapping.
495: */
496: queue_iterate(&io_tss->io_port_list, iu, io_use_t, tsq) {
497: if (iu->ps == io_port) {
498: /*
499: * Found mapping. Remove it.
500: */
501: io_bitmap_clear(io_tss->bitmap, io_port->io_port_list);
502:
503: queue_remove(&io_port->io_use_list, iu, io_use_t, psq);
504: queue_remove(&io_tss->io_port_list, iu, io_use_t, tsq);
505:
506: simple_unlock(&pcb->lock);
507: simple_unlock(&iopb_lock);
508:
509: kfree((vm_offset_t)iu, sizeof(struct io_use));
510:
511: return KERN_SUCCESS;
512: }
513: }
514:
515: /*
516: * No mapping.
517: */
518: return KERN_INVALID_ARGUMENT;
519: }
520:
521: /*
522: * Return the IO ports mapped into a thread.
523: */
524:
525: kern_return_t
526: i386_io_port_list(thread, list, list_count)
527: thread_t thread;
528: device_t **list;
529: unsigned int *list_count;
530: {
531: register pcb_t pcb;
532: register iopb_tss_t io_tss;
533: unsigned int count, alloc_count;
534: device_t *devices;
535: vm_size_t size_needed, size;
536: vm_offset_t addr;
537: int i;
538: boolean_t rt = FALSE; /* ### This boolean is FALSE, because there
539: * currently exists no mechanism to determine
540: * whether or not the reply port is an RT port
541: */
542:
543: if (thread == THREAD_NULL)
544: return KERN_INVALID_ARGUMENT;
545:
546: pcb = thread->top_act->mact.pcb;
547:
548: alloc_count = 16; /* a guess */
549:
550: do {
551: size_needed = alloc_count * sizeof(ipc_port_t);
552: if (size_needed <= size)
553: break;
554:
555: if (size != 0)
556: KFREE(addr, size, rt);
557:
558: assert(size_needed > 0);
559: size = size_needed;
560:
561: addr = KALLOC(size, rt);
562: if (addr == 0)
563: return KERN_RESOURCE_SHORTAGE;
564:
565: devices = (device_t *)addr;
566: count = 0;
567:
568: simple_lock(&iopb_lock);
569: simple_lock(&pcb->lock);
570: io_tss = pcb->ims.io_tss;
571: if (io_tss != 0) {
572: register io_use_t iu;
573:
574: queue_iterate(&io_tss->io_port_list, iu, io_use_t, tsq) {
575: if (++count < alloc_count) {
576: *devices = iu->ps->device;
577: device_reference(*devices);
578: devices++;
579: }
580: }
581: }
582: simple_unlock(&pcb->lock);
583: simple_unlock(&iopb_lock);
584: } while (count > alloc_count);
585:
586: if (count == 0) {
587: /*
588: * No IO ports
589: */
590: *list = 0;
591: *list_count = 0;
592:
593: if (size != 0)
594: KFREE(addr, size, rt);
595: }
596: else {
597: /*
598: * If we allocated too much, must copy.
599: */
600: size_needed = count * sizeof(ipc_port_t);
601: if (size_needed < size) {
602: vm_offset_t new_addr;
603:
604: new_addr = KALLOC(size_needed, rt);
605: if (new_addr == 0) {
606: for (i = 0; i < count; i++)
607: device_deallocate(devices[i]);
608: KFREE(addr, size, rt);
609: return KERN_RESOURCE_SHORTAGE;
610: }
611:
612: bcopy((char *)addr, (char *)new_addr, size_needed);
613: KFREE(addr, size, rt);
614: devices = (device_t *)new_addr;
615: }
616:
617: for (i = 0; i < count; i++)
618: ((ipc_port_t *)devices)[i] =
619: convert_device_to_port(devices[i]);
620: }
621: *list = devices;
622: *list_count = count;
623:
624: return KERN_SUCCESS;
625: }
626:
627: /*
628: * Check whether an IO device is mapped to a particular thread.
629: * Used to support the 'iopl' device automatic mapping.
630: */
631: boolean_t
632: iopb_check_mapping(
633: thread_t thread,
634: device_t device)
635: {
636: pcb_t pcb;
637: io_port_t io_port;
638: io_use_t iu;
639:
640: pcb = thread->top_act->mact.pcb;
641:
642: simple_lock(&iopb_lock);
643:
644: /* Find the io port for the device */
645:
646: io_port = device_to_io_port_lookup(device);
647: if (io_port == 0) {
648: simple_unlock(&iopb_lock);
649: return FALSE;
650: }
651:
652: /* Look up the mapping in the device`s mapping list. */
653:
654: queue_iterate(&io_port->io_use_list, iu, io_use_t, psq) {
655: if (iu->ts == pcb->ims.io_tss) {
656: /*
657: * Device is mapped.
658: */
659: simple_unlock(&iopb_lock);
660: return TRUE;
661: }
662: }
663: simple_unlock(&iopb_lock);
664: return FALSE;
665: }
666: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.