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

📄 3w-xxxx.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	outl(control_reg_value, control_reg_addr);} /* End tw_enable_interrupts() *//* This function will enable interrupts on the controller */void tw_enable_and_clear_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_and_clear_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;	int i;	u16 device[TW_NUMDEVICES] = { TW_DEVICE_ID, TW_DEVICE_ID2 };	dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n");	for (i=0;i<TW_NUMDEVICES;i++) {		while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, device[i], 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;			/* Check for errors and clear them */			status_reg_value = inl(tw_dev->registers.status_reg_addr);			if (TW_STATUS_ERRORS(status_reg_value)) 			  tw_decode_bits(tw_dev, status_reg_value);						/* 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: AEN drain failed for card %d.\n", numcards);					tries++;					continue;				}				/* Check for controller errors */				if (tw_check_errors(tw_dev)) {					printk(KERN_WARNING "3w-xxxx: Controller errors found, retrying for card %d.\n", numcards);					tries++;					continue;				}				/* Empty the response queue */				error = tw_empty_response_que(tw_dev);				if (error) {					printk(KERN_WARNING "3w-xxxx: Couldn't empty response queue, retrying 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: Controller errors, card not responding, check all cabling 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: Connection initialization failed 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, and setup queues */			if (tw_dev->num_units > 0) {				if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {					tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-1)/tw_dev->num_units;					tw_dev->free_head = TW_Q_START;					tw_dev->free_tail = TW_MAX_BOUNCEBUF - 1;					tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1;				} else {					tw_host->cmd_per_lun = (TW_Q_LENGTH-1)/tw_dev->num_units;					tw_dev->free_head = TW_Q_START;					tw_dev->free_tail = TW_Q_LENGTH - 1;					tw_dev->free_wrap = TW_Q_LENGTH - 1;				}			}		/* Register the card with the kernel SCSI layer */			host = scsi_register(tw_host, sizeof(TW_Device_Extension));			if (host == NULL) {				printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed 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;			}			/* Set max target id's */			host->max_id = TW_MAX_UNITS;			/* Set max cdb size in bytes */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,15)						host->max_cmd_len = TW_MAX_CDB_LEN;#endif			/* Set max sectors per io */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)			if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID))				host->max_sectors = TW_MAX_BOUNCE_SECTORS;			else				host->max_sectors = TW_MAX_SECTORS;#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)			scsi_set_pci_device(host, tw_pci_dev);#endif			status_reg_value = inl(tw_dev->registers.status_reg_addr);			printk(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);				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;			}			/* Tell the firmware we support shutdown notification*/			tw_setfeature(tw_dev2, 2, 1, &c);			/* 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;			}			/* Re-enable interrupts on the card */			tw_enable_interrupts(tw_dev2);			/* Free the temporary device extension */			if (tw_dev)				kfree(tw_dev);		}	}	if (numcards == 0) 		printk(KERN_WARNING "3w-xxxx: No cards with valid units found.\n");	else	  register_reboot_notifier(&tw_notifier);	return numcards;} /* End tw_findcards() *//* This function will free up device extension resources */void tw_free_device_extension(TW_Device_Extension *tw_dev){	int i;	dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");	/* Free command packet and generic buffer memory */	for (i=0;i<TW_Q_LENGTH;i++) {		if (tw_dev->command_packet_virtual_address[i]) 			kfree(tw_dev->command_packet_virtual_address[i]);		if (tw_dev->alignment_virtual_address[i])			kfree(tw_dev->alignment_virtual_address[i]);	}	for (i=0;i<TW_MAX_BOUNCEBUF;i++) {		if (tw_dev->bounce_buffer[i])			kfree(tw_dev->bounce_buffer[i]);	}} /* End tw_free_device_extension() *//* Clean shutdown routine */static int tw_halt(struct notifier_block *nb, ulong event, void *buf){	int i;	for (i=0;i<tw_device_extension_count;i++) {		printk(KERN_NOTICE "3w-xxxx: Shutting down card %d.\n", i);		tw_shutdown_device(tw_device_extension_list[i]);	}	unregister_reboot_notifier(&tw_notifier);	return NOTIFY_OK;} /* End tw_halt() *//* This function will send an initconnection command to controller */int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits) {	u32 command_que_addr, command_que_value;	u32 status_reg_addr, status_reg_value;	u32 response_que_addr;	TW_Command  *command_packet;	TW_Response_Queue response_queue;	int request_id = 0;	int i = 0;	int imax = 0;	dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n");	command_que_addr = tw_dev->registers.command_que_addr;	status_reg_addr = tw_dev->registers.status_reg_addr;	response_que_addr = tw_dev->registers.response_que_addr;	/* Initialize InitConnection command packet */	if (tw_dev->command_packet_virtual_address[request_id] == NULL) {		printk(KERN_WARNING "3w-xxxx: tw_initconnection(): 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_INIT_CONNECTION;	command_packet->byte0.sgl_offset = 0x0;	command_packet->size = TW_INIT_COMMAND_PACKET_SIZE;	command_packet->request_id = request_id;	command_packet->byte3.unit = 0x0;	command_packet->byte3.host_id = 0x0;	command_packet->status = 0x0;	command_packet->flags = 0x0;	command_packet->byte6.message_credits = message_credits; 	command_packet->byte8.init_connection.response_queue_pointer = 0x0;	command_que_value = tw_dev->command_packet_physical_address[request_id];	if (command_que_value == 0) {		printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n");		return 1;	}  	/* Send command packet to the board */	outl(command_que_value, command_que_addr);    	/* Poll for completion */	imax = TW_POLL_MAX_RETRIES;	for (i=0;i<imax;i++) {		mdelay(5);		status_reg_value = inl(status_reg_addr);		if (tw_check_bits(status_reg_value)) {			dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");			tw_decode_bits(tw_dev, status_reg_value);			return 1;		}		if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {			response_queue.value = inl(response_que_addr);			request_id = (unsigned char)response_queue.u.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 */				dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags);				tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit);				return 1;			}			break;	/* Response was okay, so we exit */		}	}	return 0;

⌨️ 快捷键说明

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