void scic_cb_port_not_ready(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port,
   U32                      reason_code
)
{
   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*)
                                   sci_object_get_association(port);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN,
      "scic_cb_port_not_ready(0x%x, 0x%x) enter\n",
      controller, port
   ));

   // The controller supplied with the port should match the controller
   // saved in the domain.
   ASSERT(sci_object_get_association(controller) == fw_domain->controller);

   // There is no need to take action on the port reconfiguring since it is
   // just a change of the port width.
   if (reason_code != SCIC_PORT_NOT_READY_RECONFIGURING)
   {
      fw_domain->is_port_ready = FALSE;

      fw_domain->state_handlers->port_not_ready_handler(
                                    &fw_domain->parent, reason_code);
   }
}
void scic_cb_port_bc_change_primitive_recieved(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port,
   SCI_PHY_HANDLE_T         phy
)
{
   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*)
                                   sci_object_get_association(port);

   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
                                           sci_object_get_association(controller);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN | SCIF_LOG_OBJECT_DOMAIN_DISCOVERY,
      "scic_cb_port_bc_change_primitive_recieved(0x%x, 0x%x, 0x%x) enter\n",
      controller, port, phy
   ));

   if (fw_domain->broadcast_change_count == 0)
   {  // Enable the BCN detection only if the bcn_count is zero. If bcn_count is
      // not zero at this time, we won't enable BCN detection since all non-zero
      // BCN_count means same to us. Furthermore, we avoid BCN storm by not
      // always enabling the BCN_detection.
      scic_port_enable_broadcast_change_notification(fw_domain->core_object);
   }

   fw_domain->broadcast_change_count++;

   //if there is smp device on this domain that is in the middle of discover
   //process or smp target reset, don't notify the driver layer.
   if( ! scif_sas_domain_is_in_smp_activity(fw_domain) )
      // Notify the user that there is, potentially, a change to the domain.
      scif_cb_domain_change_notification(fw_controller, fw_domain);
}
Example #3
0
/**
 * @brief This callback method gets the SMP frame type for an SMP request.
 *
 * @param[in]  core_request This parameter specifies the SCI core's request
 *             object associated with the SMP request.
 *
 * @return SMP frame type for the SMP request.
 */
