|
|
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.