⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 3w-xxxx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {		response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));		request_id = TW_RESID_OUT(response_queue.response_id);		if (request_id != 0) {			/* unexpected request id */			printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n");			return 1;		}		if (command_packet->status != 0) {			/* bad response */			tw_decode_sense(tw_dev, request_id, 0);			return 1;		}	}	return 0;} /* End tw_initconnection() *//* Set a value in the features table */static int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,                  unsigned char *val){	TW_Param *param;	TW_Command  *command_packet;	TW_Response_Queue response_queue;	int request_id = 0;	unsigned long command_que_value;	unsigned long param_value;  	/* Initialize SetParam command packet */	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet virtual address.\n");		return 1;	}	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	memset(command_packet, 0, sizeof(TW_Sector));	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);	param->table_id = 0x404;  /* Features table */	param->parameter_id = parm;	param->parameter_size_bytes = param_size;	memcpy(param->data, val, param_size);	param_value = tw_dev->alignment_physical_address[request_id];	if (param_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad alignment physical address.\n");		tw_dev->state[request_id] = TW_S_COMPLETED;		tw_state_request_finish(tw_dev, request_id);		tw_dev->srb[request_id]->result = (DID_OK << 16);		tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);	}	command_packet->byte8.param.sgl[0].address = param_value;	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);	command_packet->size = 4;	command_packet->request_id = request_id;	command_packet->byte6.parameter_count = 1;  	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet physical address.\n");	return 1;	}	/* Send command packet to the board */	outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));	/* Poll for completion */	if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {		response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));		request_id = TW_RESID_OUT(response_queue.response_id);		if (request_id != 0) {			/* unexpected request id */			printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected request id.\n");			return 1;		}		if (command_packet->status != 0) {			/* bad response */			tw_decode_sense(tw_dev, request_id, 0);			return 1;		}	}	return 0;} /* End tw_setfeature() *//* This function will reset a controller */static int tw_reset_sequence(TW_Device_Extension *tw_dev) {	int error = 0;	int tries = 0;	unsigned char c = 1;	/* Reset the board */	while (tries < TW_MAX_RESET_TRIES) {		TW_SOFT_RESET(tw_dev);		error = tw_aen_drain_queue(tw_dev);		if (error) {			printk(KERN_WARNING "3w-xxxx: scsi%d: AEN drain failed, retrying.\n", tw_dev->host->host_no);			tries++;			continue;		}		/* Check for controller errors */		if (tw_check_errors(tw_dev)) {			printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no);			tries++;			continue;		}		/* Now the controller is in a good state */		break;	}	if (tries >= TW_MAX_RESET_TRIES) {		printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no);		return 1;	}	error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);	if (error) {		printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no);		return 1;	}	error = tw_setfeature(tw_dev, 2, 1, &c);	if (error) {		printk(KERN_WARNING "3w-xxxx: Unable to set features for card, probable old firmware or card.\n");	}	return 0;} /* End tw_reset_sequence() *//* This function will initialize the fields of a device extension */static int tw_initialize_device_extension(TW_Device_Extension *tw_dev){	int i, error=0;	dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");	/* Initialize command packet buffers */	error = tw_allocate_memory(tw_dev, sizeof(TW_Command), 0);	if (error) {		printk(KERN_WARNING "3w-xxxx: Command packet memory allocation failed.\n");		return 1;	}	/* Initialize generic buffer */	error = tw_allocate_memory(tw_dev, sizeof(TW_Sector), 1);	if (error) {		printk(KERN_WARNING "3w-xxxx: Generic memory allocation failed.\n");		return 1;	}	for (i=0;i<TW_Q_LENGTH;i++) {		tw_dev->free_queue[i] = i;		tw_dev->state[i] = TW_S_INITIAL;	}	tw_dev->pending_head = TW_Q_START;	tw_dev->pending_tail = TW_Q_START;	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;	mutex_init(&tw_dev->ioctl_lock);	init_waitqueue_head(&tw_dev->ioctl_wqueue);	return 0;} /* End tw_initialize_device_extension() */static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd){	int use_sg;	dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");	use_sg = scsi_dma_map(cmd);	if (use_sg < 0) {		printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");		return 0;	}	cmd->SCp.phase = TW_PHASE_SGLIST;	cmd->SCp.have_data_in = use_sg;	return use_sg;} /* End tw_map_scsi_sg_data() */static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd){	dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");	scsi_dma_unmap(cmd);} /* End tw_unmap_scsi_data() *//* This function will reset a device extension */static int tw_reset_device_extension(TW_Device_Extension *tw_dev){	int i = 0;	struct scsi_cmnd *srb;	unsigned long flags = 0;	dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");	set_bit(TW_IN_RESET, &tw_dev->flags);	TW_DISABLE_INTERRUPTS(tw_dev);	TW_MASK_COMMAND_INTERRUPT(tw_dev);	spin_lock_irqsave(tw_dev->host->host_lock, flags);	/* Abort all requests that are in progress */	for (i=0;i<TW_Q_LENGTH;i++) {		if ((tw_dev->state[i] != TW_S_FINISHED) && 		    (tw_dev->state[i] != TW_S_INITIAL) &&		    (tw_dev->state[i] != TW_S_COMPLETED)) {			srb = tw_dev->srb[i];			if (srb != NULL) {				srb->result = (DID_RESET << 16);				tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);				tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);			}		}	}	/* Reset queues and counts */	for (i=0;i<TW_Q_LENGTH;i++) {		tw_dev->free_queue[i] = i;		tw_dev->state[i] = TW_S_INITIAL;	}	tw_dev->free_head = TW_Q_START;	tw_dev->free_tail = TW_Q_START;	tw_dev->posted_request_count = 0;	tw_dev->pending_request_count = 0;	tw_dev->pending_head = TW_Q_START;	tw_dev->pending_tail = TW_Q_START;	tw_dev->reset_print = 0;	spin_unlock_irqrestore(tw_dev->host->host_lock, flags);	if (tw_reset_sequence(tw_dev)) {		printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);		return 1;	}	TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);	clear_bit(TW_IN_RESET, &tw_dev->flags);	tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;	return 0;} /* End tw_reset_device_extension() *//* This funciton returns unit geometry in cylinders/heads/sectors */static int tw_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev,		sector_t capacity, int geom[]) {	int heads, sectors, cylinders;	TW_Device_Extension *tw_dev;		dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n");	tw_dev = (TW_Device_Extension *)sdev->host->hostdata;	heads = 64;	sectors = 32;	cylinders = sector_div(capacity, heads * sectors);	if (capacity >= 0x200000) {		heads = 255;		sectors = 63;		cylinders = sector_div(capacity, heads * sectors);	}	dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders);	geom[0] = heads;			 	geom[1] = sectors;	geom[2] = cylinders;	return 0;} /* End tw_scsi_biosparam() *//* This is the new scsi eh reset function */static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt) {	TW_Device_Extension *tw_dev=NULL;	int retval = FAILED;	tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;	tw_dev->num_resets++;	sdev_printk(KERN_WARNING, SCpnt->device,		"WARNING: Command (0x%x) timed out, resetting card.\n",		SCpnt->cmnd[0]);	/* Make sure we are not issuing an ioctl or resetting from ioctl */	mutex_lock(&tw_dev->ioctl_lock);	/* Now reset the card and some of the device extension data */	if (tw_reset_device_extension(tw_dev)) {		printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);		goto out;	}	retval = SUCCESS;out:	mutex_unlock(&tw_dev->ioctl_lock);	return retval;} /* End tw_scsi_eh_reset() *//* This function handles scsi inquiry commands */static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id){	TW_Param *param;	TW_Command *command_packet;	unsigned long command_que_value;	unsigned long param_value;	dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n");	/* Initialize command packet */	command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];	if (command_packet == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");		return 1;	}	memset(command_packet, 0, sizeof(TW_Sector));	command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);	command_packet->size = 4;	command_packet->request_id = request_id;	command_packet->status = 0;	command_packet->flags = 0;	command_packet->byte6.parameter_count = 1;	/* Now setup the param */	if (tw_dev->alignment_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n");		return 1;	}	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	memset(param, 0, sizeof(TW_Sector));	param->table_id = 3;	 /* unit summary table */	param->parameter_id = 3; /* unitsstatus parameter */	param->parameter_size_bytes = TW_MAX_UNITS;	param_value = tw_dev->alignment_physical_address[request_id];	if (param_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n");		return 1;	}	command_packet->byte8.param.sgl[0].address = param_value;	command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n");		return 1;	}	/* Now try to post the command packet */	tw_post_command_packet(tw_dev, request_id);	return 0;} /* End tw_scsiop_inquiry() */static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,				 void *data, unsigned int len){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -