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

📄 3w-xxxx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
				queue = 0;				switch (aen_code) {					case TW_AEN_QUEUE_EMPTY:						dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);						if (first_reset != 1) {							continue;						} else {							finished = 1;						}						break;					case TW_AEN_SOFT_RESET:						if (first_reset == 0) {							first_reset = 1;						} else {							printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);							tw_dev->aen_count++;							queue = 1;						}						break;					default:						if (aen == 0x0ff) {							printk(KERN_WARNING "3w-xxxx: AEN: AEN queue overflow.\n");						} else {							if ((aen & 0x0ff) < TW_AEN_STRING_MAX) {								if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {									printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);								} else {									printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);								}							} else								printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen);						}						tw_dev->aen_count++;						queue = 1;				}				/* Now put the aen on the aen_queue */				if (queue == 1) {					tw_dev->aen_queue[tw_dev->aen_tail] = aen_code;					if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {						tw_dev->aen_tail = TW_Q_START;					} else {						tw_dev->aen_tail = tw_dev->aen_tail + 1;					}					if (tw_dev->aen_head == tw_dev->aen_tail) {						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;						}					}				}				found = 1;				break;			}		}		if (found == 0) {			printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");			return 1;		}		tries++;	} while ((tries < TW_MAX_AEN_TRIES) && (finished == 0));	if (tries >=TW_MAX_AEN_TRIES) {		printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Aen queue error.\n");		return 1;	}	return 0;} /* End tw_aen_drain_queue() *//* This function will read the aen queue from the isr */int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) {	TW_Command *command_packet;	TW_Param *param;	u32 command_que_value = 0, command_que_addr;	u32 status_reg_value = 0, status_reg_addr;	u32 param_value = 0;	dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n");	command_que_addr = tw_dev->registers.command_que_addr;	status_reg_addr = tw_dev->registers.status_reg_addr;	status_reg_value = inl(status_reg_addr);	if (tw_check_bits(status_reg_value)) {		dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");		tw_decode_bits(tw_dev, status_reg_value);		return 1;	}	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): 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));	command_packet->byte0.opcode = TW_OP_GET_PARAM;	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;	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");		return 1;	}	/* Now setup the param */	if (tw_dev->alignment_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): 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 = 0x401; /* AEN table */	param->parameter_id = 2; /* Unit code */	param->parameter_size_bytes = 2;	param_value = tw_dev->alignment_physical_address[request_id];	if (param_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): 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);	/* Now post the command packet */	if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {		dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");		tw_dev->srb[request_id] = 0; /* Flag internal command */		tw_dev->state[request_id] = TW_S_POSTED;		outl(command_que_value, command_que_addr);	} else {		printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");		return 1;	}	return 0;} /* End tw_aen_read_queue() *//* This function will allocate memory and check if it is 16 d-word aligned */int tw_allocate_memory(TW_Device_Extension *tw_dev, int request_id, int size, int which){	u32 *virt_addr = kmalloc(size, GFP_ATOMIC);	dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");	if (!virt_addr) {		printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): kmalloc() failed.\n");		return 1;	}	if ((u32)virt_addr % TW_ALIGNMENT) {		kfree(virt_addr);		printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): Found unaligned address.\n");		return 1;	}	switch(which) {	case 0:		tw_dev->command_packet_virtual_address[request_id] = virt_addr;		tw_dev->command_packet_physical_address[request_id] = virt_to_bus(virt_addr);		break;	case 1:		tw_dev->alignment_virtual_address[request_id] = virt_addr;		tw_dev->alignment_physical_address[request_id] = virt_to_bus(virt_addr);		break;	case 2:		tw_dev->bounce_buffer[request_id] = virt_addr;		break;	default:		printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n");		return 1;	}	return 0;} /* End tw_allocate_memory() *//* This function will check the status register for unexpected bits */int tw_check_bits(u32 status_reg_value){	if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {  		dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);		return 1;	}	if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {		dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);		return 1;	}	return 0;} /* End tw_check_bits() *//* This function will report controller error status */int tw_check_errors(TW_Device_Extension *tw_dev) {	u32 status_reg_addr, status_reg_value;  	status_reg_addr = tw_dev->registers.status_reg_addr;	status_reg_value = inl(status_reg_addr);	if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value))		return 1;	return 0;} /* End tw_check_errors() *//* This function will clear the attention interrupt */void tw_clear_attention_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_CLEAR_ATTENTION_INTERRUPT;	outl(control_reg_value, control_reg_addr);} /* End tw_clear_attention_interrupt() *//* This function will clear the host interrupt */void tw_clear_host_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_CLEAR_HOST_INTERRUPT;	outl(control_reg_value, control_reg_addr);} /* End tw_clear_host_interrupt() *//* This function is called by tw_scsi_proc_info */static int tw_copy_info(TW_Info *info, char *fmt, ...) {	va_list args;	char buf[81];	int len;  	va_start(args, fmt);	len = vsprintf(buf, fmt, args);	va_end(args);	tw_copy_mem_info(info, buf, len);	return len;} /* End tw_copy_info() *//* This function is called by tw_scsi_proc_info */static void tw_copy_mem_info(TW_Info *info, char *data, int len){	if (info->position + len > info->length)		len = info->length - info->position;	if (info->position + len < info->offset) {		info->position += len;		return;	}	if (info->position < info->offset) {		data += (info->offset - info->position);		len  -= (info->offset - info->position);	}	if (len > 0) {		memcpy(info->buffer + info->position, data, len);		info->position += len;	}} /* End tw_copy_mem_info() *//* This function will print readable messages from status register errors */void tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value){	dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n");	switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) {	case TW_STATUS_PCI_PARITY_ERROR:		printk(KERN_WARNING "3w-xxxx: PCI Parity Error: Reseat card, move card, or buggy device on the bus.\n");		outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr);		pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PARITY_ERRORS);		break;	case TW_STATUS_MICROCONTROLLER_ERROR:		printk(KERN_WARNING "3w-xxxx: Microcontroller Error.\n");		break;	case TW_STATUS_PCI_ABORT:		printk(KERN_WARNING "3w-xxxx: PCI Abort: clearing.\n");		outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr);		pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);		break;  }} /* End tw_decode_bits() *//* This function will print readable messages from flags and status values */void tw_decode_error(TW_Device_Extension *tw_dev, unsigned char status, unsigned char flags, unsigned char unit){	dprintk(KERN_WARNING "3w-xxxx: tw_decode_error()\n");	switch (status) {	case 0xc7:		switch (flags) {		case 0x1b: 			printk(KERN_WARNING "3w-xxxx: scsi%d: Drive timeout on unit %d, check drive and drive cables.\n", tw_dev->host->host_no, unit);			break;		case 0x51:			printk(KERN_WARNING "3w-xxxx: scsi%d: Unrecoverable drive error on unit %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, unit);			break;		default:			printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);		}		break;	default:		printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit);	}} /* End tw_decode_error() *//* This function will disable interrupts on the controller */  void tw_disable_interrupts(TW_Device_Extension *tw_dev) {	u32 control_reg_value, control_reg_addr;	control_reg_addr = tw_dev->registers.control_reg_addr;	control_reg_value = TW_CONTROL_DISABLE_INTERRUPTS;	outl(control_reg_value, control_reg_addr);} /* End tw_disable_interrupts() *//* This function will empty the response que */int tw_empty_response_que(TW_Device_Extension *tw_dev) {	u32 status_reg_addr, status_reg_value;	u32 response_que_addr, response_que_value;	status_reg_addr = tw_dev->registers.status_reg_addr;	response_que_addr = tw_dev->registers.response_que_addr;  	status_reg_value = inl(status_reg_addr);	if (tw_check_bits(status_reg_value)) {		dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");		tw_decode_bits(tw_dev, status_reg_value);		return 1;	}  	while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {		response_que_value = inl(response_que_addr);		status_reg_value = inl(status_reg_addr);		if (tw_check_bits(status_reg_value)) {			dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");			tw_decode_bits(tw_dev, status_reg_value);			return 1;		}	}	return 0;} /* End tw_empty_response_que() *//* This function will enable interrupts on the controller */void tw_enable_interrupts(TW_Device_Extension *tw_dev){	u32 control_reg_value, control_reg_addr;	control_reg_addr = tw_dev->registers.control_reg_addr;	control_reg_value = (TW_CONTROL_ENABLE_INTERRUPTS |			     TW_CONTROL_UNMASK_RESPONSE_INTERRUPT);

⌨️ 快捷键说明

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