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

📄 sbp2.c

📁 这个是uClinux下的ieee1394驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
 * transfer sizes. */MODULE_PARM(sbp2_max_sectors,"i");MODULE_PARM_DESC(sbp2_max_sectors, "Change max sectors per I/O supported (default = 255)");static int sbp2_max_sectors = SBP2_MAX_SECTORS;/* * Adjust sbp2_max_outstanding_cmds to tune performance if you have many * sbp2 devices attached (or if you need to do some debugging). */MODULE_PARM(sbp2_max_outstanding_cmds,"i");MODULE_PARM_DESC(sbp2_max_outstanding_cmds, "Change max outstanding concurrent commands (default = 8)");static int sbp2_max_outstanding_cmds = SBP2SCSI_MAX_OUTSTANDING_CMDS;/* * Adjust sbp2_max_cmds_per_lun to tune performance. Enabling more than * one concurrent/linked command per sbp2 device may allow some * performance gains, but some older sbp2 devices have firmware bugs * resulting in problems when linking commands... so, enable this with * care.  I can note that the Oxsemi OXFW911 sbp2 chipset works very well * with large numbers of concurrent/linked commands.  =) */MODULE_PARM(sbp2_max_cmds_per_lun,"i");MODULE_PARM_DESC(sbp2_max_cmds_per_lun, "Change max concurrent commands per sbp2 device (default = 1)");static int sbp2_max_cmds_per_lun = SBP2SCSI_MAX_CMDS_PER_LUN;/* * Exclusive login to sbp2 device? In most cases, the sbp2 driver should * do an exclusive login, as it's generally unsafe to have two hosts * talking to a single sbp2 device at the same time (filesystem coherency, * etc.). If you're running an sbp2 device that supports multiple logins, * and you're either running read-only filesystems or some sort of special * filesystem supporting multiple hosts, then set sbp2_exclusive_login to * zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four * concurrent logins. */MODULE_PARM(sbp2_exclusive_login,"i");MODULE_PARM_DESC(sbp2_exclusive_login, "Exclusive login to sbp2 device (default = 1)");static int sbp2_exclusive_login = 1;/* * SCSI inquiry hack for really badly behaved sbp2 devices. Turn this on * if your sbp2 device is not properly handling the SCSI inquiry command. * This hack makes the inquiry look more like a typical MS Windows * inquiry. *  * If sbp2_force_inquiry_hack=1 is required for your device to work, * please submit the logged sbp2_firmware_revision value of this device to * the linux1394-devel mailing list. */MODULE_PARM(sbp2_force_inquiry_hack,"i");MODULE_PARM_DESC(sbp2_force_inquiry_hack, "Force SCSI inquiry hack (default = 0)");static int sbp2_force_inquiry_hack = 0;/* * Export information about protocols/devices supported by this driver. */static struct ieee1394_device_id sbp2_id_table[] = {	{		.match_flags =IEEE1394_MATCH_SPECIFIER_ID |		              IEEE1394_MATCH_VERSION,		.specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,		.version =    SBP2_SW_VERSION_ENTRY & 0xffffff	},	{ }};MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);/* * Debug levels, configured via kernel config, or enable here. *//* #define CONFIG_IEEE1394_SBP2_DEBUG_ORBS *//* #define CONFIG_IEEE1394_SBP2_DEBUG_DMA *//* #define CONFIG_IEEE1394_SBP2_DEBUG 1 *//* #define CONFIG_IEEE1394_SBP2_DEBUG 2 *//* #define CONFIG_IEEE1394_SBP2_PACKET_DUMP */#ifdef CONFIG_IEEE1394_SBP2_DEBUG_ORBS#define SBP2_ORB_DEBUG(fmt, args...)	HPSB_ERR("sbp2(%s): "fmt, __FUNCTION__, ## args)static u32 global_outstanding_command_orbs = 0;#define outstanding_orb_incr global_outstanding_command_orbs++#define outstanding_orb_decr global_outstanding_command_orbs--#else#define SBP2_ORB_DEBUG(fmt, args...)#define outstanding_orb_incr#define outstanding_orb_decr#endif#ifdef CONFIG_IEEE1394_SBP2_DEBUG_DMA#define SBP2_DMA_ALLOC(fmt, args...) \	HPSB_ERR("sbp2(%s)alloc(%d): "fmt, __FUNCTION__, \		 ++global_outstanding_dmas, ## args)#define SBP2_DMA_FREE(fmt, args...) \	HPSB_ERR("sbp2(%s)free(%d): "fmt, __FUNCTION__, \		 --global_outstanding_dmas, ## args)static u32 global_outstanding_dmas = 0;#else#define SBP2_DMA_ALLOC(fmt, args...)#define SBP2_DMA_FREE(fmt, args...)#endif#if CONFIG_IEEE1394_SBP2_DEBUG >= 2#define SBP2_DEBUG(fmt, args...)	HPSB_ERR("sbp2: "fmt, ## args)#define SBP2_INFO(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)#define SBP2_NOTICE(fmt, args...)	HPSB_ERR("sbp2: "fmt, ## args)#define SBP2_WARN(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)#elif CONFIG_IEEE1394_SBP2_DEBUG == 1#define SBP2_DEBUG(fmt, args...)	HPSB_DEBUG("sbp2: "fmt, ## args)#define SBP2_INFO(fmt, args...)		HPSB_INFO("sbp2: "fmt, ## args)#define SBP2_NOTICE(fmt, args...)	HPSB_NOTICE("sbp2: "fmt, ## args)#define SBP2_WARN(fmt, args...)		HPSB_WARN("sbp2: "fmt, ## args)#else #define SBP2_DEBUG(fmt, args...)#define SBP2_INFO(fmt, args...)		HPSB_INFO("sbp2: "fmt, ## args)#define SBP2_NOTICE(fmt, args...)       HPSB_NOTICE("sbp2: "fmt, ## args)#define SBP2_WARN(fmt, args...)         HPSB_WARN("sbp2: "fmt, ## args)#endif#define SBP2_ERR(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args)/* * Spinlock debugging stuff. */#define SBP2_USE_REAL_SPINLOCKS#ifdef SBP2_USE_REAL_SPINLOCKS#define sbp2_spin_lock(lock, flags)	spin_lock_irqsave(lock, flags)	#define sbp2_spin_unlock(lock, flags)	spin_unlock_irqrestore(lock, flags);static spinlock_t sbp2_host_info_lock = SPIN_LOCK_UNLOCKED;#else#define sbp2_spin_lock(lock, flags)	do {save_flags(flags); cli();} while (0)	#define sbp2_spin_unlock(lock, flags)	do {restore_flags(flags);} while (0)#endif/* * Globals */static Scsi_Host_Template scsi_driver_template;static u8 sbp2_speedto_maxrec[] = { 0x7, 0x8, 0x9 };static LIST_HEAD(sbp2_host_info_list);static struct hpsb_highlevel *sbp2_hl_handle = NULL;static struct hpsb_highlevel_ops sbp2_hl_ops = {	.add_host =	sbp2_add_host,	.remove_host =	sbp2_remove_host,};static struct hpsb_address_ops sbp2_ops = {	.write = sbp2_handle_status_write};#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMAstatic struct hpsb_address_ops sbp2_physdma_ops = {        .read = sbp2_handle_physdma_read,        .write = sbp2_handle_physdma_write,};#endifstatic struct hpsb_protocol_driver sbp2_driver = {	.name =		"SBP2 Driver",	.id_table = 	sbp2_id_table,	.probe = 		sbp2_probe,	.disconnect = 	sbp2_disconnect,	.update = 	sbp2_update};/* List of device firmware's that require a forced 36 byte inquiry.  */static u32 sbp2_broken_inquiry_list[] = {	0x00002800,	/* Stefan Richter <richtest@bauwesen.tu-cottbus.de> */			/* DViCO Momobay CX-1 */	0x00000200	/* Andreas Plesch <plesch@fas.harvard.edu> */			/* QPS Fire DVDBurner */};#define NUM_BROKEN_INQUIRY_DEVS \	(sizeof(sbp2_broken_inquiry_list)/sizeof(*sbp2_broken_inquiry_list))/************************************** * General utility functions **************************************/#ifndef __BIG_ENDIAN/* * Converts a buffer from be32 to cpu byte ordering. Length is in bytes. */static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length){	u32 *temp = buffer;	for (length = (length >> 2); length--; )		temp[length] = be32_to_cpu(temp[length]);	return;}/* * Converts a buffer from cpu to be32 byte ordering. Length is in bytes. */static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length){	u32 *temp = buffer;	for (length = (length >> 2); length--; )		temp[length] = cpu_to_be32(temp[length]);	return;}#else /* BIG_ENDIAN *//* Why waste the cpu cycles? */#define sbp2util_be32_to_cpu_buffer(x,y)#define sbp2util_cpu_to_be32_buffer(x,y)#endif#ifdef CONFIG_IEEE1394_SBP2_PACKET_DUMP/* * Debug packet dump routine. Length is in bytes. */static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, u32 dump_phys_addr){	int i;	unsigned char *dump = buffer;	if (!dump || !length || !dump_name)		return;	if (dump_phys_addr)		printk("[%s, 0x%x]", dump_name, dump_phys_addr);	else		printk("[%s]", dump_name);	for (i = 0; i < length; i++) {		if (i > 0x3f) {			printk("\n   ...");			break;		}		if ((i & 0x3) == 0)			printk("  ");		if ((i & 0xf) == 0)			printk("\n   ");		printk("%02x ", (int) dump[i]);	}	printk("\n");	return;}#else#define sbp2util_packet_dump(w,x,y,z)#endif/* * Goofy routine that basically does a down_timeout function. */static int sbp2util_down_timeout(atomic_t *done, int timeout){	int i;	for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) {		set_current_state(TASK_INTERRUPTIBLE);		if (schedule_timeout(HZ/10))	/* 100ms */			return(1);	}	return ((i > 0) ? 0:1);}/* * This function is called to initially create a packet pool for use in * sbp2 I/O requests. This packet pool is used when sending out sbp2 * command and agent reset requests, and allows us to remove all * kmallocs/kfrees from the critical I/O paths. */static int sbp2util_create_request_packet_pool(struct sbp2scsi_host_info *hi){	struct hpsb_packet *packet;	int i;	hi->request_packet = kmalloc(sizeof(struct sbp2_request_packet) * SBP2_MAX_REQUEST_PACKETS, 				     GFP_KERNEL);	if (!hi->request_packet) {		SBP2_ERR("sbp2util_create_request_packet_pool - packet allocation failed!");		return(-ENOMEM);	}	memset(hi->request_packet, 0, sizeof(struct sbp2_request_packet) * SBP2_MAX_REQUEST_PACKETS);	/* 	 * Create a pool of request packets. Just take the max supported 	 * concurrent commands and multiply by two to be safe... 	 */	for (i=0; i<SBP2_MAX_REQUEST_PACKETS; i++) {		/*		 * Max payload of 8 bytes since the sbp2 command request		 * uses a payload of 8 bytes, and agent reset is a quadlet		 * write request. Bump this up if we plan on using this		 * pool for other stuff.		 */		packet = alloc_hpsb_packet(8);		if (!packet) {			SBP2_ERR("sbp2util_create_request_packet_pool - packet allocation failed!");			return(-ENOMEM);		}		/* 		 * Put these request packets into a free list		 */		INIT_LIST_HEAD(&hi->request_packet[i].list);		hi->request_packet[i].packet = packet;		list_add_tail(&hi->request_packet[i].list, &hi->sbp2_req_free);	}	return(0);}/* * This function is called to remove the packet pool. It is called when * the sbp2 driver is unloaded. */static void sbp2util_remove_request_packet_pool(struct sbp2scsi_host_info *hi){	struct list_head *lh;	struct sbp2_request_packet *request_packet;	unsigned long flags;	/* 	 * Go through free list releasing packets	 */	sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags);	while (!list_empty(&hi->sbp2_req_free)) {		lh = hi->sbp2_req_free.next;		list_del(lh);		request_packet = list_entry(lh, struct sbp2_request_packet, list);		/*		 * Free the hpsb packets that we allocated for the pool		 */		if (request_packet) {			free_hpsb_packet(request_packet->packet);		}	}	kfree(hi->request_packet);	sbp2_spin_unlock(&hi->sbp2_request_packet_lock, flags);	return;}/* * This function is called to retrieve a block write packet from our * packet pool. This function is used in place of calling * alloc_hpsb_packet (which costs us three kmallocs). Instead we just pull * out a free request packet and re-initialize values in it. I'm sure this * can still stand some more optimization. */static struct sbp2_request_packet *sbp2util_allocate_write_request_packet(struct sbp2scsi_host_info *hi,				       struct node_entry *ne, u64 addr,				       size_t data_size,				       quadlet_t data) {	struct list_head *lh;	struct sbp2_request_packet *request_packet = NULL;	struct hpsb_packet *packet;	unsigned long flags;	sbp2_spin_lock(&hi->sbp2_request_packet_lock, flags);	if (!list_empty(&hi->sbp2_req_free)) {		/*		 * Pull out a free request packet		 */		lh = hi->sbp2_req_free.next;		list_del(lh);		request_packet = list_entry(lh, struct sbp2_request_packet, list);		packet = request_packet->packet;		/*		 * Initialize the packet (this is really initialization		 * the core 1394 stack should do, but I'm doing it myself		 * to avoid the overhead).		 */

⌨️ 快捷键说明

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