h20154
s 00016/00011/00272
d D 3.2 85/06/04 14:56:09 dock 2 1
c changed include files
e
s 00283/00000/00000
d D 3.1 84/11/13 16:28:33 dan 1 0
c date and time created 84/11/13 16:28:33 by dan
e
u
U
t
T
I 1
D 2
/*  pcthandlr.c -- VIOS Physical Device Control request handler
 *  copyright (c) American Information Systems Corporation
 *	Daniel Steinberg
 *	November, 1984
E 2
I 2

/*
 * %M%: version %I% of %H%
E 2
 *
I 2
 *  pcthandlr.c -- VIOS Physical Device Control request handler
 *  copyright (c) American Information Systems Corporation
 *	Daniel Steinberg	November, 1984
E 2
 */
I 2
#ifdef SCCS
static char *sccsid = "%W%";
#endif
E 2

D 2
#include "viosconf.h"
#include "iopacket.h"
#include "devfuncs.h"
#include "poolfuncs.h"
#include "handlers.h"
#include "viocmds.h"
#include "viostatus.h"
E 2
I 2
#include "vinc/viosconf.h"
#include "vinc/iopacket.h"
#include "vinc/devfuncs.h"
#include "vinc/poolfuncs.h"
#include "vinc/handlers.h"
#include "vinc/viocmds.h"
#include "vinc/viostatus.h"
E 2


    PKT_STATE			/* Throws: V_NO_DEVICE / V_ILL_FUNCTION */
pctrl_handler (pkt)
    register PKT_PTR pkt;

/* pctrl_handler (pkt) -- Do initial processing of VIOS Control Requests
 *
 *	in:	pkt		I/O Packet to process
 *	return:	(PKT_STATE)	next I/O packet state
 *	thrown:	V_NO_DEVICE	device spec supplied on CREATEPD function
 *				or missing if required
 *		V_ILL_FUNCTION	illegal physical device control function
 *
 *	Dispatch i/o packet to appropriate Physical Device Control handler.
 *	Make sure that there is (or isn't) a target device if required (or not).
 */
{
    register IO_PACKET *pk;	/* dereferenced ptr */
    PDD_PTR dev;

    pk = *pkt;

    switch (Stnum(pk))
	{
    case 0:
	switch (Fcode(pk))
	    {
	case CREATEPD:
	    if (PDevice(pk) NE NULL)  throw(V_NO_DEVICE);
	    Handler(pk) = pcre_handler;		/* Create a PDD */
	    return(VIO_RUN_STATE);		/* continue with new handler */

	case REMOVEPD:
	    Handler(pk) = prem_handler;		/* Remove a PDD */
	    break;

	default:
	    throw(V_ILL_FUNCTION);

	    } /* switch function-code */

	if (PDevice(pk) EQ NULL)  throw(V_NO_DEVICE);	/* must be a PDD */

	return(VIO_RUN_STATE);		/* continue with new handler */

    default:

#ifdef DEBUG3   /*************************************************************/
	error ("Bad stnum in pkt @%x (pctrl_handler)", pk);
#endif /* DEBUG3 *************************************************************/

	} /* switch Stnum */
}

    PKT_STATE					/* Throws: various errors */
pcre_handler (pkt)
    PKT_PTR pkt;

