예제 #1
0
파일: switches.c 프로젝트: mercurycc/cs452
int ui_switch_init( Console* cons )
{
	int status = 0;

	/* Initialize switchio body */
	/* Notice an Iobuf is only needed to point to the console.  No
	   io should be done in this frame */
	switchFrameio = &switchFrameiobody;
	status = iobuf_init( switchFrameio, cons );
	ASSERT( status == ERR_NONE );
	
	switchFrame = &switchFramebody;
	buffers[ 0 ] = buffersbody;
	buffers[ 1 ] = buffersbody + UI_SWITCH_WIDTH;
	
	status = region_setup( switchFrame, 0,
			       UI_SWITCH_COLUMN, UI_SWITCH_ROW,
			       UI_SWITCH_WIDTH, UI_SWITCH_HEIGHT,
			       UI_SWITCH_HORIZONTAL_MARGIN, UI_SWITCH_VERTICAL_MARGIN,
			       UI_SWITCH_BOUNDRY, switchFrameio, buffers );
	ASSERT( status == ERR_NONE );

	status = region_init( switchFrame );
	ASSERT( status == ERR_NONE );

	status = region_write( switchFrame, UI_SWITCH_TITLE );
	ASSERT( status == ERR_NONE );

	while( ! region_flushed( switchFrame ) ){
		status = region_flush( switchFrame );
		ASSERT( status == ERR_NONE );
	}

	/* Print switch names */
	status = ui_switch_names( cons );
	ASSERT( status == ERR_NONE );

	/* Init switch individual states */
	status = ui_switch_state_init( cons );
	ASSERT( status == ERR_NONE );

	return ERR_NONE;
}
예제 #2
0
파일: timer.c 프로젝트: mercurycc/cs452
int ui_timer_init( Console* outputCons )
{
	int status = 0;
	
	iobuf = &iobody;	
	status = iobuf_init( iobuf, outputCons );
	ASSERT( status == ERR_NONE );

	buffers[ 0 ] = buffersbody;
	buffers[ 1 ] = buffersbody + UI_TIME_WIDTH;

	cons = &consbody;
	status = region_setup( cons, 0, UI_TIME_COLUMN, UI_TIME_ROW, UI_TIME_WIDTH, UI_TIME_HEIGHT, UI_TIME_HORIZONTAL_MARGIN, UI_TIME_VERTICAL_MARGIN, UI_TIME_BOUNDRY, iobuf, buffers );
	ASSERT( status == ERR_NONE );

	status = region_init( cons );
	ASSERT( status == ERR_NONE );

	DEBUG_PRINT( DBG_TIMER, "%s: Done\n", __func__ );

	return ERR_NONE;
}
예제 #3
0
파일: switches.c 프로젝트: mercurycc/cs452
static inline int ui_switch_state_init( Console* cons )
{
	uint i = 0;
	int status = 0;
	uchar* buffers[ 2 ] = { 0 };

	for( i = 0; i < SWITCHES_COUNT; i += 1 ){
		status = iobuf_init( switchesIoBuf + i, cons );
		ASSERT( status == ERR_NONE );

		buffers[ 0 ] = switchesOutBuf + i * 2;
		buffers[ 1 ] = switchesOutBuf + i * 2 + 1;

		region_setup( switches + i, switchFrame,
			      ( i % UI_SWITCH_NAME_PER_LINE ) * UI_SWITCH_NAME_SIZE + UI_SWITCH_STATE_OFFSET,
			      ( i / UI_SWITCH_NAME_PER_LINE ) + 2,
			      1, 1, 0, 0, 0, switchesIoBuf + i, buffers );

		region_init( switches + i );
	}
	
	return ERR_NONE;
}
예제 #4
0
void
acpi_ev_detach_region(union acpi_operand_object *region_obj,
                      u8 acpi_ns_is_locked)
{
    union acpi_operand_object *handler_obj;
    union acpi_operand_object *obj_desc;
    union acpi_operand_object *start_desc;
    union acpi_operand_object **last_obj_ptr;
    acpi_adr_space_setup region_setup;
    void **region_context;
    union acpi_operand_object *region_obj2;
    acpi_status status;

    ACPI_FUNCTION_TRACE(ev_detach_region);

    region_obj2 = acpi_ns_get_secondary_object(region_obj);
    if (!region_obj2) {
        return_VOID;
    }
    region_context = &region_obj2->extra.region_context;

    /* Get the address handler from the region object */

    handler_obj = region_obj->region.handler;
    if (!handler_obj) {

        /* This region has no handler, all done */

        return_VOID;
    }

    /* Find this region in the handler's list */

    obj_desc = handler_obj->address_space.region_list;
    start_desc = obj_desc;
    last_obj_ptr = &handler_obj->address_space.region_list;

    while (obj_desc) {

        /* Is this the correct Region? */

        if (obj_desc == region_obj) {
            ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                              "Removing Region %p from address handler %p\n",
                              region_obj, handler_obj));

            /* This is it, remove it from the handler's list */

            *last_obj_ptr = obj_desc->region.next;
            obj_desc->region.next = NULL;	/* Must clear field */

            if (acpi_ns_is_locked) {
                status =
                    acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
                if (ACPI_FAILURE(status)) {
                    return_VOID;
                }
            }

            /* Now stop region accesses by executing the _REG method */

            status =
                acpi_ev_execute_reg_method(region_obj,
                                           ACPI_REG_DISCONNECT);
            if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status,
                                "from region _REG, [%s]",
                                acpi_ut_get_region_name
                                (region_obj->region.space_id)));
            }

            if (acpi_ns_is_locked) {
                status =
                    acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
                if (ACPI_FAILURE(status)) {
                    return_VOID;
                }
            }

            /*
             * If the region has been activated, call the setup handler with
             * the deactivate notification
             */
            if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {
                region_setup = handler_obj->address_space.setup;
                status =
                    region_setup(region_obj,
                                 ACPI_REGION_DEACTIVATE,
                                 handler_obj->address_space.
                                 context, region_context);

                /*
                 * region_context should have been released by the deactivate
                 * operation. We don't need access to it anymore here.
                 */
                if (region_context) {
                    *region_context = NULL;
                }

                /* Init routine may fail, Just ignore errors */

                if (ACPI_FAILURE(status)) {
                    ACPI_EXCEPTION((AE_INFO, status,
                                    "from region handler - deactivate, [%s]",
                                    acpi_ut_get_region_name
                                    (region_obj->region.
                                     space_id)));
                }

                region_obj->region.flags &=
                    ~(AOPOBJ_SETUP_COMPLETE);
            }

            /*
             * Remove handler reference in the region
             *
             * NOTE: this doesn't mean that the region goes away, the region
             * is just inaccessible as indicated to the _REG method
             *
             * If the region is on the handler's list, this must be the
             * region's handler
             */
            region_obj->region.handler = NULL;
            acpi_ut_remove_reference(handler_obj);

            return_VOID;
        }

        /* Walk the linked list of handlers */

        last_obj_ptr = &obj_desc->region.next;
        obj_desc = obj_desc->region.next;

        /* Prevent infinite loop if list is corrupted */

        if (obj_desc == start_desc) {
            ACPI_ERROR((AE_INFO,
                        "Circular handler list in region object %p",
                        region_obj));
            return_VOID;
        }
    }

    /* If we get here, the region was not in the handler's region list */

    ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                      "Cannot remove region %p from address handler %p\n",
                      region_obj, handler_obj));

    return_VOID;
}
예제 #5
0
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
                               union acpi_operand_object *field_obj,
                               u32 function,
                               u32 region_offset, u32 bit_width, u64 *value)
{
    acpi_status status;
    acpi_adr_space_handler handler;
    acpi_adr_space_setup region_setup;
    union acpi_operand_object *handler_desc;
    union acpi_operand_object *region_obj2;
    void *region_context = NULL;
    struct acpi_connection_info *context;
    acpi_physical_address address;

    ACPI_FUNCTION_TRACE(ev_address_space_dispatch);

    region_obj2 = acpi_ns_get_secondary_object(region_obj);
    if (!region_obj2) {
        return_ACPI_STATUS(AE_NOT_EXIST);
    }

    /* Ensure that there is a handler associated with this region */

    handler_desc = region_obj->region.handler;
    if (!handler_desc) {
        ACPI_ERROR((AE_INFO,
                    "No handler for Region [%4.4s] (%p) [%s]",
                    acpi_ut_get_node_name(region_obj->region.node),
                    region_obj,
                    acpi_ut_get_region_name(region_obj->region.
                                            space_id)));

        return_ACPI_STATUS(AE_NOT_EXIST);
    }

    context = handler_desc->address_space.context;

    /*
     * It may be the case that the region has never been initialized.
     * Some types of regions require special init code
     */
    if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {

        /* This region has not been initialized yet, do it */

        region_setup = handler_desc->address_space.setup;
        if (!region_setup) {

            /* No initialization routine, exit with error */

            ACPI_ERROR((AE_INFO,
                        "No init routine for region(%p) [%s]",
                        region_obj,
                        acpi_ut_get_region_name(region_obj->region.
                                                space_id)));
            return_ACPI_STATUS(AE_NOT_EXIST);
        }

        /*
         * We must exit the interpreter because the region setup will
         * potentially execute control methods (for example, the _REG method
         * for this region)
         */
        acpi_ex_exit_interpreter();

        status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
                              context, &region_context);

        /* Re-enter the interpreter */

        acpi_ex_enter_interpreter();

        /* Check for failure of the Region Setup */

        if (ACPI_FAILURE(status)) {
            ACPI_EXCEPTION((AE_INFO, status,
                            "During region initialization: [%s]",
                            acpi_ut_get_region_name(region_obj->
                                                    region.
                                                    space_id)));
            return_ACPI_STATUS(status);
        }

        /* Region initialization may have been completed by region_setup */

        if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
            region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;

            /*
             * Save the returned context for use in all accesses to
             * the handler for this particular region
             */
            if (!(region_obj2->extra.region_context)) {
                region_obj2->extra.region_context =
                    region_context;
            }
        }
    }

    /* We have everything we need, we can invoke the address space handler */

    handler = handler_desc->address_space.handler;
    address = (region_obj->region.address + region_offset);

    /*
     * Special handling for generic_serial_bus and general_purpose_io:
     * There are three extra parameters that must be passed to the
     * handler via the context:
     *   1) Connection buffer, a resource template from Connection() op
     *   2) Length of the above buffer
     *   3) Actual access length from the access_as() op
     *
     * In addition, for general_purpose_io, the Address and bit_width fields
     * are defined as follows:
     *   1) Address is the pin number index of the field (bit offset from
     *      the previous Connection)
     *   2) bit_width is the actual bit length of the field (number of pins)
     */
    if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
            context && field_obj) {

        /* Get the Connection (resource_template) buffer */

        context->connection = field_obj->field.resource_buffer;
        context->length = field_obj->field.resource_length;
        context->access_length = field_obj->field.access_length;
    }
    if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
            context && field_obj) {

        /* Get the Connection (resource_template) buffer */

        context->connection = field_obj->field.resource_buffer;
        context->length = field_obj->field.resource_length;
        context->access_length = field_obj->field.access_length;
        address = field_obj->field.pin_number_index;
        bit_width = field_obj->field.bit_length;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
                      "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
                      &region_obj->region.handler->address_space, handler,
                      ACPI_FORMAT_NATIVE_UINT(address),
                      acpi_ut_get_region_name(region_obj->region.
                              space_id)));

    if (!(handler_desc->address_space.handler_flags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
        /*
         * For handlers other than the default (supplied) handlers, we must
         * exit the interpreter because the handler *might* block -- we don't
         * know what it will do, so we can't hold the lock on the intepreter.
         */
        acpi_ex_exit_interpreter();
    }

    /* Call the handler */

    status = handler(function, address, bit_width, value, context,
                     region_obj2->extra.region_context);

    if (ACPI_FAILURE(status)) {
        ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
                        acpi_ut_get_region_name(region_obj->region.
                                                space_id)));
    }

    if (!(handler_desc->address_space.handler_flags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
        /*
         * We just returned from a non-default handler, we must re-enter the
         * interpreter
         */
        acpi_ex_enter_interpreter();
    }

    return_ACPI_STATUS(status);
}
예제 #6
0
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
			       u32 function,
			       acpi_physical_address address,
			       u32 bit_width, acpi_integer * value)
{
	acpi_status status;
	acpi_status status2;
	acpi_adr_space_handler handler;
	acpi_adr_space_setup region_setup;
	union acpi_operand_object *handler_desc;
	union acpi_operand_object *region_obj2;
	void *region_context = NULL;

	ACPI_FUNCTION_TRACE(ev_address_space_dispatch);

	region_obj2 = acpi_ns_get_secondary_object(region_obj);
	if (!region_obj2) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/* Ensure that there is a handler associated with this region */

	handler_desc = region_obj->region.handler;
	if (!handler_desc) {
		ACPI_ERROR((AE_INFO,
			    "No handler for Region [%4.4s] (%p) [%s]",
			    acpi_ut_get_node_name(region_obj->region.node),
			    region_obj,
			    acpi_ut_get_region_name(region_obj->region.
						    space_id)));

		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/*
	 * It may be the case that the region has never been initialized
	 * Some types of regions require special init code
	 */
	if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
		/*
		 * This region has not been initialized yet, do it
		 */
		region_setup = handler_desc->address_space.setup;
		if (!region_setup) {

			/* No initialization routine, exit with error */

			ACPI_ERROR((AE_INFO,
				    "No init routine for region(%p) [%s]",
				    region_obj,
				    acpi_ut_get_region_name(region_obj->region.
							    space_id)));
			return_ACPI_STATUS(AE_NOT_EXIST);
		}

		/*
		 * We must exit the interpreter because the region
		 * setup will potentially execute control methods
		 * (e.g., _REG method for this region)
		 */
		acpi_ex_exit_interpreter();

		status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
				      handler_desc->address_space.context,
				      &region_context);

		/* Re-enter the interpreter */

		status2 = acpi_ex_enter_interpreter();
		if (ACPI_FAILURE(status2)) {
			return_ACPI_STATUS(status2);
		}

		/* Check for failure of the Region Setup */

		if (ACPI_FAILURE(status)) {
			ACPI_EXCEPTION((AE_INFO, status,
					"During region initialization: [%s]",
					acpi_ut_get_region_name(region_obj->
								region.
								space_id)));
			return_ACPI_STATUS(status);
		}

		/*
		 * Region initialization may have been completed by region_setup
		 */
		if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
			region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;

			if (region_obj2->extra.region_context) {

				/* The handler for this region was already installed */

				ACPI_FREE(region_context);
			} else {
				/*
				 * Save the returned context for use in all accesses to
				 * this particular region
				 */
				region_obj2->extra.region_context =
				    region_context;
			}
		}
	}

	/* We have everything we need, we can invoke the address space handler */

	handler = handler_desc->address_space.handler;

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
			  &region_obj->region.handler->address_space, handler,
			  ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(region_obj->region.
						  space_id)));

	if (!(handler_desc->address_space.handler_flags &
	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * For handlers other than the default (supplied) handlers, we must
		 * exit the interpreter because the handler *might* block -- we don't
		 * know what it will do, so we can't hold the lock on the intepreter.
		 */
		acpi_ex_exit_interpreter();
	}

	/* Call the handler */

	status = handler(function, address, bit_width, value,
			 handler_desc->address_space.context,
			 region_obj2->extra.region_context);

	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
				acpi_ut_get_region_name(region_obj->region.
							space_id)));
	}

	if (!(handler_desc->address_space.handler_flags &
	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * We just returned from a non-default handler, we must re-enter the
		 * interpreter
		 */
		status2 = acpi_ex_enter_interpreter();
		if (ACPI_FAILURE(status2)) {
			return_ACPI_STATUS(status2);
		}
	}

	return_ACPI_STATUS(status);
}
예제 #7
0
void
acpi_ev_detach_region(
	union acpi_operand_object       *region_obj,
	u8                              acpi_ns_is_locked)
{
	union acpi_operand_object       *handler_obj;
	union acpi_operand_object       *obj_desc;
	union acpi_operand_object       **last_obj_ptr;
	acpi_adr_space_setup            region_setup;
	void                            **region_context;
	union acpi_operand_object       *region_obj2;
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("ev_detach_region");


	region_obj2 = acpi_ns_get_secondary_object (region_obj);
	if (!region_obj2) {
		return_VOID;
	}
	region_context = &region_obj2->extra.region_context;

	/* Get the address handler from the region object */

	handler_obj = region_obj->region.address_space;
	if (!handler_obj) {
		/* This region has no handler, all done */

		return_VOID;
	}

	/* Find this region in the handler's list */

	obj_desc = handler_obj->address_space.region_list;
	last_obj_ptr = &handler_obj->address_space.region_list;

	while (obj_desc) {
		/* Is this the correct Region? */

		if (obj_desc == region_obj) {
			ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
				"Removing Region %p from address handler %p\n",
				region_obj, handler_obj));

			/* This is it, remove it from the handler's list */

			*last_obj_ptr = obj_desc->region.next;
			obj_desc->region.next = NULL;           /* Must clear field */

			if (acpi_ns_is_locked) {
				status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
				if (ACPI_FAILURE (status)) {
					return_VOID;
				}
			}

			/* Now stop region accesses by executing the _REG method */

			status = acpi_ev_execute_reg_method (region_obj, 0);
			if (ACPI_FAILURE (status)) {
				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
					acpi_format_exception (status),
					acpi_ut_get_region_name (region_obj->region.space_id)));
			}

			if (acpi_ns_is_locked) {
				status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
				if (ACPI_FAILURE (status)) {
					return_VOID;
				}
			}

			/* Call the setup handler with the deactivate notification */

			region_setup = handler_obj->address_space.setup;
			status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
					  handler_obj->address_space.context, region_context);

			/* Init routine may fail, Just ignore errors */

			if (ACPI_FAILURE (status)) {
				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
					acpi_format_exception (status),
					acpi_ut_get_region_name (region_obj->region.space_id)));
			}

			region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);

			/*
			 * Remove handler reference in the region
			 *
			 * NOTE: this doesn't mean that the region goes away
			 * The region is just inaccessible as indicated to
			 * the _REG method
			 *
			 * If the region is on the handler's list
			 * this better be the region's handler
			 */
			region_obj->region.address_space = NULL;
			acpi_ut_remove_reference (handler_obj);

			return_VOID;
		}

		/* Walk the linked list of handlers */

		last_obj_ptr = &obj_desc->region.next;
		obj_desc = obj_desc->region.next;
	}

	/* If we get here, the region was not in the handler's region list */

	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
		"Cannot remove region %p from address handler %p\n",
		region_obj, handler_obj));

	return_VOID;
}
예제 #8
0
파일: switches.c 프로젝트: mercurycc/cs452
static inline int ui_switch_names( Console* cons )
{
	/* Switch name */
	Iobuf switchNameIobody;
	Iobuf* switchNameIo;
	Region switchNamebody;
	Region* switchName;
	uchar switchNameBuffer[ UI_SWITCH_NAME_SIZE * 2 ];
	uchar* switchNamebuffers[ 2 ];

	int status = 0;
	int i = 1;
	int switchId = 1;
	uchar curname[ UI_SWITCH_NAME_SIZE ] = UI_SWITCH_NAME;
	uint convSize = 0;

	switchNameIo = &switchNameIobody;
	switchName = &switchNamebody;
	switchNamebuffers[ 0 ] = switchNameBuffer;
	switchNamebuffers[ 1 ] = switchNameBuffer + UI_SWITCH_NAME_SIZE;

	while( 1 ){
		status = iobuf_init( switchNameIo, cons );
		ASSERT( status == ERR_NONE );
	
		status = region_setup( switchName, switchFrame,
				       ( ( ( i - 1 ) % UI_SWITCH_NAME_PER_LINE ) * UI_SWITCH_NAME_SIZE ),
				       ( i - 1 ) / UI_SWITCH_NAME_PER_LINE + 2,
				       UI_SWITCH_NAME_SIZE, 1,
				       0, 0,
				       0, switchNameIo, switchNamebuffers );
		ASSERT( status == ERR_NONE );

		status = region_init( switchName );
		ASSERT( status == ERR_NONE );

		if( i > 18 ){
			switchId = 153 + i - 19;
		} else {
			switchId = i;
		}

		convSize = utos( switchId, (char*)(curname + UI_SWITCH_NAME_NUMBER_OFFSET) );

		switch( convSize ){
		case 1:
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 2 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET ];
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET ] = ' ';
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ] = ' ';
			break;
		case 2:
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 2 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ];
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 1 ] = curname[ UI_SWITCH_NAME_NUMBER_OFFSET ];
			curname[ UI_SWITCH_NAME_NUMBER_OFFSET ] = ' ';
		}
		
		curname[ UI_SWITCH_NAME_NUMBER_OFFSET + 3 ] = ' ';
		curname[ UI_SWITCH_NAME_SIZE - 1 ] = '\0';

		status = region_write( switchName, (char*)curname );
		ASSERT( status == ERR_NONE );

		while( ! region_flushed( switchName ) ){
			status = region_flush( switchName );
			ASSERT( status == ERR_NONE );
		}

		i += 1;
		if( i > SWITCHES_COUNT ){
			break;
		}
	}

	return ERR_NONE;
}
예제 #9
0
void
acpi_ev_disassociate_region_from_handler(
	ACPI_OPERAND_OBJECT     *region_obj,
	u8                      acpi_ns_is_locked)
{
	ACPI_OPERAND_OBJECT     *handler_obj;
	ACPI_OPERAND_OBJECT     *obj_desc;
	ACPI_OPERAND_OBJECT     **last_obj_ptr;
	ADDRESS_SPACE_SETUP     region_setup;
	void                    *region_context;
	ACPI_STATUS             status;


	region_context = region_obj->region.extra->extra.region_context;

	/*
	 *  Get the address handler from the region object
	 */

	handler_obj = region_obj->region.addr_handler;
	if (!handler_obj) {
		/*
		 *  This region has no handler, all done
		 */
		return;
	}


	/*
	 *  Find this region in the handler's list
	 */

	obj_desc = handler_obj->addr_handler.region_list;
	last_obj_ptr = &handler_obj->addr_handler.region_list;

	while (obj_desc) {
		/*
		 *  See if this is the one
		 */
		if (obj_desc == region_obj) {
			/*
			 *  This is it, remove it from the handler's list
			 */
			*last_obj_ptr = obj_desc->region.next;
			obj_desc->region.next = NULL;           /* Must clear field */

			if (acpi_ns_is_locked) {
				acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
			}

			/*
			 *  Now stop region accesses by executing the _REG method
			 */
			acpi_ev_execute_reg_method (region_obj, 0);

			if (acpi_ns_is_locked) {
				acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
			}

			/*
			 *  Call the setup handler with the deactivate notification
			 */
			region_setup = handler_obj->addr_handler.setup;
			status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
					  handler_obj->addr_handler.context,
					  &region_context);

			/*
			 *  Init routine may fail, Just ignore errors
			 */

			region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);

			/*
			 *  Remove handler reference in the region
			 *
			 *  NOTE: this doesn't mean that the region goes away
			 *  The region is just inaccessible as indicated to
			 *  the _REG method
			 *
			 *  If the region is on the handler's list
			 *  this better be the region's handler
			 */
			ACPI_ASSERT (region_obj->region.addr_handler == handler_obj);

			region_obj->region.addr_handler = NULL;

			return;

		} /* found the right handler */

		/*
		 *  Move through the linked list of handlers
		 */
		last_obj_ptr = &obj_desc->region.next;
		obj_desc = obj_desc->region.next;
	}

	/*
	 *  If we get here, the region was not in the handler's region list
	 */
	return;
}
예제 #10
0
ACPI_STATUS
acpi_ev_address_space_dispatch (
	ACPI_OPERAND_OBJECT     *region_obj,
	u32                     function,
	ACPI_PHYSICAL_ADDRESS   address,
	u32                     bit_width,
	u32                     *value)
{
	ACPI_STATUS             status;
	ADDRESS_SPACE_HANDLER   handler;
	ADDRESS_SPACE_SETUP     region_setup;
	ACPI_OPERAND_OBJECT     *handler_desc;
	void                    *region_context = NULL;


	/*
	 *  Check for an installed handler
	 */
	handler_desc = region_obj->region.addr_handler;

	if (!handler_desc) {
		return(AE_NOT_EXIST);
	}

	/*
	 *  It may be the case that the region has never been initialized
	 *  Some types of regions require special init code
	 */
	if (!(region_obj->region.flags & AOPOBJ_INITIALIZED)) {
		/*
		 *  This region has not been initialized yet, do it
		 */
		region_setup = handler_desc->addr_handler.setup;
		if (!region_setup) {
			/*
			 *  Bad news, no init routine and not init'd
			 */
			return (AE_UNKNOWN_STATUS);
		}

		/*
		 * We must exit the interpreter because the region setup will potentially
		 * execute control methods
		 */
		acpi_aml_exit_interpreter ();

		status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
				  handler_desc->addr_handler.context,
				  &region_context);

		/* Re-enter the interpreter */

		acpi_aml_enter_interpreter ();

		/*
		 *  Init routine may fail
		 */
		if (ACPI_FAILURE (status)) {
			return(status);
		}

		region_obj->region.flags |= AOPOBJ_INITIALIZED;

		/*
		 *  Save the returned context for use in all accesses to
		 *  this particular region.
		 */
		region_obj->region.extra->extra.region_context = region_context;
	}

	/*
	 *  We have everything we need, begin the process
	 */
	handler = handler_desc->addr_handler.handler;

	if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 *  For handlers other than the default (supplied) handlers, we must
		 *  exit the interpreter because the handler *might* block -- we don't
		 *  know what it will do, so we can't hold the lock on the intepreter.
		 */
		acpi_aml_exit_interpreter();
	}

	/*
	 *  Invoke the handler.
	 */
	status = handler (function, address, bit_width, value,
			 handler_desc->addr_handler.context,
			 region_obj->region.extra->extra.region_context);


	if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/* We just returned from a non-default handler, we must re-enter the
		interpreter */

		acpi_aml_enter_interpreter ();
	}

	return (status);
}