static uint8_t
smp_io_request_cb_get_frame_type(SCI_IO_REQUEST_HANDLE_T core_request)
{
	struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
	    sci_object_get_association(sci_object_get_association(core_request));
	SMP_REQUEST_HEADER_T *header =
	    (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;

	return (header->smp_frame_type);
}
Example #4
0
/**
 * @brief This callback method gets the allocated response length for an SMP request.
 *
 * @param[in]  core_request This parameter specifies the SCI core's request
 *             object associated with the SMP request.
 *
 * @return Allocated response length for the SMP request.
 */
static uint8_t
smp_io_request_cb_get_allocated_response_length(
    SCI_IO_REQUEST_HANDLE_T core_request)
{
	struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
	    sci_object_get_association(sci_object_get_association(core_request));
	SMP_REQUEST_HEADER_T *header =
	    (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;

	return (header->allocated_response_length);
}
U8 *scic_cb_io_request_get_virtual_address_from_sgl(
   void * scic_user_io_request,
   U32    byte_offset
)
{
   SCIF_SAS_REQUEST_T *fw_request =
      (SCIF_SAS_REQUEST_T *) sci_object_get_association(scic_user_io_request);

   return scif_cb_io_request_get_virtual_address_from_sgl(
             sci_object_get_association(fw_request),
             byte_offset
          );
}
Example #6
0
/**
 * @brief This callback method gets the size of and pointer to the buffer
 *         (if any) containing the request buffer for an SMP request.
 *
 * @param[in]  core_request This parameter specifies the SCI core's request
 *             object associated with the SMP request.
 * @param[out] smp_request_buffer This parameter returns a pointer to the
 *             payload portion of the SMP request - i.e. everything after
 *             the SMP request header.
 *
 * @return Size of the request buffer in bytes.  This does *not* include
 *          the size of the SMP request header.
 */
static uint32_t
smp_io_request_cb_get_request_buffer(SCI_IO_REQUEST_HANDLE_T core_request,
    uint8_t ** smp_request_buffer)
{
	struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
	    sci_object_get_association(sci_object_get_association(core_request));

	*smp_request_buffer = isci_request->ccb->smpio.smp_request +
	    sizeof(SMP_REQUEST_HEADER_T);

	return (isci_request->ccb->smpio.smp_request_len -
	    sizeof(SMP_REQUEST_HEADER_T));
}
Example #7
0
/**
 * @brief In this method the user must read from PCI memory via access.
 *        This method is used for access to memory space and IO space.
 *
 * @param[in]  controller The controller for which to read a DWORD.
 * @param[in]  address This parameter depicts the address from
 *             which to read.
 *
 * @return The value being returned from the PCI memory location.
 *
 * @todo This PCI memory access calls likely need to be optimized into macro?
 */
uint32_t
scic_cb_pci_read_dword(SCI_CONTROLLER_HANDLE_T scic_controller, void *address)
{
    SCI_CONTROLLER_HANDLE_T scif_controller =
        (SCI_CONTROLLER_HANDLE_T)sci_object_get_association(scic_controller);
    struct ISCI_CONTROLLER *isci_controller =
        (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
    struct isci_softc *isci = isci_controller->isci;
    uint32_t bar = (uint32_t)(((POINTER_UINT)address & 0xF0000000) >> 28);
    bus_size_t offset = (bus_size_t)((POINTER_UINT)address & 0x0FFFFFFF);

    return (bus_space_read_4(isci->pci_bar[bar].bus_tag,
                             isci->pci_bar[bar].bus_handle, offset));
}
Example #8
0
void scic_cb_controller_stop_complete(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_STATUS               completion_status
)
{
   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
                                         sci_object_get_association(controller);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(controller),
      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_SHUTDOWN,
      "scic_cb_controller_stop_complete(0x%x, 0x%x) enter\n",
      controller, completion_status
   ));

   if (completion_status == SCI_SUCCESS)
   {
      sci_base_state_machine_change_state(
         &fw_controller->parent.state_machine,
         SCI_BASE_CONTROLLER_STATE_STOPPED
      );
   }
   else
   {
      sci_base_state_machine_change_state(
         &fw_controller->parent.state_machine,
         SCI_BASE_CONTROLLER_STATE_FAILED
      );
   }

   scif_cb_controller_stop_complete(fw_controller, completion_status);
}
Example #9
0
void scic_cb_controller_start_complete(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_STATUS               completion_status
)
{
   SCIF_SAS_CONTROLLER_T *fw_controller = (SCIF_SAS_CONTROLLER_T*)
                                         sci_object_get_association(controller);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(controller),
      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_INITIALIZATION,
      "scic_cb_controller_start_complete(0x%x, 0x%x) enter\n",
      controller, completion_status
   ));

   if (completion_status == SCI_SUCCESS
       || completion_status == SCI_FAILURE_TIMEOUT)
   {
      // Even the initialization of the core controller timed out, framework
      // controller should still transit to READY state.
      sci_base_state_machine_change_state(
         &fw_controller->parent.state_machine,
         SCI_BASE_CONTROLLER_STATE_READY
      );
   }

   scif_cb_controller_start_complete(fw_controller, completion_status);
}
Example #10
0
/**
 * @brief This user callback will inform the user that the controller has
 *        finished the start process.
 *
 * @param[in]  controller This parameter specifies the controller that was
 *             started.
 * @param[in]  completion_status This parameter specifies the results of
 *             the start operation.  SCI_SUCCESS indicates successful
 *             completion.
 *
 * @return none
 */
void scif_cb_controller_start_complete(SCI_CONTROLLER_HANDLE_T controller,
    SCI_STATUS completion_status)
{
	uint32_t index;
	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
	    sci_object_get_association(controller);

	isci_controller->is_started = TRUE;

	/* Set bits for all domains.  We will clear them one-by-one once
	 *  the domains complete discovery, or return error when calling
	 *  scif_domain_discover.  Once all bits are clear, we will register
	 *  the controller with CAM.
	 */
	isci_controller->initial_discovery_mask = (1 << SCI_MAX_DOMAINS) - 1;

	for(index = 0; index < SCI_MAX_DOMAINS; index++) {
		SCI_STATUS status;
		SCI_DOMAIN_HANDLE_T domain =
		    isci_controller->domain[index].sci_object;

		status = scif_domain_discover(
			domain,
			scif_domain_get_suggested_discover_timeout(domain),
			DEVICE_TIMEOUT
		);

		if (status != SCI_SUCCESS)
		{
			isci_controller_domain_discovery_complete(
			    isci_controller, &isci_controller->domain[index]);
		}
	}
}
Example #11
0
/**
 * @brief This method will be invoked to allocate memory dynamically.
 *
 * @param[in]  controller This parameter represents the controller
 *             object for which to allocate memory.
 * @param[out] mde This parameter represents the memory descriptor to
 *             be filled in by the user that will reference the newly
 *             allocated memory.
 *
 * @return none
 */
