File:  [Apple Darwin 0.x] / driverkit / Config / ConfigUtils.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:37:51 2018 UTC (8 years, 3 months ago) by root
Branches: MAIN, Apple
CVS tags: HEAD, Darwin03, Darwin02
Darwin 0.2 Driver Kit

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.1 (the "License").  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*	Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
 *
 * ConfigUtils.c - common utility functions for Config server.
 *
 * HISTORY
 * 12-Apr-91    Doug Mitchell at NeXT
 *      Created.
 */

#import <bsd/sys/types.h>
#import <bsd/libc.h>
#import <mach/mach_types.h>
#import <driverkit/userConfigServer.h>
#import "ConfigPrivate.h"
#import "ConfigUtils.h"
#import <mach/kern_return.h>
#import <mach/mach.h>
#import <mach/mach_error.h>
#import <kernserv/queue.h>
#import <driverkit/generalFuncs.h>

IONamedValue search_keys[] = {
	{SK_DRIVER_PORT,	"Driver Port"		},
	{SK_DEV_PORT,		"Device Port"		},
	{SK_SIG_PORT,		"Driver Sig Port"	},
	{SK_DEVNUM,		"dev_number"		},	
	{SK_FID,		"FID"			},	
	{SK_DEV_INDEX,		"deviceIndex"		},	
	{0,			NULL			},
};

IONamedValue dev_returns[] = {
	{IO_R_SUCCESS,		"Success"				},
	{IO_R_PRIVILEGE,	"port/device access denied"		},
	{IO_R_NO_CHANNELS,	"no DMA channels available"		},
	{IO_R_NO_SPACE,		"no address space available for mapping"},
	{IO_R_NO_DEVICE,	"no more dev_numbers"			},
	{0,			NULL					},
};

IONamedValue config_returns[] = {
	{IO_CNF_SUCCESS,	"Success"				},
	{IO_CNF_NOT_REGISTERED,	"port not registered"			},
	{IO_CNF_NOT_FOUND,	"slot_id/dev_type not found"		},
	{IO_CNF_BUSY,		"Config Busy"				},
	{IO_CNF_REGISTERED,	"driver_port already registered"	},
	{IO_CNF_RESOURCE,	"System Resource Shortage"		},
	{IO_CNF_ACCESS,		"Device Access Denied"			},
	{0,			NULL					},
};

/*
 * Get a driver_entry_t (and possibly a dev_entry_t) from driver_list 
 * matching the specified parameter. *dev_entry is only returned if the
 * specified search_key necessitates searching through a driver_entry's
 * dev_list.
 * Returns NULL if specified driver_entry not found.
 * driver_list_lock must be held on entry.
 */
driver_entry_t *get_driver_entry(
	dev_search_key_t search_key,
	port_t search_port,
	IODeviceNumber dev_number,
	file_id_t fid,
	IODeviceType device_type,	// only deviceIndex is used
	IOSlotId slot_id,
	dev_entry_t **dev_entry_pp)
{
	driver_entry_t *driver_entry;
	boolean_t found = FALSE;
	dev_entry_t *dev_entry;
	
#if	DDM_DEBUG
	xpr_common("get_driver_port: search key %s\n", 
		IOFindNameForValue(search_key, search_keys), 2,3,4,5);
#endif	DDM_DEBUG
	driver_entry = (driver_entry_t *)queue_first(&driver_list);
	while(!queue_end(&driver_list, (queue_t)driver_entry)) {
		switch(search_key) {
		    case SK_DRIVER_PORT:
			if(driver_entry->driver_port == search_port) 
		    		found = TRUE;
			break;
		    case SK_DEV_PORT:
		    case SK_DEVNUM:
		    case SK_DEV_INDEX:
			/*
			 * Search this driver's dev_list for this dev_port
			 * or dev_number.
			 */
			dev_entry = get_dev_entry(
				search_key,
				driver_entry,
				search_port,
				dev_number,
				device_type,
				slot_id);
			if(dev_entry != NULL) {
				found = TRUE;
				if(dev_entry) {
					*dev_entry_pp = dev_entry;
				}
			}
			break;
			
		    case SK_SIG_PORT:
			if(driver_entry->driver_sig_port == search_port)
				found = TRUE;
			break;
			
		    case SK_FID:
			if(driver_entry->executable_fid == fid)
				found = TRUE;
			break;
			
		    default:
		    	printf("BOGUS SEARCH KEY IN get_driver_entry()\n");
			driver_entry = NULL;
			found = TRUE;
			break;
		}
		if(found)
			break;
		/*
		 * Try next entry.
		 */
		driver_entry = (driver_entry_t *)driver_entry->link.next;
	}
	if(found) {
		xpr_common("get_driver_port: found driver_entry 0x%x\n", 
			driver_entry, 2,3,4,5);
		if(driver_entry->filename) {
			xpr_common("    filename = %s\n", 
				IOCopyString(driver_entry->filename), 2,3,4,5);
		}
	}
	else {
		driver_entry = NULL;
		xpr_common("get_driver_port: driver_entry not found\n", 
			1,2,3,4,5);
	}
	return(driver_entry);
}

