/* Below are a series of functions for sending a drive info request * to the adapter. The flow order is: get, send, callback. It uses * the generic finish callback at the top of this file. * This can be used to get drive status info from the card */ static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) { ips_softc_t *sc; ips_command_t *command = cmdptr; ips_drive_cmd *command_struct; ips_drive_info_t *driveinfo; sc = command->sc; if(error){ ips_set_error(command, error); printf("ips: error = %d in ips_get_drive_info\n", error); return; } command_struct = (ips_drive_cmd *)command->command_buffer; command_struct->command = IPS_DRIVE_INFO_CMD; command_struct->id = command->id; command_struct->buffaddr = segments[0].ds_addr; bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_PREREAD); sc->ips_issue_cmd(command); if (sema_timedwait(&sc->cmd_sema, 10*hz) != 0) { ips_set_error(command, ETIMEDOUT); return; } bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTREAD); driveinfo = command->data_buffer; memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8); sc->drivecount = driveinfo->drivecount; device_printf(sc->dev, "logical drives: %d\n",sc->drivecount); }
static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) { ips_softc_t *sc; ips_command_t *command = cmdptr; ips_rw_nvram_cmd *command_struct; sc = command->sc; if(error){ ips_set_error(command, error); printf("ips: error = %d in ips_read_nvram_callback\n", error); return; } command_struct = (ips_rw_nvram_cmd *)command->command_buffer; command_struct->command = IPS_RW_NVRAM_CMD; command_struct->id = command->id; command_struct->pagenum = 5; command_struct->rw = 0; command_struct->buffaddr = segments[0].ds_addr; bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_PREREAD); sc->ips_issue_cmd(command); if (sema_timedwait(&sc->cmd_sema, 30*hz) != 0) { ips_set_error(command, ETIMEDOUT); return; } bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTWRITE); }
/* Below are a series of functions for sending an adapter info request * to the adapter. The flow order is: get, send, callback. It uses * the generic finish callback at the top of this file. * This can be used to get configuration/status info from the card */ static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) { ips_softc_t *sc; ips_command_t *command = cmdptr; ips_adapter_info_cmd *command_struct; sc = command->sc; if(error){ ips_set_error(command, error); printf("ips: error = %d in ips_get_adapter_info\n", error); return; } command_struct = (ips_adapter_info_cmd *)command->command_buffer; command_struct->command = IPS_ADAPTER_INFO_CMD; command_struct->id = command->id; command_struct->buffaddr = segments[0].ds_addr; bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_PREREAD); sc->ips_issue_cmd(command); if (sema_timedwait(&sc->cmd_sema, 30*hz) != 0) { ips_set_error(command, ETIMEDOUT); return; } bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTREAD); memcpy(&(sc->adapter_info), command->data_buffer, IPS_ADAPTER_INFO_LEN); }
/* * RNDIS filter set packet filter * Sends an rndis request with the new filter, then waits for a response * from the host. * Returns zero on success, non-zero on failure. */ static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter) { rndis_request *request; rndis_set_request *set; rndis_set_complete *set_complete; uint32_t status; int ret; request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG, RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t)); if (request == NULL) { ret = -1; goto cleanup; } /* Set up the rndis set */ set = &request->request_msg.msg.set_request; set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER; set->info_buffer_length = sizeof(uint32_t); set->info_buffer_offset = sizeof(rndis_set_request); memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)), &new_filter, sizeof(uint32_t)); ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG); if (ret != 0) { goto cleanup; } /* * Wait for the response from the host. Another thread will signal * us when the response has arrived. In the failure case, * sema_timedwait() returns a non-zero status after waiting 5 seconds. */ ret = sema_timedwait(&request->wait_sema, 500); if (ret == 0) { /* Response received, check status */ set_complete = &request->response_msg.msg.set_complete; status = set_complete->status; if (status != RNDIS_STATUS_SUCCESS) { /* Bad response status, return error */ ret = -2; } } else { /* * We cannot deallocate the request since we may still * receive a send completion for it. */ goto exit; } cleanup: if (request != NULL) { hv_put_rndis_request(device, request); } exit: return (ret); }
int sem_timedwait(sem_t *sem, const timespec_t *abstime) { int error; if (sem_invalid(sem)) return (-1); if ((error = sema_timedwait((sema_t *)sem, abstime)) != 0) { if (error == ETIME) error = ETIMEDOUT; errno = error; return (-1); } return (0); }