File:  [Apple Darwin 0.x] / driverkit / libDriver / User / volDriver.m
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:37:51 2018 UTC (8 years, 2 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. 
 *
 * volDriver.m - user-level "emulation" of vol driver. 
 *
 * a signal 14 delivered to this executable results in a panel response
 * action, which is interpreted as a "disk not available" by volCheck.
 *
 * a signal 1 delivered causes the same action as the death of the 
 * WorkSpace - all pending panel requests are ack'd.
 *
 * HISTORY
 * 09-May-91    Doug Mitchell at NeXT
 *      Created.
 */

#undef	DRIVER_PRIVATE
#define DRIVER_PRIVATE

#import <objc/objc.h>
#import <bsd/sys/types.h>
#import <mach/cthreads.h>	/* FIXME - for ASSERT for MD includes...*/
#import <kernserv/queue.h>
#import <driverkit/generalFuncs.h>
#import <bsd/sys/signal.h>
#import <driverkit/Device_ddm.h>
#import <machkit/NXLock.h>
#import <driverkit/volCheck.h>
#import "volCheckPrivate.h"
#import "volDriver.h"

/*
 * Struct for maintaining state of panel requests.
 */
typedef struct {
        queue_chain_t           link;
        int                     tag;
        vpt_func                fnc;            /* to be called upon receipt of
                                                 * vol_panel_resp message */    
        void                    *param;
} vol_panel_entry_t;

/*
 * static data.
 */
static int volDriverTag;
static queue_head_t volDriverPanelQ;
static id volDriverLock;		// NXLock - protects above

/*
 * Static function prototypes.
 */
static char *diskTypeToString(int diskType);
static char *volStateToString(int volState);
static vol_panel_entry_t *vol_panel_get_entry(int tag);
static void volDriverSig(int foo);
static void volDriverWSDeath(int foo);

/*
 * One-time only init.
 */
void volDriverInit()
{
	queue_init(&volDriverPanelQ);
	volDriverLock = [NXLock new];
	signal(SIGALRM, volDriverSig);
	signal(SIGHUP, volDriverWSDeath);
}

kern_return_t vol_notify_dev(dev_t block_dev, 
	dev_t raw_dev,
	const char *form_type,
   	int vol_state,				/* IND_VS_LABEL, etc. */
	const char *dev_str,
	int flags)
{
	
	IOLog("Disk Insertion: block_dev 0x%x vol_state %s\n",
		block_dev, volStateToString(vol_state));
	return(KERN_SUCCESS);
}

/*
 * Cancel notification message. Called on 'mount' of device.
 */
void vol_notify_cancel(dev_t device)
{
	IOLog("Cancelling Alert for dev 0x%x\n", device);
}

kern_return_t vol_panel_request(vpt_func fnc,
	int panel_type,				/* PR_PT_DISK_NUM, etc. */
	int response_type,			/* PR_RT_ACK, atc. */
	int p1,
	int p2,
	int p3,
	int p4,
	char *string1,
	char *string2,
	void *param,
	int *tag)				/* RETURNED */
{
	char *disk_string = diskTypeToString(p2);
	vol_panel_entry_t *vpe;
	
	[volDriverLock lock];
	
	/*
	 * Record this panel in case of ack or cancel.
	 */
	vpe = IOMalloc(sizeof(*vpe));
	vpe->tag = volDriverTag;
	vpe->fnc = fnc;
	vpe->param = param;
	queue_enter(&volDriverPanelQ,
		vpe,
		vol_panel_entry_t *,
		link);
		
	switch(panel_type) {
	    case PR_PT_DISK_NUM:
		IOLog("Please Insert %s Disk %d in Drive %d (tag %d)\n", 
			disk_string, p1, p3, volDriverTag);
		break;
	    case PR_PT_DISK_LABEL:
		IOLog("Please Insert %s Disk \'%s\' in Drive %d (tag %d)\n", 
			disk_string, string1, p3);
		break;
	    case PR_PT_DISK_NUM_W:
		IOLog("Wrong Disk: Please Insert %s Disk %d in Drive "
			"%d (tag %d)\n", disk_string, p1, p3);
		break;
	    case PR_PT_DISK_LABEL_W:
		IOLog("Wrong Disk: Please Insert %s Disk \'%s\' in "
			"Drive %d (tag %d)\n", disk_string, string1, p3);
		break;
	    case PR_PT_SWAPDEV_FULL:
		IOLog("***Swap Device Full***\n");
		break;
	    case PR_PT_FILESYS_FULL:
		IOLog("***File System %s Full***\n", string1);
		break;
	    case PR_RT_EJECT_REQ:
		IOLog("Please Eject %s Disk %d (tag %d)\n", disk_string, p3);
		break;
	    default:
		/* FIXME: what do we do here? */
		IOLog("vol_panel_request: bogus panel_type (%d)\n",
			panel_type);
		break;
	}
	*tag = volDriverTag++;
	[volDriverLock unlock];
	
	return(KERN_SUCCESS);
}

kern_return_t vol_panel_disk_num(vpt_func fnc,
	int volume_num,
	int drive_type,				/* PR_DRIVE_FLOPPY, etc. */
	int drive_num,
	void *param,
	boolean_t wrong_disk,
	int *tag)				/* RETURNED */
{
        return(vol_panel_request(fnc,
                wrong_disk ? PR_PT_DISK_NUM_W : PR_PT_DISK_NUM,
                PR_RT_ACK,
                volume_num,
                drive_type,
                drive_num,
                0,
                "",
                "",
                param,
                tag));  

}
kern_return_t vol_panel_disk_label(vpt_func fnc,
	char *label,
	int drive_type,				/* PR_DRIVE_FLOPPY, etc. */
	int drive_num,
	void *param,
	boolean_t wrong_disk,
	int *tag)				/* RETURNED */
{
	return(vol_panel_request(fnc,
                wrong_disk ? PR_PT_DISK_LABEL_W : PR_PT_DISK_LABEL,
                PR_RT_ACK,
                0,
                drive_type,
                drive_num,
                0,
                label,
                "",
                param,
                tag));
}

/*
 * Remove an alert panel. Called upon detection of desired disk after putting
 * up an alert panel.
 */
kern_return_t vol_panel_remove(int tag)
{
	vol_panel_entry_t *vpe;

	[volDriverLock lock];
	vpe = vol_panel_get_entry(tag);
	if(vpe == NULL) {
		IOLog("vol_panel_remove: Nonexistent panel (tag %d)\n",
			tag);
	}
	else {
		IOLog("volDriver: removing panel for tag %d\n", tag);
		IOFree(vpe, sizeof(*vpe));
	}
	[volDriverLock unlock];
	return(KERN_SUCCESS);
}

/*
 * Private functions.
 */
 
static char *diskTypeToString(int diskType)
{
	switch(diskType) {
	    case PR_DRIVE_FLOPPY:
		return("Floppy");
	    case PR_DRIVE_OPTICAL:
		return("Optical");
	    case PR_DRIVE_SCSI:
		return("SCSI");
	    default: 
		return("");
	}
}

static char *volStateToString(int volState)
{
	switch(volState) {
	    case IND_VS_LABEL:
	    	return("IND_VS_LABEL");
	    case IND_VS_FORMATTED:
	    	return("IND_VS_FORMATTED");
	    case IND_VS_UNFORMATTED:
	    	return("IND_VS_UNFORMATTED");
	    default:
	    	return("Unknown volState");
	}
}

static vol_panel_entry_t *vol_panel_get_entry(int tag) {

        /*
         * get and remove vol_panel_entry associated with 'tag' from 
	 * volDriverPanelQ. Returns NULL if entry not found.
	 * volDriverLock should be held on entry.
         */
	 
        vol_panel_entry_t *vpe;

        vpe = (vol_panel_entry_t *)queue_first(&volDriverPanelQ);
        while(!queue_end(&volDriverPanelQ, (queue_entry_t)vpe)) {
                if(vpe->tag == tag) {
                        /*
                         * Found it. 
                         */
                        queue_remove(&volDriverPanelQ,
                                vpe,
                                vol_panel_entry_t *,
                                link);
                        return(vpe);
                }
                vpe = (vol_panel_entry_t *)vpe->link.next;
        }
        /*
         * Not found. 
         */
        return(NULL);
}

/*
 * Signal catcher to emulate WS's panel response message. All we can do
 * is cancel the last request which went out.
 */
static void volDriverSig(int foo)
{
	vol_panel_entry_t *vpe;
	
	[volDriverLock lock];
	vpe = vol_panel_get_entry(volDriverTag - 1);
	if(vpe == NULL) {
		IOLog("volDriverSig: Couldn't find entry for tag %d\n",
			volDriverTag - 1);
		goto done;
	}
	/*
	 * Perform callout if necessary, then dispose of entry.
	 */
	xpr_vc("volDriverSig: doing VOL_PANEL_RESP callout\n", 1,2,3,4,5);
	if(vpe->fnc) {
		(*vpe->fnc)(vpe->param, 
			vpe->tag, 
			0);		// 'value'
	}
	IOFree(vpe, sizeof(*vpe));
done:
	[volDriverLock unlock];
	return;
}

/*
 * Signal catcher to abort all pending panels. Emulates death of workspace.
 */
static void volDriverWSDeath(int foo)
{
	vol_panel_entry_t *vpe;

	/*
	 * Ack and dispose of every vol_panel_entry in volDriverPanelQ.
	 */
	xpr_vc("volDriverWSDeath\n", 1,2,3,4,5);
	while(!queue_empty(&volDriverPanelQ)) {
		vpe = (vol_panel_entry_t *)queue_first(&volDriverPanelQ);
		queue_remove(&volDriverPanelQ,
			vpe,
			vol_panel_entry_t *,
			link);
		xpr_vc("volDriverWSDeath: doing VOL_PANEL_RESP "
			"callout\n", 1,2,3,4,5);
		if(vpe->fnc) {
			(*vpe->fnc)(vpe->param, 
				vpe->tag, 
				0);        /* as in "disk not 
					    * available" */
		}
		IOFree(vpe, sizeof(*vpe));
	}
}

static int manual_poll;

int vol_check_manual_poll()
{
	if(manual_poll) {
		manual_poll = 0;
		return(1);
	}
	else {
		return(0);
	}
}

/*
 * Internal version of ioctl(DKIOCCHECKINSERT).
 */
void vol_check_set_poll()
{
	manual_poll = 1;
}

unix.superglobalmegacorp.com

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