/*
 * Get a dev_entry_t from specified driver_entry's dev_list matching the
 * specified parameter.
 * Returns NULL if dev_entry not found.
 * driver_list_lock must be held on entry.
 */
dev_entry_t *get_dev_entry(
	dev_search_key_t search_key,
	driver_entry_t *driver_entry,
	port_t search_port,
	IODeviceNumber dev_number,
	IODeviceType dev_type,
	IOSlotId slot_id)
{
	dev_entry_t *dev_entry;
	boolean_t found = FALSE;
	
	dev_entry = (dev_entry_t *)queue_first(&driver_entry->dev_list);
	while(!queue_end(&driver_entry->dev_list, (queue_t)dev_entry)) {
		switch(search_key) {
		    case SK_DEV_PORT:
			if(dev_entry->dev_port == search_port) 
				found = TRUE;
			break;
		    case SK_DEVNUM:
			if(dev_entry->dev_number == dev_number)
				found = TRUE;
			break;
		    case SK_DEV_INDEX:
			if((dev_entry->dev_type == dev_type) &&
			   (dev_entry->slot_id == slot_id)) {
				found = TRUE;	
			}
			break;
		    default:
			printf("get_dev_entry: BOGUS SEARCH_KEY\n");
			dev_entry = NULL;
			found = TRUE;
			break;
		}
		if(found)
			break;
			
		/*
		 * Try next dev_entry.
		 */
		dev_entry = (dev_entry_t *)dev_entry->link.next;
	}
	if(found)
		return(dev_entry);
	else
		return(NULL);
}

/*
 * Create a new driver_entry_t, add it to driver_list. Caller must hold
 * driver_list_lock. No ports are allocated here (that's done in 
 * exec_driver().
 */
driver_entry_t *create_driver_entry(
	file_id_t fid,
	filename_t filename)
{
	driver_entry_t *driver_entry;
	
	xpr_common("create_driver_entry: filename %s\n", 
		IOCopyString(filename), 2,3,4,5);
	driver_entry = malloc(sizeof(*driver_entry));
	queue_init(&driver_entry->dev_list);
	driver_entry->executable_fid = fid;
	strncpy(driver_entry->filename, filename, FILENAME_SIZE);
	driver_entry->driver_port = PORT_NULL;
	driver_entry->driver_sig_port = PORT_NULL;
	driver_entry->boot_requestor = PORT_NULL;
	driver_entry->running = FALSE;
	queue_enter(&driver_list,
		driver_entry,
		driver_entry_t *,
		link);
	return(driver_entry);
}

/*
 * Release all state associated with specified driver_entry_t. Inform kernel 
 * that all associated dev_ports are to be destroyed.
 *
 * This is used by driver_delete() and upon port death notification of a
 * driver_port.
 *
 * driver_list_lock must be held on entry.
 */