void scif_cb_controller_allocate_memory(SCI_CONTROLLER_HANDLE_T controller,
    SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde)
{
	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
	    sci_object_get_association(controller);

	/*
	 * Note this routine is only used for buffers needed to translate
	 * SCSI UNMAP commands to ATA DSM commands for SATA disks.
	 *
	 * We first try to pull a buffer from the controller's pool, and only
	 * call contigmalloc if one isn't there.
	 */
	if (!sci_pool_empty(isci_controller->unmap_buffer_pool)) {
		sci_pool_get(isci_controller->unmap_buffer_pool,
		    mde->virtual_address);
	} else
		mde->virtual_address = contigmalloc(PAGE_SIZE,
		    M_ISCI, M_NOWAIT, 0, BUS_SPACE_MAXADDR,
		    mde->constant_memory_alignment, 0);

	if (mde->virtual_address != NULL)
		bus_dmamap_load(isci_controller->buffer_dma_tag,
		    NULL, mde->virtual_address, PAGE_SIZE,
		    isci_single_map, &mde->physical_address,
		    BUS_DMA_NOWAIT);
}
void scic_cb_io_request_copy_buffer(
   void * scic_user_io_request,
   U8    *source_addr,
   U32   offset,
   U32   length
)
{
   SCIF_SAS_REQUEST_T *fw_request =
      (SCIF_SAS_REQUEST_T *)sci_object_get_association(scic_user_io_request);

   return scif_cb_io_request_copy_buffer(
             sci_object_get_association(fw_request),
             source_addr,
             offset,
             length
          );
}
Example #13
0
/**
 * @brief This user callback will inform the user that the controller has
 *        finished the stop process. Note, after user calls
 *        scif_controller_stop(), before user receives this controller stop
 *        complete callback, user should not expect any callback from
 *        framework, such like scif_cb_domain_change_notification().
 *
 * @param[in]  controller This parameter specifies the controller that was
 *             stopped.
 * @param[in]  completion_status This parameter specifies the results of
 *             the stop operation.  SCI_SUCCESS indicates successful
 *             completion.
 *
 * @return none
 */
void scif_cb_controller_stop_complete(SCI_CONTROLLER_HANDLE_T controller,
    SCI_STATUS completion_status)
{
	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
	    sci_object_get_association(controller);

	isci_controller->is_started = FALSE;
}
Example #14
0
void scic_cb_port_hard_reset_complete(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port,
   SCI_STATUS               completion_status
)
{
   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T*)
                                   sci_object_get_association(port);
   SCIF_SAS_REMOTE_DEVICE_T * fw_device;
   SCI_FAST_LIST_ELEMENT_T  * element = fw_domain->request_list.list_head;
   SCIF_SAS_TASK_REQUEST_T  * task_request = NULL;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN,
      "scic_cb_port_hard_reset_complete(0x%x, 0x%x, 0x%x) enter\n",
      controller, port, completion_status
   ));

   while (element != NULL)
   {
      task_request = (SCIF_SAS_TASK_REQUEST_T*) sci_fast_list_get_object(element);
      element = sci_fast_list_get_next(element);

      if (scif_sas_task_request_get_function(task_request)
             == SCI_SAS_HARD_RESET)
      {
         fw_device = task_request->parent.device;

         if (fw_device->domain == fw_domain)
         {
            scic_remote_device_reset_complete(fw_device->core_object);

            scif_cb_task_request_complete(
               sci_object_get_association(controller),
               fw_device,
               task_request,
               (SCI_TASK_STATUS) completion_status
            );

            break;
         }
      }
   }
}
Example #15
0
void scic_cb_port_link_down(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port,
   SCI_PHY_HANDLE_T         phy
)
{
   SCIF_SAS_DOMAIN_T        * fw_domain = (SCIF_SAS_DOMAIN_T*)
                                 sci_object_get_association(port);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(sci_object_get_association(port)),
      SCIF_LOG_OBJECT_DOMAIN,
      "scic_cb_port_link_down(0x%x, 0x%x, 0x%x) enter\n",
      controller, port, phy
   ));

   scif_sas_domain_update_device_port_width(fw_domain, port);
}
Example #16
0
void scic_cb_timer_stop(
   SCI_CONTROLLER_HANDLE_T   controller,
   void                    * timer
)
{
   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
                                         sci_object_get_association(controller);

   scif_cb_timer_stop(fw_controller, timer);
}
Example #17
0
void * scic_cb_timer_create(
   SCI_CONTROLLER_HANDLE_T   controller,
   SCI_TIMER_CALLBACK_T      timer_callback,
   void                    * cookie
)
{
   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
                                         sci_object_get_association(controller);

   return scif_cb_timer_create(fw_controller, timer_callback, cookie);
}
Example #18
0
void scic_cb_timer_start(
   SCI_CONTROLLER_HANDLE_T   controller,
   void                    * timer,
   U32                       milliseconds
)
{
   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
                                         sci_object_get_association(controller);

   scif_cb_timer_start(fw_controller, timer, milliseconds);
}
Example #19
0
void
isci_io_request_timeout(void *arg)
{
	struct ISCI_IO_REQUEST *request = (struct ISCI_IO_REQUEST *)arg;
	struct ISCI_REMOTE_DEVICE *remote_device = (struct ISCI_REMOTE_DEVICE *)
		sci_object_get_association(request->parent.remote_device_handle);
	struct ISCI_CONTROLLER *controller = remote_device->domain->controller;

	mtx_lock(&controller->lock);
	isci_remote_device_reset(remote_device, NULL);
	mtx_unlock(&controller->lock);
}
Example #20
0
/**
 * @brief This callback method asks the user to destory the supplied timer.
 *
 * @param[in]  controller This parameter specifies the controller with
 *             which this timer is to associated.
 * @param[in]  timer This parameter specifies the timer to be destroyed.
 *
 * @return none
 */
