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 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);
}
/* 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);
}
Beispiel #4
0
void ips_issue_morpheus_cmd(ips_command_t *command)
{
	/* hmmm, is there a cleaner way to do this? */
	if(command->sc->state & IPS_OFFLINE){
		ips_set_error(command, EINVAL);
		command->callback(command);
		return;
	}
	command->timeout = 10;
	ips_write_4(command->sc, MORPHEUS_REG_IQPR, command->command_phys_addr);
}
Beispiel #5
0
void ips_issue_copperhead_cmd(ips_command_t *command)
{
	int i;
	/* hmmm, is there a cleaner way to do this? */
	if(command->sc->state & IPS_OFFLINE){
		ips_set_error(command, EINVAL);
		command->callback(command);
		return;
	}
	command->timeout = 10;
	for(i = 0; ips_read_4(command->sc, COPPER_REG_CCCR) & COPPER_SEM_BIT;
	    i++ ){
		if( i == 20){
printf("sem bit still set, can't send a command\n");
			return;
		}
		DELAY(500);/* need to do a delay here */
	}
	ips_write_4(command->sc, COPPER_REG_CCSAR, command->command_phys_addr);
	ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
}
Beispiel #6
0
static void ips_ioctl_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error)
{
	ips_command_t *command = cmdptr;
	ips_ioctl_t *ioctl_cmd = command->arg;
	ips_generic_cmd *command_buffer = command->command_buffer;
	if(error){
		ips_set_error(command, error);
		return;
	}
	command_buffer->id = command->id;
	command_buffer->buffaddr = segments[0].ds_addr;
	if(ioctl_cmd->readwrite & IPS_IOCTL_WRITE){
		bus_dmamap_sync(ioctl_cmd->dmatag, ioctl_cmd->dmamap, 
				BUS_DMASYNC_PREWRITE);
	} else if(ioctl_cmd->readwrite & IPS_IOCTL_READ){
		bus_dmamap_sync(ioctl_cmd->dmatag, ioctl_cmd->dmamap, 
				BUS_DMASYNC_PREREAD);
	}
	bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap, 
			BUS_DMASYNC_PREWRITE);
	command->sc->ips_issue_cmd(command);
}
Beispiel #7
0
/* ips_timeout is periodically called to make sure no commands sent
 * to the card have become stuck.  If it finds a stuck command, it
 * sets a flag so the driver won't start any more commands and then
 * is periodically called to see if all outstanding commands have
 * either finished or timed out.  Once timed out, an attempt to
 * reinitialize the card is made.  If that fails, the driver gives
 * up and declares the card dead. */
static void ips_timeout(void *arg)
{
	ips_softc_t *sc = arg;
	int i, state = 0;
	ips_command_t *command;

	mtx_lock(&sc->queue_mtx);
	command = &sc->commandarray[0];
	for(i = 0; i < sc->max_cmds; i++){
		if(!command[i].timeout){
			continue;
		}
		command[i].timeout--;
		if(!command[i].timeout){
			if(!(sc->state & IPS_TIMEOUT)){
				sc->state |= IPS_TIMEOUT;
				device_printf(sc->dev, "WARNING: command timeout. Adapter is in toaster mode, resetting to known state\n");
			}
			ips_set_error(&command[i], ETIMEDOUT);
			command[i].callback(&command[i]);
			/* hmm, this should be enough cleanup */
		} else
			state = 1;
	}
	if(!state && (sc->state & IPS_TIMEOUT)){
		if(sc->ips_adapter_reinit(sc, 1)){
			device_printf(sc->dev, "AIEE! adapter reset failed, giving up and going home! Have a nice day.\n");
			sc->state |= IPS_OFFLINE;
			sc->state &= ~IPS_TIMEOUT;
			/* Grr, I hate this solution. I run waiting commands
			   one at a time and error them out just before they 
			   would go to the card. This sucks. */
		} else
			sc->state &= ~IPS_TIMEOUT;
	}
	if (sc->state != IPS_OFFLINE)
		sc->timer = timeout(ips_timeout, sc, 10*hz);
	mtx_unlock(&sc->queue_mtx);
}