/* pcre_handler (pkt) -- Process Create Physical Device Requests
 *
 *	in:	pkt		I/O Packet to process
 *	return:	(PKT_STATE)	next I/O packet state
 *	thrown:	V_BAD_PARAMS	Bad parameter in request
 *		V_ILL_MODIFIER	Bad modifier in request function
 *		V_DUP_NAME	Existing Physical Device cannot be shared
 *		V_SUCCESS	Packet successfully processed
 *
 *	Process VIOS requests to create a Physical Device.
 *	Process as follows:
 *		1) If invalid or excessively long device name specification,
 *		   or if Param1 is a non-existent class,
 *			throw V_BAD_PARAMS.
 *		2) If request originated from an O.S., set the REM_ON_DEA bit
 *		   to ensure that the device is removed when no longer needed.
 *		3) If SHR_WRITE, set SHR_READ and WRITE_ACCESS modifier bits.
 *		4) If invalid or inconsistent function modifier,
 *			throw V_ILL_MODIFIER.
 *		5) If the device name already exists, connect to it if the
 *		   proper shareable/writeable attributes are set.  If the
 *		   request doesnt allow sharing (SHR_READ or LOOKUP_PD not set),
 *			throw V_DUP_NAME.
 *		6) If the device exists but does not allow the appropriate
 *		   shared and/or write access,
 *			throw V_DEV_BUSY.
 *		7) If the device exists and the above tests pass, allow a new
 *		   physical device to be created with a duplicate name.
 *		8) If the device does not already exist, then call imp_search()
 *		   (in ctrlsubs.c) to locate the appropriate implementation
 *		   module descriptor.  Then, allocate a PDD and set the
 *		   appropriate attributes.  (If allocation failure, requeue.)
 *		9) Set packet to release PDD on completion, in case of error, by
 *		   setting the address of the allocated PDD in Auxparam.
 *		10)Call the device dispatcher with the PDCREATE code to perform
 *		   the actual device connection.  The device handler must set
 *		   Statauxcode in the i/o packet and verify that Devclass in the
 *		   PDD is set to the correct device class.
 *		11)If the device handler returns DONE_STATE, clear Auxparam
 *		   so that the PDD will not be deallocated.  Then link the PDD
 *		   into the Physical Device Queue and return DONE_STATE.
 *		12)If an error is thrown from the device handler, free the name
 *		   buffer and rethrow.  I/O completion will free the allocated
 *		   PDD.
 *		13)Otherwise, assume the device handler has set up the packet
 *		   for direct processing and return the state from the device
 *		   handler.  In this case, the device handler is responsible
 *		   for:
 *			*  normal VIOS i/o packet processing conventions
 *			*  clearing Auxparam, preserving PDD in Stataux2,
 *			   checking the device class in Devclass,
 *			   and linking the PDD into Pqueue, if success
 *			*  freeing the name buffer at Devname, if error
 */
{
    register IO_PACKET *pk;	/* dereferenced i/o pointer */
    register char **name;	/* bufptr to device name */
    register PDD *pd;		/* ptr to PDD */
    PDD_PTR pdd;		/* bufptr to Physical Device Descriptor */
    unsigned mod;		/* request modifier */
    CLASS_MODULE **classmod;	/* Class module bufptr */

    pk = *pkt;		/* pk must be refreshed after alloc() */
    name = Auxparam(pk);	/* get bufptr to device name */
    if ( (name EQ NULL) OR (**name EQ '\0') OR
    					(strlen(*name) GT MAX_NAMELENGTH) )
	throw(V_BAD_PARAMS);	/* not a bufptr or no name */

    mod = Fmod(pk);				/* get function modifier */
    if (Osid(pk) GT 0)  mod |= REM_ON_DEA;	/* OS pdds always temporary */

    switch (Stnum(pk))
	{
    case 0:
	if (mod & SHR_WRITE)  mod |= SHR_READ | WRITE_ACCESS;

	if ( ((mod & (READ_ONLY|WRITE_ACCESS)) EQ (READ_ONLY|WRITE_ACCESS)) OR
		(mod & ~(LOOKUP_PD | NEW_PD | SHR_READ | SHR_WRITE |
			READ_ONLY | WRITE_ACCESS | REM_ON_DEA)) )
	    throw(V_ILL_MODIFIER);

	classmod = cls_search(Param1(pk));	/* valid or V_BAD_PARAMS */

	Stnum(pk)++;

    case 1:
	/* If the device already exists, verify shared access */
	if ((pdd = pname_search(*name)) NE NULL)	/* if dev exists */
	    {
	    if ( ((mod & (LOOKUP_PD|NEW_PD)) NE LOOKUP_PD) OR
							(NOT (mod & SHR_READ)) )
		throw(V_DUP_NAME);	/* device cannot be new or non-shared */
	    
	    if ( (NOT Devrdshare(pd = *pdd)) OR
		    ((mod & (WRITE_ACCESS|SHR_WRITE)) EQ WRITE_ACCESS) OR
			((mod & SHR_WRITE) AND (NOT Devwtshare(pd))) OR
			    ((mod & READ_ONLY) AND (Writeable(pd))) )
		throw(V_DEV_BUSY);	/* Connection may not be established */


		/* ***Create new device rather than link to old one*** */

	    } /*if-device exists*/

	/* If device does not exist in VIOS, create a new PDD for it */
	switch (catch())
	    {
	case 0:
	    /* Locate the correct device dispatcher and allocate a PDD */

	    pdd = NULL;		/* initialize, in case of error */
	    pd = *(pdd = pddalloc(Imp_dispatcher(*imp_search(*name))));

	    pk = *pkt;		/* in case of pool compaction */
	    Devname(pd) = name;		/* bufptr to name */
	    Devclass(pd) = Param1(pk);	/* set device class */

	    /* Set attributes based on function modifier */
	    Readable(pd) = TRUE;	/* Always true */
	    if (mod & WRITE_ACCESS) Writeable(pd) = TRUE;
	    if (mod & SHR_READ)  Devrdshare(pd) = TRUE;	/* Shared reading */
	    if (mod & SHR_WRITE) Devwtshare(pd) = TRUE;	/* Shared writing */
	    if (mod & REM_ON_DEA) Detachremove(pd) = TRUE;

	    Classmod(pd) = classmod;	/* set class descriptor bufptr */


	    /* Remove link to free name buffer and set to remove PDD if error */
	    Auxparam(pk) = (char**) (Stataux2(pk) = (int) pdd);


	    /* Call device dispatcher to finish device handling */
	    /* It must check the device class in the PDD */
	    /* and, possibly, call the class-dependent handler */

	    mod = (unsigned) (*Dispatcher(pd))(PDCREATE,pdd,pkt);
	    uncatch();			/* end of protected code */

	    if (mod EQ DONE_STATE)
		{
		Auxparam(pk) = NULL;		/* do not free PDD */
		q_item(pdd, &Pdevices);		/* add to PDD list */
		}

	    return ((PKT_STATE) mod);

	case V_ALL_FAILURE:		/* pkt on wait queue (in viomain.c) */
	case V_SUCCESS:			/* PDD must be queued and */
					/* Auxparam cleared */
	    rethrow();			/* rethrow successful return */

	default:
	    if ((pdd NE NULL) AND (Devname(pd = *pdd) NE NULL))
	    	vfree(Devname(pd));	/* release PDD name, if any */
	    rethrow();			/* pass error along */
	    } /*switch (catch)*/

	break; /*case 1*/

    default:

#ifdef DEBUG3   /*************************************************************/
	error ("Bad stnum in packet @%x (create_pd)", pk);
#endif /* DEBUG3 *************************************************************/

	} /*switch Stnum*/

}

    PKT_STATE					/* Throws: various errors */