void
scif_cb_timer_destroy(SCI_CONTROLLER_HANDLE_T scif_controller,
                      void *timer_handle)
{
    struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
            sci_object_get_association(scif_controller);

    scif_cb_timer_stop(scif_controller, timer_handle);
    sci_pool_put(isci_controller->timer_pool, (struct ISCI_TIMER *)timer_handle);

    isci_log_message(3, "TIMER", "destroy %p\n", timer_handle);
}
Example #21
0
/**
 * @brief This user callback will inform the user that an IO request has
 *        completed.
 *
 * @param[in]  controller This parameter specifies the controller on
 *             which the IO request is completing.
 * @param[in]  remote_device This parameter specifies the remote device on
 *             which this request is completing.
 * @param[in]  io_request This parameter specifies the IO request that has
 *             completed.
 * @param[in]  completion_status This parameter specifies the results of
 *             the IO request operation.  SCI_IO_SUCCESS indicates
 *             successful completion.
 *
 * @return none
 */
void
scif_cb_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
    SCI_IO_REQUEST_HANDLE_T io_request, SCI_IO_STATUS completion_status)
{
	struct ISCI_IO_REQUEST *isci_request =
	    (struct ISCI_IO_REQUEST *)sci_object_get_association(io_request);

	scif_controller_complete_io(scif_controller, remote_device, io_request);
	isci_io_request_complete(scif_controller, remote_device, isci_request,
	    completion_status);
}
Example #22
0
/**
 * @brief This callback method asks the user to provide the physical
 *        address for the supplied virtual address when building an
 *        io request object.
 *
 * @param[in] controller This parameter is the core controller object
 *            handle.
 * @param[in] io_request This parameter is the io request object handle
 *            for which the physical address is being requested.
 * @param[in] virtual_address This paramter is the virtual address which
 *            is to be returned as a physical address.
 * @param[out] physical_address The physical address for the supplied virtual
 *             address.
 *
 * @return None.
 */