IOConfigReturn free_driver_entry(
	driver_entry_t *driver_entry)
{
	dev_entry_t *dev_entry, *dev_entry_next;
	IOConfigReturn crtn = IO_CNF_SUCCESS;
	
	xpr_common("free_driver_entry driver_entry 0x%x\n", 
		driver_entry, 2,3,4,5);
	xpr_common("  filename %s\n", 
		IOCopyString(driver_entry->filename), 2,3,4,5);
	dev_entry = (dev_entry_t *)queue_first(&driver_entry->dev_list);
	
	/*
	 * First delete all of this driver's dev_ports.
	 */
	while(!queue_end(&driver_entry->dev_list, (queue_t)dev_entry)) {
		dev_entry_next = (dev_entry_t *)dev_entry->link.next;
		if(free_dev_entry(dev_entry))
			crtn = IO_CNF_ACCESS;
		dev_entry = dev_entry_next;
	}

	/*
	 * Now free up internal state.
	 */
	if(driver_entry->driver_sig_port != PORT_NULL)
		port_deallocate(task_self(), driver_entry->driver_sig_port);
	if(driver_entry->boot_requestor != PORT_NULL)
		port_deallocate(task_self(), driver_entry->boot_requestor);
	queue_remove(&driver_list,
		driver_entry,
		driver_entry_t *,
		link);
	free(driver_entry);
	return(crtn);
}

/*
 * Create a new dev_entry_t, add it to driver_entry's dev_list. This is the 
 * only place where we ask the kernel to create a dev_port.
 */
dev_entry_t *create_dev_entry(
	driver_entry_t *driver_entry, 
	IODeviceNumber dev_number,
	IODeviceType dev_type, 
	IOSlotId slot_id)
{	
	dev_entry_t *dev_entry;
	IOReturn drtn;
	
	xpr_common("create_dev_entry: dev_number %d dev_type 0x%x\n",
		dev_number, dev_type, 3,4,5);
	xpr_common("   slot_id 0x%x filename %s\n", 
		slot_id, IOCopyString(driver_entry->filename), 3,4,5);
	dev_entry = malloc(sizeof(*dev_entry));
	drtn = _IOCreateDevicePort(device_master_port,
		task_self(),
		dev_number,
		&dev_entry->dev_port);
	if(drtn) {
		IOLog("Config: _IOCreateDevicePort() returned %s\n",
			IOFindNameForValue(drtn, dev_returns), 2,3,4,5);
		free(dev_entry);
		return(NULL);
	}
	dev_entry->dev_type = dev_type;
	dev_entry->slot_id = slot_id;
	dev_entry->dev_number = dev_number;
	dev_entry->driver_entry = driver_entry;
	queue_enter(&driver_entry->dev_list,
		dev_entry,
		dev_entry_t *,
		link);
	return(dev_entry);
}


/*
 * Destroy state associated with specified dev_entry.
 */
IOConfigReturn free_dev_entry(
	dev_entry_t *dev_entry)
{
	IOReturn drtn;
	IOConfigReturn crtn = IO_CNF_SUCCESS;
	
	xpr_common("deleting dev_entry 0x%x\n", dev_entry, 2,3,4,5);
	xpr_common("   dev_type 0x%x  slot_id 0x%x\n", 
		dev_entry->dev_type, dev_entry->slot_id, 3,4,5);
	if(dev_entry->dev_port != PORT_NULL) {
		drtn = _IODestroyDevicePort(device_master_port,
			dev_entry->dev_port);
		if(drtn) {
			xpr_common("free_dev_entry: _IODestroyDevicePort() "
				"returned %s\n", 
				IOFindNameForValue(drtn, dev_returns),
				2,3,4,5);
			crtn = IO_CNF_ACCESS;
		}
	}
		
	/*
	 * Delete the dev_entry_t itself.
	 */
	queue_remove(&dev_entry->driver_entry->dev_list,
		dev_entry,
		dev_entry_t *,
		link);
	free(dev_entry);
	return(crtn);
}

/*
 * Get/release driver_list_lock as a sleep lock.
 */
void get_driver_list_lock()
{
	mutex_lock(driver_list_lock);
	while(driver_list_locked)
		condition_wait(driver_list_cond, driver_list_lock);
	driver_list_locked = TRUE;
	mutex_unlock(driver_list_lock);
}

void release_driver_list_lock()
{
	mutex_lock(driver_list_lock);
	driver_list_locked = FALSE;
	condition_signal(driver_list_cond);
	mutex_unlock(driver_list_lock);
}


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.