int ips_clear_adapter(ips_softc_t *sc) { ips_cmd_status_t *status; status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); if(!status) return ENOMEM; device_printf(sc->dev, "syncing config\n"); if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status, IPS_NOWAIT_FLAG)){ free(status, M_IPSBUF); device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); return 1; } if(COMMAND_ERROR(status)){ free(status, M_IPSBUF); device_printf(sc->dev, "ERROR: cache sync command failed!\n"); return 1; } device_printf(sc->dev, "clearing error table\n"); if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status, IPS_NOWAIT_FLAG)){ free(status, M_IPSBUF); device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); return 1; } if(COMMAND_ERROR(status)){ device_printf(sc->dev, "ERROR: etable command failed!\n"); free(status, M_IPSBUF); return 1; } free(status, M_IPSBUF); return 0; }
int ips_clear_adapter(ips_softc_t *sc) { ips_command_t *command; device_printf(sc->dev, "syncing config\n"); if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); return 1; } ips_send_config_sync_cmd(command); if(COMMAND_ERROR(command)){ device_printf(sc->dev, "ERROR: cache sync command failed!\n"); return 1; } device_printf(sc->dev, "clearing error table\n"); if(ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); return 1; } ips_send_error_table_cmd(command); if(COMMAND_ERROR(command)){ device_printf(sc->dev, "ERROR: etable command failed!\n"); return 1; } return 0; }
static int ips_ioctl_cmd(ips_softc_t *sc, ips_ioctl_t *ioctl_cmd, ips_user_request *user_request) { ips_command_t *command; int error = EINVAL; if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, /* alignment */ 1, /* boundary */ 0, /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, /* highaddr */ BUS_SPACE_MAXADDR, /* filter */ NULL, /* filterarg */ NULL, /* maxsize */ ioctl_cmd->datasize, /* numsegs */ 1, /* maxsegsize*/ ioctl_cmd->datasize, /* flags */ 0, /* lockfunc */ NULL, /* lockarg */ NULL, &ioctl_cmd->dmatag) != 0) { return ENOMEM; } if(bus_dmamem_alloc(ioctl_cmd->dmatag, &ioctl_cmd->data_buffer, 0, &ioctl_cmd->dmamap)){ error = ENOMEM; goto exit; } if(copyin(user_request->data_buffer,ioctl_cmd->data_buffer, ioctl_cmd->datasize)) goto exit; ioctl_cmd->status.value = 0xffffffff; mtx_lock(&sc->queue_mtx); if((error = ips_get_free_cmd(sc, &command, 0)) > 0){ error = ENOMEM; mtx_unlock(&sc->queue_mtx); goto exit; } command->arg = ioctl_cmd; ips_ioctl_start(command); while( ioctl_cmd->status.value == 0xffffffff) msleep(ioctl_cmd, &sc->queue_mtx, 0, "ips", hz/10); if(COMMAND_ERROR(ioctl_cmd)) error = EIO; else error = 0; mtx_unlock(&sc->queue_mtx); if(copyout(ioctl_cmd->data_buffer, user_request->data_buffer, ioctl_cmd->datasize)) error = EINVAL; mtx_lock(&sc->queue_mtx); ips_insert_free_cmd(sc, command); mtx_unlock(&sc->queue_mtx); exit: bus_dmamem_free(ioctl_cmd->dmatag, ioctl_cmd->data_buffer, ioctl_cmd->dmamap); bus_dma_tag_destroy(ioctl_cmd->dmatag); return error; }
static void ipsd_dump_block_complete(ips_command_t *command) { if (COMMAND_ERROR(&command->status)) { kprintf("ipsd_dump completion error= 0x%x\n", command->status.value); } bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(command->data_dmatag, command->data_dmamap); }
static int ipsd_dump(struct dev_dump_args *ap) { cdev_t dev = ap->a_head.a_dev; ips_softc_t *sc; ips_command_t *command; ips_io_cmd *command_struct; ipsdisk_softc_t *dsc; off_t off; uint8_t *va; size_t len; int error = 0; dsc = dev->si_drv1; if (dsc == NULL) return (EINVAL); sc = dsc->sc; if (ips_get_free_cmd(sc, &command, 0) != 0) { kprintf("ipsd: failed to get cmd for dump\n"); return (ENOMEM); } command->data_dmatag = sc->sg_dmatag; command->callback = ipsd_dump_block_complete; command_struct = (ips_io_cmd *)command->command_buffer; command_struct->id = command->id; command_struct->drivenum = sc->drives[dsc->disk_number].drivenum; off = ap->a_offset; va = ap->a_virtual; size_t length = ap->a_length; while (length > 0) { len = length > IPS_MAX_IO_SIZE ? IPS_MAX_IO_SIZE : length; command_struct->lba = off / IPS_BLKSIZE; if (bus_dmamap_load(command->data_dmatag, command->data_dmamap, va, len, ipsd_dump_map_sg, command, 0) != 0) { error = EIO; break; } if (COMMAND_ERROR(&command->status)) { error = EIO; break; } length -= len; off += len; va += len; } ips_insert_free_cmd(command->sc, command); return(error); }
int ips_ffdc_reset(ips_softc_t *sc) { ips_command_t *command; if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't send ffdc reset!\n"); } ips_send_ffdc_reset_cmd(command); if(COMMAND_ERROR(command)){ device_printf(sc->dev, "ERROR: ffdc reset command failed!\n"); } return 0; }
int ips_flush_cache(ips_softc_t *sc) { ips_command_t *command; device_printf(sc->dev, "flushing cache\n"); if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n"); } ips_send_flush_cache_cmd(command); if(COMMAND_ERROR(command)){ device_printf(sc->dev, "ERROR: cache flush command failed!\n"); } return 0; }
int ips_get_drive_info(ips_softc_t *sc) { int error = 0; ips_command_t *command; if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) > 0){ device_printf(sc->dev, "unable to get drive configuration\n"); return ENXIO; } ips_send_drive_info_cmd(command); if(COMMAND_ERROR(command)){ error = ENXIO; } return error; }
int ips_update_nvram(ips_softc_t *sc) { ips_command_t *command; if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n"); return 1; } ips_read_nvram(command); if(COMMAND_ERROR(command)){ device_printf(sc->dev, "ERROR: nvram update command failed!\n"); } return 0; }
int ips_ffdc_reset(ips_softc_t *sc) { ips_cmd_status_t *status; status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); if(!status) return ENOMEM; if(ips_get_free_cmd(sc, ips_send_ffdc_reset_cmd, status, IPS_NOWAIT_FLAG)){ free(status, M_IPSBUF); device_printf(sc->dev, "ERROR: unable to get a command! can't send ffdc reset!\n"); } if(COMMAND_ERROR(status)){ device_printf(sc->dev, "ERROR: ffdc reset command failed!\n"); } free(status, M_IPSBUF); return 0; }
/* Below is a pair of functions for making sure data is safely * on disk by flushing the adapter's cache. */ static int ips_send_flush_cache_cmd(ips_command_t *command) { ips_softc_t *sc = command->sc; ips_generic_cmd *command_struct; PRINTF(10,"ips test: got a command, building flush command\n"); command->callback = ips_wakeup_callback; command_struct = (ips_generic_cmd *)command->command_buffer; command_struct->command = IPS_CACHE_FLUSH_CMD; command_struct->id = command->id; bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); sc->ips_issue_cmd(command); if (COMMAND_ERROR(command) == 0) sema_wait(&sc->cmd_sema); ips_insert_free_cmd(sc, command); return 0; }
int ips_update_nvram(ips_softc_t *sc) { ips_cmd_status_t *status; status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); if(!status) return ENOMEM; if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){ free(status, M_IPSBUF); device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n"); return 1; } if(COMMAND_ERROR(status)){ device_printf(sc->dev, "ERROR: nvram update command failed!\n"); } free(status, M_IPSBUF); return 0; }
int ips_get_drive_info(ips_softc_t *sc) { int error = 0; ips_cmd_status_t *status; status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_NOWAIT|M_ZERO); if(!status) return ENOMEM; if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status, IPS_NOWAIT_FLAG) > 0){ free(status, M_IPSBUF); device_printf(sc->dev, "unable to get drive configuration\n"); return ENXIO; } if(COMMAND_ERROR(status)){ error = ENXIO; } free(status, M_IPSBUF); return error; }
/* Below are a series of functions for sending an IO request * to the adapter. The flow order is: start, send, callback, finish. * The caller must have already assembled an iorequest struct to hold * the details of the IO request. */ static void ips_io_request_finish(ips_command_t *command) { struct buf *iobuf = command->arg; if(ips_read_request(iobuf)) { bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTREAD); } else { bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTWRITE); } bus_dmamap_unload(command->data_dmatag, command->data_dmamap); bus_dmamap_destroy(command->data_dmatag, command->data_dmamap); if(COMMAND_ERROR(&command->status)){ iobuf->b_flags |=B_ERROR; iobuf->b_error = EIO; } ips_insert_free_cmd(command->sc, command); ipsd_finish(iobuf); }
/* Below are a series of functions for sending an IO request * to the adapter. The flow order is: start, send, callback, finish. * The caller must have already assembled an iorequest struct to hold * the details of the IO request. */ static void ips_io_request_finish(ips_command_t *command) { struct bio *iobuf = command->arg; if(ips_read_request(iobuf)) { bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTREAD); } else { bus_dmamap_sync(command->data_dmatag, command->data_dmamap, BUS_DMASYNC_POSTWRITE); } bus_dmamap_unload(command->data_dmatag, command->data_dmamap); if(COMMAND_ERROR(command)){ iobuf->bio_flags |=BIO_ERROR; iobuf->bio_error = EIO; printf("ips: io error, status= 0x%x\n", command->status.value); } ips_insert_free_cmd(command->sc, command); ipsd_finish(iobuf); }
static int ips_send_ffdc_reset_cmd(ips_command_t *command) { ips_softc_t *sc = command->sc; ips_adapter_ffdc_cmd *command_struct; PRINTF(10,"ips test: got a command, building ffdc reset command\n"); command->callback = ips_wakeup_callback; command_struct = (ips_adapter_ffdc_cmd *)command->command_buffer; command_struct->command = IPS_FFDC_CMD; command_struct->id = command->id; command_struct->reset_count = sc->ffdc_resetcount; command_struct->reset_type = 0x0; ips_ffdc_settime(command_struct, sc->ffdc_resettime.tv_sec); bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, BUS_DMASYNC_PREWRITE); sc->ips_issue_cmd(command); if (COMMAND_ERROR(command) == 0) sema_wait(&sc->cmd_sema); ips_insert_free_cmd(sc, command); return 0; }