void
scic_cb_io_request_get_physical_address(SCI_CONTROLLER_HANDLE_T	controller,
    SCI_IO_REQUEST_HANDLE_T io_request, void *virtual_address,
    SCI_PHYSICAL_ADDRESS *physical_address)
{
	SCI_IO_REQUEST_HANDLE_T scif_request =
	    sci_object_get_association(io_request);
	struct ISCI_REQUEST *isci_request =
	    sci_object_get_association(scif_request);

	if(isci_request != NULL) {
		/* isci_request is not NULL, meaning this is a request initiated
		 *  by CAM or the isci layer (i.e. device reset for I/O
		 *  timeout).  Therefore we can calculate the physical address
		 *  based on the address we stored in the struct ISCI_REQUEST
		 *  object.
		 */
		*physical_address = isci_request->physical_address +
		    (uintptr_t)virtual_address -
		    (uintptr_t)isci_request;
	} else {
		/* isci_request is NULL, meaning this is a request generated
		 *  internally by SCIL (i.e. for SMP requests or NCQ error
		 *  recovery).  Therefore we calculate the physical address
		 *  based on the controller's uncached controller memory buffer,
		 *  since we know that this is what SCIL uses for internal
		 *  framework requests.
		 */
		SCI_CONTROLLER_HANDLE_T scif_controller =
		    (SCI_CONTROLLER_HANDLE_T) sci_object_get_association(controller);
		struct ISCI_CONTROLLER *isci_controller =
		    (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
		U64 virt_addr_offset = (uintptr_t)virtual_address -
		    (U64)isci_controller->uncached_controller_memory.virtual_address;

		*physical_address =
		    isci_controller->uncached_controller_memory.physical_address
		    + virt_addr_offset;
	}
}
Example #23
0
void scic_cb_port_bc_aen_primitive_recieved(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port,
   SCI_PHY_HANDLE_T         phy
)
{
   SCIF_LOG_TRACE((
      sci_base_object_get_logger(sci_object_get_association(port)),
      SCIF_LOG_OBJECT_DOMAIN,
      "scic_cb_port_bc_aen_primitive_received(0x%x, 0x%x, 0x%x) enter\n",
      controller, port, phy
   ));
}
Example #24
0
void scic_cb_timer_destroy(
   SCI_CONTROLLER_HANDLE_T   controller,
   void                    * timer
)
{
   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T *)
                                         sci_object_get_association(controller);
   if (timer != NULL)
   {
      scif_cb_timer_destroy(fw_controller, timer);
      timer = NULL;
   }
}
Example #25
0
void scic_cb_port_stop_complete(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port,
   SCI_STATUS               completion_status
)
{
   SCIF_LOG_TRACE((
      sci_base_object_get_logger((SCIF_SAS_DOMAIN_T*)sci_object_get_association(port)),
      SCIF_LOG_OBJECT_DOMAIN,
      "scic_cb_port_stop_complete(0x%x, 0x%x, 0x%x) enter\n",
      controller, port, completion_status
   ));
}
Example #26
0
void scic_cb_port_ready(
   SCI_CONTROLLER_HANDLE_T  controller,
   SCI_PORT_HANDLE_T        port
)
{
   SCIF_SAS_DOMAIN_T * fw_domain = (SCIF_SAS_DOMAIN_T*)
                                   sci_object_get_association(port);

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_domain),
      SCIF_LOG_OBJECT_DOMAIN,
      "scic_cb_port_ready(0x%x, 0x%x) enter\n",
      controller, port
   ));

   // The controller supplied with the port should match the controller
   // saved in the domain.
   ASSERT(sci_object_get_association(controller) == fw_domain->controller);

   fw_domain->is_port_ready = TRUE;

   fw_domain->state_handlers->port_ready_handler(&fw_domain->parent);
}
Example #27
0
/**
 * @brief This method will be invoked to allocate memory dynamically.
 *
 * @param[in]  controller This parameter represents the controller
 *             object for which to allocate memory.
 * @param[out] mde This parameter represents the memory descriptor to
 *             be filled in by the user that will reference the newly
 *             allocated memory.
 *
 * @return none
 */
void scif_cb_controller_free_memory(SCI_CONTROLLER_HANDLE_T controller,
    SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde)
{
	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
	    sci_object_get_association(controller);

	/*
	 * Put the buffer back into the controller's buffer pool, rather
	 * than invoking configfree.  This helps reduce chance we won't
	 * have buffers available when system is under memory pressure.
	 */ 
	sci_pool_put(isci_controller->unmap_buffer_pool,
	    mde->virtual_address);
}
Example #28
0
/**
 * @brief This callback method informs the framework user that the remote
 *        device is ready and capable of processing IO requests.
 *
 * @param[in]  controller This parameter specifies the controller object
 *             with which this callback is associated.
 * @param[in]  domain This parameter specifies the domain object with
 *             which this callback is associated.
 * @param[in]  remote_device This parameter specifies the device object with
 *             which this callback is associated.
 *
 * @return none
 */