prem_handler (pkt)
    register PKT_PTR pkt;

/* prem_handler (pkt) -- Process Remove Physical Device Requests
 *
 *	in:	pkt		I/O Packet to process
 *	return:	(PKT_STATE)	next I/O packet state
 *	thrown:	V_SUCCESS	Packet successfully processed
 *
 *	Process VIOS requests to remove a Physical Device.
 *	Process as follows:
 *		1) Remove all references to the target device.
 *		   See rem_references() (in ctrlsubs.c).
 *		2) Set device to be removed when i/o completes.
 *		   This means it will be removed as soon as this packet
 *		   completes, if it is the only outstanding i/o.
 *		   Otherwise, removal will wait for the rest.
 *		3) Return DONE_STATE and have i/o completion remove the PDD,
 *		   calling the device dispatcher for special handling.
 */
{
    register IO_PACKET *pk;
    register PDD_PTR pdd;	/* PDD to remove */
    register PDD *pd;

    pd = *(pdd = PDevice(pk = *pkt));	/* PDD has already been verified */
    rem_references(pdd);	/* remove all references to this device */

#ifdef DEBUG2   /*************************************************************/
    if (Attachments(pd) NE 0)
	error("Prem_handler couldn't run down pdd at %x", pd);
#endif /* DEBUG2 *************************************************************/


    Rundown(pd) = Compremove(pd) = TRUE;	/* remove when i/o done */
    Statcode(pk) = V_SUCCESS;		/* be optimistic */

    /* I/O completion will call device dispatcher to finish device handling */
    return(DONE_STATE);
}
E 1
