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

📄 3w-xxxx.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	/* 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;	}	if (which == 0) {		tw_dev->command_packet_virtual_address[request_id] = virt_addr;		tw_dev->command_packet_physical_address[request_id] = 		virt_to_bus(virt_addr);	} else {		tw_dev->alignment_virtual_address[request_id] = virt_addr;		tw_dev->alignment_physical_address[request_id] = virt_to_bus(virt_addr);	}	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) {  		printk(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) {		printk(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 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)) {		printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");		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)) {			printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");			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_CLEAR_ATTENTION_INTERRUPT |			     TW_CONTROL_UNMASK_RESPONSE_INTERRUPT |			     TW_CONTROL_ENABLE_INTERRUPTS);	outl(control_reg_value, control_reg_addr);} /* End tw_enable_interrupts() *//* This function will find and initialize all cards */int tw_findcards(Scsi_Host_Template *tw_host) {	int numcards = 0, tries = 0, error = 0;	struct Scsi_Host *host;	TW_Device_Extension *tw_dev;	TW_Device_Extension *tw_dev2;	struct pci_dev *tw_pci_dev = NULL;	u32 status_reg_value;	unsigned char c = 1;	dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n");	while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, TW_DEVICE_ID, tw_pci_dev))) {		if (pci_enable_device(tw_pci_dev))			continue;		/* Prepare temporary device extension */		tw_dev=(TW_Device_Extension *)kmalloc(sizeof(TW_Device_Extension), GFP_ATOMIC);		if (tw_dev == NULL) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): kmalloc() failed for card %d.\n", numcards);			continue;		}		memset(tw_dev, 0, sizeof(TW_Device_Extension));		error = tw_initialize_device_extension(tw_dev);		if (error) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize device extension for card %d.\n", numcards);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}		/* Calculate the cards register addresses */		tw_dev->registers.base_addr = pci_resource_start(tw_pci_dev, 0);		tw_dev->registers.control_reg_addr = pci_resource_start(tw_pci_dev, 0);		tw_dev->registers.status_reg_addr = pci_resource_start(tw_pci_dev, 0) + 0x4;		tw_dev->registers.command_que_addr = pci_resource_start(tw_pci_dev, 0) + 0x8;		tw_dev->registers.response_que_addr = pci_resource_start(tw_pci_dev, 0) + 0xC;		/* Save pci_dev struct to device extension */		tw_dev->tw_pci_dev = tw_pci_dev;		/* Poll status register for 60 secs for 'Controller Ready' flag */		if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Microcontroller not ready for card %d.\n", numcards);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}		/* Disable interrupts on the card */		tw_disable_interrupts(tw_dev);		while (tries < TW_MAX_RESET_TRIES) {			/* Do soft reset */			tw_soft_reset(tw_dev);			error = tw_aen_drain_queue(tw_dev);			if (error) {				printk(KERN_WARNING "3w-xxxx: tw_findcards(): No attention interrupt for card %d.\n", numcards);				tries++;				continue;			}			/* Check for controller errors */			if (tw_check_errors(tw_dev)) {				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Controller errors found, soft resetting card %d.\n", numcards);				tries++;				continue;			}			/* Empty the response queue */			error = tw_empty_response_que(tw_dev);			if (error) {				printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't empty response queue for card %d.\n", numcards);				tries++;				continue;			}			/* Now the controller is in a good state */			break;		}		if (tries >= TW_MAX_RESET_TRIES) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Controller error or no attention interrupt: giving up for card %d.\n", numcards);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}		/* Make sure that io region isn't already taken */		if (check_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE)) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't get io range 0x%lx-0x%lx for card %d.\n", 				(tw_dev->tw_pci_dev->resource[0].start), 				(tw_dev->tw_pci_dev->resource[0].start) + 				TW_IO_ADDRESS_RANGE, numcards);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}    		/* Reserve the io address space */		request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME);		error = tw_initialize_units(tw_dev);		if (error) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize units for card %d.\n", numcards);			release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}		error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);		if (error) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initconnection for card %d.\n", numcards);			release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}		/* Calculate max cmds per lun */		if (tw_dev->num_units > 0)			tw_host->cmd_per_lun = (TW_Q_LENGTH-2)/tw_dev->num_units;		/* Register the card with the kernel SCSI layer */		host = scsi_register(tw_host, sizeof(TW_Device_Extension));		if( host == NULL)		{			release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}		status_reg_value = inl(tw_dev->registers.status_reg_addr);		dprintk(KERN_NOTICE "scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d P-chip: %d.%d\n", host->host_no,				(u32)(tw_pci_dev->resource[0].start), tw_pci_dev->irq, 				(status_reg_value & TW_STATUS_MAJOR_VERSION_MASK) >> 28, 				(status_reg_value & TW_STATUS_MINOR_VERSION_MASK) >> 24);		if (host->hostdata) {			tw_dev2 = (TW_Device_Extension *)host->hostdata;			memcpy(tw_dev2, tw_dev, sizeof(TW_Device_Extension));			tw_device_extension_list[tw_device_extension_count] = tw_dev2;			numcards++;			tw_device_extension_count = numcards;			tw_dev2->host = host;		} else { 			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", numcards-1);			scsi_unregister(host);			release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			continue;		}    		/* Re-enable interrupts on the card */		tw_enable_interrupts(tw_dev2);		/* Now setup the interrupt handler */		error = tw_setup_irq(tw_dev2);		if (error) {			printk(KERN_WARNING "3w-xxxx: tw_findcards(): Error requesting irq for card %d.\n", numcards-1);			scsi_unregister(host);			release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);			tw_free_device_extension(tw_dev);			kfree(tw_dev);			numcards--;			continue;		}		/* Free the temporary device extension */		if (tw_dev)			kfree(tw_dev);		/* Tell the firmware we support shutdown notification*/		tw_setfeature(tw_dev2, 2, 1, &c);	}	if (numcards == 0) 		printk(KERN_WARNING "3w-xxxx: tw_findcards(): No cards found.\n");	else	  register_reboot_notifier(&tw_notifier);

⌨️ 快捷键说明

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