void
scif_cb_remote_device_ready(SCI_CONTROLLER_HANDLE_T controller,
    SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
{
	struct ISCI_REMOTE_DEVICE *isci_remote_device =
	    sci_object_get_association(remote_device);
	struct ISCI_CONTROLLER *isci_controller =
	    sci_object_get_association(controller);
	uint32_t device_index = isci_remote_device->index;

	if (isci_controller->remote_device[device_index] == NULL) {
		/* This new device is now ready, so put it in the controller's
		 *  remote device list so it is visible to CAM.
		 */
		isci_controller->remote_device[device_index] =
		    isci_remote_device;

		if (isci_controller->has_been_scanned) {
			/* The sim object has been scanned at least once
			 *  already.  In that case, create a CCB to instruct
			 *  CAM to rescan this device.
			 * If the sim object has not been scanned, this device
			 *  will get scanned as part of the initial scan.
			 */
			union ccb *ccb = xpt_alloc_ccb_nowait();

			xpt_create_path(&ccb->ccb_h.path, NULL,
			    cam_sim_path(isci_controller->sim),
			    isci_remote_device->index, CAM_LUN_WILDCARD);

			xpt_rescan(ccb);
		}
	}

	isci_remote_device_release_device_queue(isci_remote_device);
}
Example #29
0
/**
 * @brief This callback method asks the user to create a timer and provide
 *        a handle for this timer for use in further timer interactions.
 *
 * @warning The "timer_callback" method should be executed in a mutually
 *          exlusive manner from the controller completion handler
 *          handler (refer to scic_controller_get_handler_methods()).
 *
 * @param[in]  timer_callback This parameter specifies the callback method
 *             to be invoked whenever the timer expires.
 * @param[in]  controller This parameter specifies the controller with
 *             which this timer is to be associated.
 * @param[in]  cookie This parameter specifies a piece of information that
 *             the user must retain.  This cookie is to be supplied by the
 *             user anytime a timeout occurs for the created timer.
 *
 * @return This method returns a handle to a timer object created by the
 *         user.  The handle will be utilized for all further interactions
 *         relating to this timer.
 */
void *
scif_cb_timer_create(SCI_CONTROLLER_HANDLE_T scif_controller,
                     SCI_TIMER_CALLBACK_T timer_callback, void *cookie)
{
    struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
            sci_object_get_association(scif_controller);
    struct ISCI_TIMER *timer;

    sci_pool_get(isci_controller->timer_pool, timer);

    callout_init_mtx(&timer->callout, &isci_controller->lock, FALSE);

    timer->callback = timer_callback;
    timer->cookie = cookie;
    timer->is_started = FALSE;

    isci_log_message(3, "TIMER", "create %p %p %p\n", timer, timer_callback, cookie);

    return (timer);
}
Example #30
0
/**
 * @brief This method continues a scif sas request.
 *
 * @param[in] fw_controller The framework controller
 * @param[in] fw_device The device that the IO request targets to.
 * @param[in] fw_request The IO request to be continued.
 *
 * @return Indicate if the internal io was successfully constructed.
 * @retval SCI_SUCCESS This value is returned if the internal io was
 *         successfully continued.
 * @retval SCI_FAILURE This value is returned if the io was failed to
 *         be continued.
 */
SCI_STATUS scif_sas_io_request_continue(
   SCIF_SAS_CONTROLLER_T       * fw_controller,
   SCIF_SAS_REMOTE_DEVICE_T    * fw_device,
   SCIF_SAS_REQUEST_T          * fw_request
)
{
   SCI_IO_REQUEST_HANDLE_T dummy_handle;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_request),
      SCIF_LOG_OBJECT_IO_REQUEST,
      "scif_sas_io_request_continue(0x%x, 0x%x, 0x%x) enter\n",
      fw_controller,
      fw_device,
      fw_request
   ));

   //complete this io request in framework and core.
   scif_controller_complete_io(fw_controller, fw_device, fw_request);

   //construct next command in the sequence using the same memory. We pass
   //a dummy pointer to let the framework user keep the pointer to this IO
   //request untouched.
   scif_sas_io_request_construct(
      fw_device,
      (SCIF_SAS_IO_REQUEST_T*)fw_request,
      SCI_CONTROLLER_INVALID_IO_TAG,
      (void *)sci_object_get_association(fw_request),
      &dummy_handle,
      FALSE
   );

   //start the new constructed IO.
   return (SCI_STATUS)scif_controller_start_io(
             (SCI_CONTROLLER_HANDLE_T) fw_controller,
             (SCI_REMOTE_DEVICE_HANDLE_T) fw_device,
             (SCI_IO_REQUEST_HANDLE_T) fw_request,
             SCI_CONTROLLER_INVALID_IO_TAG
          );
}