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

📄 3w-xxxx.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
				}				if (tw_dev->state[request_id] != TW_S_POSTED) {					printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode);				}				error = 0;				dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);				/* Check for internal command */				if (tw_dev->srb[request_id] == 0) {					dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");					error = tw_aen_complete(tw_dev, request_id);					if (error) {						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error completing aen.\n");					}					status_reg_value = inl(status_reg_addr);					if (tw_check_bits(status_reg_value)) {						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");					}		} else {				switch (tw_dev->srb[request_id]->cmnd[0]) {					case READ_10:						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10\n");					case READ_6:						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_6\n");						break;					case WRITE_10:						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10\n");					case WRITE_6:						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_6\n");						break;					case INQUIRY:						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");						error = tw_scsiop_inquiry_complete(tw_dev, request_id);						break;					case READ_CAPACITY:						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");						error = tw_scsiop_read_capacity_complete(tw_dev, request_id);						break;					case TW_IOCTL:						dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TW_IOCTL\n");						error = tw_ioctl_complete(tw_dev, request_id);						break;					default:						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unknown scsi opcode: 0x%x.\n", tw_dev->srb[request_id]->cmnd[0]);						tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);						tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);					}					if (error) {						/* Tell scsi layer there was an error */						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Scsi Error.\n");						tw_dev->srb[request_id]->result = (DID_ERROR << 16);					} else {						/* Tell scsi layer command was a success */						tw_dev->srb[request_id]->result = (DID_OK << 16);					}					tw_dev->state[request_id] = TW_S_COMPLETED;					tw_state_request_finish(tw_dev, request_id);					tw_dev->posted_request_count--;					tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);					status_reg_value = inl(status_reg_addr);					if (tw_check_bits(status_reg_value)) {						printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");					}				}			}		}		spin_unlock_irqrestore(&tw_dev->tw_lock, flags2);	}	spin_unlock_irqrestore(&io_request_lock, flags);	clear_bit(TW_IN_INTR, &tw_dev->flags);}	/* End tw_interrupt() *//* This function handles ioctls from userspace to the driver */int tw_ioctl(TW_Device_Extension *tw_dev, int request_id){	unsigned char opcode;	int bufflen;	TW_Param *param;	TW_Command *command_packet;	u32 param_value;	TW_Ioctl *ioctl = NULL;	int tw_aen_code;	ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;	if (ioctl == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Request buffer NULL.\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]);		return 0;	}	bufflen = tw_dev->srb[request_id]->request_bufflen;	/* 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_ioctl(): Bad command packet virtual 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]);		return 0;	}	memset(command_packet, 0, sizeof(TW_Sector));	/* Initialize param */	if (tw_dev->alignment_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment virtual 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]);		return 0;	}	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	memset(param, 0, sizeof(TW_Sector));	dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id,, ioctl->parameter_size_bytes);	opcode = ioctl->opcode;	switch (opcode) {		case TW_OP_NOP:			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n");			command_packet->byte0.opcode = TW_OP_NOP;			break;		case TW_OP_GET_PARAM:			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");			command_packet->byte0.opcode = TW_OP_GET_PARAM;			param->table_id = ioctl->table_id;			param->parameter_id = ioctl->parameter_id;			param->parameter_size_bytes = ioctl->parameter_size_bytes;			tw_dev->ioctl_size[request_id] = ioctl->parameter_size_bytes;			dprintk(KERN_NOTICE "table_id = %d parameter_id = %d parameter_size_bytes %d\n", param->table_id, param->parameter_id, param->parameter_size_bytes);			break;		case TW_OP_SET_PARAM:			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n",			ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);			command_packet->byte0.opcode = TW_OP_SET_PARAM;			param->table_id = ioctl->table_id;			param->parameter_id = ioctl->parameter_id;			param->parameter_size_bytes = ioctl->parameter_size_bytes;			memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes);			break;		case TW_OP_AEN_LISTEN:			dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n");			if (tw_dev->aen_head == tw_dev->aen_tail) {				/* aen queue empty */				dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Aen queue empty.\n");				tw_aen_code = TW_AEN_QUEUE_EMPTY;				memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);			} else {				/* Copy aen queue entry to request buffer */				dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev->aen_queue[tw_dev->aen_head]);				tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];				memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);				if (tw_dev->aen_head == TW_Q_LENGTH - 1) {					tw_dev->aen_head = TW_Q_START;				} else {					tw_dev->aen_head = tw_dev->aen_head + 1;				}			}			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]);			return 0;	        case TW_CMD_PACKET:		  memcpy(command_packet, ioctl->data, sizeof(TW_Command));		  command_packet->request_id = request_id;		  tw_post_command_packet(tw_dev, request_id);		  return 0;		default:			printk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);			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]);			return 0;	}	param_value = tw_dev->alignment_physical_address[request_id];	if (param_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_ioctl(): 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->byte0.sgl_offset = 2;	command_packet->size = 4;	command_packet->request_id = request_id;	command_packet->byte3.unit = 0;	command_packet->byte3.host_id = 0;	command_packet->status = 0;	command_packet->flags = 0;	command_packet->byte6.parameter_count = 1;	/* Now try to post the command to the board */	tw_post_command_packet(tw_dev, request_id);	return 0;} /* End tw_ioctl() *//* This function is called by the isr to complete ioctl requests */int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id){	unsigned char *param_data;	unsigned char *buff;	TW_Param *param;	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");	buff = tw_dev->srb[request_id]->request_buffer;	if (buff == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n");		return 1;	}	dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);	memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);	param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];	if (param == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");		return 1;	}	param_data = &(param->data[0]);	memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);	return 0;} /* End tw_ioctl_complete() *//* This function will mask the command interrupt */void tw_mask_command_interrupt(TW_Device_Extension *tw_dev){	u32 control_reg_addr, control_reg_value;		control_reg_addr = tw_dev->registers.control_reg_addr;	control_reg_value = TW_CONTROL_MASK_COMMAND_INTERRUPT;	outl(control_reg_value, control_reg_addr);} /* End tw_mask_command_interrupt() *//* This function will poll the status register for a flag */int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds){	u32 status_reg_addr, status_reg_value;	struct timeval before, timeout;	status_reg_addr = tw_dev->registers.status_reg_addr;	do_gettimeofday(&before);	status_reg_value = inl(status_reg_addr);	while ((status_reg_value & flag) != flag) {		status_reg_value = inl(status_reg_addr);		do_gettimeofday(&timeout);		if (before.tv_sec + seconds < timeout.tv_sec) { 			printk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);			return 1;		}		mdelay(1);	}	return 0;} /* End tw_poll_status() *//* This function will attempt to post a command packet to the board */int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id){	u32 status_reg_addr, status_reg_value;	u32 command_que_addr, command_que_value;	dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n");	command_que_addr = tw_dev->registers.command_que_addr;	command_que_value = tw_dev->command_packet_physical_address[request_id];	status_reg_addr = tw_dev->registers.status_reg_addr;	status_reg_value = inl(status_reg_addr);	if (tw_check_bits(status_reg_value)) 		printk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");	if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {		/* We successfully posted the command packet */		outl(command_que_value, command_que_addr);		tw_dev->state[request_id] = TW_S_POSTED;		tw_dev->posted_request_count++;		if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {			tw_dev->max_posted_request_count = tw_dev->posted_request_count;		}	} else {		/* Couldn't post the command packet, so we do it in the isr */		if (tw_dev->state[request_id] != TW_S_PENDING) {			tw_dev->state[request_id] = TW_S_PENDING;			tw_dev->pending_request_count++;			if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) {				tw_dev->max_pending_request_count = tw_dev->pending_request_count;			}			tw_dev->pending_queue[tw_dev->pending_tail] = request_id;			if (tw_dev->pending_tail == TW_Q_LENGTH-1) {				tw_dev->pending_tail = TW_Q_START;			} else {				tw_dev->pending_tail = tw_dev->pending_tail + 1;			}		} 		tw_unmask_command_interrupt(tw_dev);		return 1;	}	return 0;} /* End tw_post_command_packet() *//* This function will reset a device extension */int tw_reset_device_extension(TW_Device_Extension *tw_dev) {	int imax = 0;	int i = 0;	Scsi_Cmnd *srb;	dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");	imax = TW_Q_LENGTH;	if (tw_reset_sequence(tw_dev)) {		printk(KERN_WARNING "3w-xxxx: tw_reset_device_extension(): Reset sequence failed for card %d.\n", tw_dev->host->host_no);		return 1;	}	/* Abort all requests that are in progress */	for (i=0;i<imax;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];			srb->result = (DID_RESET << 16);			tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);		}	}	/* Reset queues and counts */	for (i=0;i<imax;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_LENGTH - 1;	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;	return 0;} /* End tw_reset_device_extension() *//* This function will reset a controller */int tw_reset_sequence(TW_Device_Extension *tw_dev) {	int error = 0;	int tries = 0;	/* Disable interrupts */	tw_disable_interrupts(tw_dev);	/* 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: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev->host->host_no);			tries++;			continue;		}		/* Check for controller errors */		if (tw_check_errors(tw_dev)) {			printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller errors found, soft resetting card %d.\n", tw_dev->host->host_no);			tries++;			continue;		}

⌨️ 快捷键说明

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