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

📄 ncr53c8xx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
**    Io mapped or memory mapped.*/#if defined(SCSI_NCR_IOMAPPED)#define NCR_IOMAPPED#endif/***	other*/#define NCR_SNOOP_TIMEOUT (1000000)/*==========================================================****	Defines for Linux.****	Linux and Bsd kernel functions are quite different.**	These defines allow a minimum change of the original**	code.****==========================================================*/ /* **	Obvious definitions */#define u_char		unsigned char#define u_short		unsigned short#define u_int		unsigned int#define u_long		unsigned longtypedef	u_long		vm_offset_t;typedef	int		vm_size_t;#ifndef bcopy#define bcopy(s, d, n)	memcpy((d), (s), (n))#endif#ifndef bzero#define bzero(d, n)	memset((d), 0, (n))#endif #ifndef offsetof#define offsetof(t, m)	((size_t) (&((t *)0)->m))#endif/***	SMP threading.****	Assuming that SMP systems are generally high end systems and may **	use several SCSI adapters, we are using one lock per controller **	instead of some global one. For the moment (linux-2.1.95), driver's **	entry points are called with the 'io_request_lock' lock held, so:**	- We are uselessly loosing a couple of micro-seconds to lock the **	  controller data structure.**	- But the driver is not broken by design for SMP and so can be **	  more resistant to bugs or bad changes in the IO sub-system code.**	- A small advantage could be that the interrupt code is grained as **	  wished (e.g.: threaded by controller).*/#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)#if 0	/* not yet needed */static spinlock_t driver_lock;#define	NCR_LOCK_DRIVER(flags)     spin_lock_irqsave(&driver_lock, flags)#define	NCR_UNLOCK_DRIVER(flags)   spin_unlock_irqrestore(&driver_lock, flags)#endif#define NCR_INIT_LOCK_NCB(np)      spin_lock_init(&np->smp_lock);#define	NCR_LOCK_NCB(np, flags)    spin_lock_irqsave(&np->smp_lock, flags)#define	NCR_UNLOCK_NCB(np, flags)  spin_unlock_irqrestore(&np->smp_lock, flags)#	if LINUX_VERSION_CODE < LinuxVersionCode(2,3,99)#	define	NCR_LOCK_SCSI_DONE(np, flags) \		spin_lock_irqsave(&io_request_lock, flags)#	define	NCR_UNLOCK_SCSI_DONE(np, flags) \		spin_unlock_irqrestore(&io_request_lock, flags)#	else#	define	NCR_LOCK_SCSI_DONE(np, flags)    do {;} while (0)#	define	NCR_UNLOCK_SCSI_DONE(np, flags)  do {;} while (0)#	endif#else#if 0	/* not yet needed */#define	NCR_LOCK_DRIVER(flags)     do {;} while (0)#define	NCR_UNLOCK_DRIVER(flags)   do {;} while (0)#endif#define	NCR_INIT_LOCK_NCB(np)      do { } while (0)#define	NCR_LOCK_NCB(np, flags)    do { save_flags(flags); cli(); } while (0)#define	NCR_UNLOCK_NCB(np, flags)  do { restore_flags(flags); } while (0)#define	NCR_LOCK_SCSI_DONE(np, flags)    do {;} while (0)#define	NCR_UNLOCK_SCSI_DONE(np, flags)  do {;} while (0)#endif/***	Address translation****	The driver has to provide physical memory addresses to **	the script processor. Because some architectures use **	different physical addresses from the PCI BUS, we must **	use virt_to_bus instead of virt_to_phys.*/#define vtophys(p)	virt_to_bus(p)/***	Memory mapped IO****	Since linux-2.1, we must use ioremap() to map the io memory space.**	iounmap() to unmap it. That allows portability.**	Linux 1.3.X and 2.0.X allow to remap physical pages addresses greater **	than the highest physical memory address to kernel virtual pages with **	vremap() / vfree(). That was not portable but worked with i386 **	architecture.*/#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)#define ioremap vremap#define iounmap vfree#endif#if defined (__sparc__)#include <asm/irq.h>#elif defined (__alpha__)#define bus_dvma_to_mem(p)		((p) & 0xfffffffful)#else#define bus_dvma_to_mem(p)		(p)#endif#if defined(__i386__) || !defined(NCR_IOMAPPED)__initfunc(static vm_offset_t remap_pci_mem(u_long base, u_long size)){	u_long page_base	= ((u_long) base) & PAGE_MASK;	u_long page_offs	= ((u_long) base) - page_base;	u_long page_remapped	= (u_long) ioremap(page_base, page_offs+size);	return (vm_offset_t) (page_remapped? (page_remapped + page_offs) : 0UL);}__initfunc(static void unmap_pci_mem(vm_offset_t vaddr, u_long size)){	if (vaddr)		iounmap((void *) (vaddr & PAGE_MASK));}#endif	/* __i386__ || !NCR_IOMAPPED *//***	Insert a delay in micro-seconds and milli-seconds.**	-------------------------------------------------**	Under Linux, udelay() is restricted to delay < 1 milli-second.**	In fact, it generally works for up to 1 second delay.**	Since 2.1.105, the mdelay() function is provided for delays **	in milli-seconds.**	Under 2.0 kernels, udelay() is an inline function that is very **	inaccurate on Pentium processors.*/#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,105)#define UDELAY udelay#define MDELAY mdelay#elsestatic void UDELAY(long us) { udelay(us); }static void MDELAY(long ms) { while (ms--) UDELAY(1000); }#endif/***	Internal data structure allocation.****	Linux scsi memory poor pool is adjusted for the need of**	middle-level scsi driver.**	We allocate our control blocks in the kernel memory pool**	to avoid scsi pool shortage.****	kmalloc() only ensures 8 bytes boundary alignment.**	The NCR need better alignment for cache line bursting.**	The global header is moved between the NCB and CCBs and needs **	origin and destination addresses to have same lower four bits.****	We use 32 boundary alignment for NCB and CCBs and offset multiple **	of 32 for global header fields. That's too much but at least enough.*/#define ALIGN_SIZE(shift)	(1UL << shift)#define ALIGN_MASK(shift)	(~(ALIGN_SIZE(shift)-1))#define CACHE_LINE_SHIFT	5#define CACHE_LINE_SIZE		ALIGN_SIZE(CACHE_LINE_SHIFT)#define CACHE_LINE_MASK		ALIGN_MASK(CACHE_LINE_SHIFT)static void *m_alloc(int size, int a_shift){	u_long addr;	void *ptr;	u_long a_size, a_mask;	if (a_shift < 3)		a_shift = 3;	a_size	= ALIGN_SIZE(a_shift);	a_mask	= ALIGN_MASK(a_shift);	ptr = (void *) kmalloc(size + a_size, GFP_ATOMIC);	if (ptr) {		addr	= (((u_long) ptr) + a_size) & a_mask;		*((void **) (addr - sizeof(void *))) = ptr;		ptr	= (void *) addr;	}	return ptr;}#ifdef MODULEstatic void m_free(void *ptr, int size){	u_long addr;	if (ptr) {		addr	= (u_long) ptr;		ptr	= *((void **) (addr - sizeof(void *)));		kfree(ptr);	}}#endif/***	Transfer direction****	Low-level scsi drivers under Linux do not receive the expected **	data transfer direction from upper scsi drivers.**	The driver will only check actual data direction for common **	scsi opcodes. Other ones may cause problem, since they may **	depend on device type or be vendor specific.**	I would prefer to never trust the device for data direction, **	but that is not possible.****	The original driver requires the expected direction to be known.**	The Linux version of the driver has been enhanced in order to **	be able to transfer data in the direction choosen by the target. */#define XFER_IN		(1)#define XFER_OUT	(2)/***	Head of list of NCR boards****	For kernel version < 1.3.70, host is retrieved by its irq level.**	For later kernels, the internal host control block address **	(struct ncb) is used as device id parameter of the irq stuff.*/static struct Scsi_Host		*first_host	= NULL;static Scsi_Host_Template	*the_template	= NULL;	/***	/proc directory entry and proc_info function*/static struct proc_dir_entry proc_scsi_ncr53c8xx = {    PROC_SCSI_NCR53C8XX, 9, "ncr53c8xx",    S_IFDIR | S_IRUGO | S_IXUGO, 2};#ifdef SCSI_NCR_PROC_INFO_SUPPORTstatic int ncr53c8xx_proc_info(char *buffer, char **start, off_t offset,			int length, int hostno, int func);#endif/***	Driver setup.****	This structure is initialized from linux config options.**	It can be overridden at boot-up by the boot command line.*/static struct ncr_driver_setup	driver_setup			= SCSI_NCR_DRIVER_SETUP;#ifdef	SCSI_NCR_BOOT_COMMAND_LINE_SUPPORTstatic struct ncr_driver_setup	driver_safe_setup __initdata	= SCSI_NCR_DRIVER_SAFE_SETUP;# ifdef	MODULEchar *ncr53c8xx = 0;	/* command line passed by insmod */#  if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)MODULE_PARM(ncr53c8xx, "s");#  endif# endif#endif/***	Other Linux definitions*/#define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f))static void ncr53c8xx_select_queue_depths(	struct Scsi_Host *host, struct scsi_device *devlist);static void ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs);static void ncr53c8xx_timeout(unsigned long np);#define initverbose (driver_setup.verbose)#define bootverbose (np->verbose)#ifdef SCSI_NCR_NVRAM_SUPPORTstatic u_char Tekram_sync[12] __initdata = {25,31,37,43,50,62,75,125,12,15,18,21};#endif /* SCSI_NCR_NVRAM_SUPPORT *//***	Structures used by ncr53c8xx_detect/ncr53c8xx_pci_init to **	transmit device configuration to the ncr_attach() function.*/typedef struct {	int	bus;	u_char	device_fn;	u_long	base;	u_long	base_2;	u_long	io_port;	int	irq;/* port and reg fields to use INB, OUTB macros */	u_long	port;	volatile struct ncr_reg	*reg;} ncr_slot;typedef struct {	int type;#define	SCSI_NCR_SYMBIOS_NVRAM	(1)#define	SCSI_NCR_TEKRAM_NVRAM	(2)#ifdef	SCSI_NCR_NVRAM_SUPPORT	union {		Symbios_nvram Symbios;		Tekram_nvram Tekram;	} data;#endif} ncr_nvram;/***	Structure used by ncr53c8xx_detect/ncr53c8xx_pci_init**	to save data on each detected board for ncr_attach().*/typedef struct {	ncr_slot  slot;	ncr_chip  chip;	ncr_nvram *nvram;	u_char	  host_id;	int attach_done;} ncr_device;/*==========================================================****	Debugging tags****==========================================================*/#define DEBUG_ALLOC    (0x0001)#define DEBUG_PHASE    (0x0002)#define DEBUG_POLL     (0x0004)#define DEBUG_QUEUE    (0x0008)#define DEBUG_RESULT   (0x0010)#define DEBUG_SCATTER  (0x0020)#define DEBUG_SCRIPT   (0x0040)#define DEBUG_TINY     (0x0080)#define DEBUG_TIMING   (0x0100)#define DEBUG_NEGO     (0x0200)#define DEBUG_TAGS     (0x0400)#define DEBUG_FREEZE   (0x0800)#define DEBUG_RESTART  (0x1000)/***    Enable/Disable debug messages.**    Can be changed at runtime too.*/#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT	#define DEBUG_FLAGS ncr_debug#else	#define DEBUG_FLAGS	SCSI_NCR_DEBUG_FLAGS#endif/*==========================================================****	assert ()****==========================================================****	modified copy from 386bsd:/usr/include/sys/assert.h****----------------------------------------------------------*/#define	assert(expression) { \	if (!(expression)) { \		(void)printk(KERN_ERR \			"assertion \"%s\" failed: file \"%s\", line %d\n", \			#expression, \			__FILE__, __LINE__); \	} \}/*==========================================================****	Big/Little endian support.****==========================================================*//***	If the NCR uses big endian addressing mode over the **	PCI, actual io register addresses for byte and word **	accesses must be changed according to lane routing.**	Btw, ncr_offb() and ncr_offw() macros only apply to **	constants and so donnot generate bloated code.*/#if	defined(SCSI_NCR_BIG_ENDIAN)#define ncr_offb(o)	(((o)&~3)+((~((o)&3))&3))#define ncr_offw(o)	(((o)&~3)+((~((o)&3))&2))#else#define ncr_offb(o)	(o)#define ncr_offw(o)	(o)#endif/***	If the CPU and the NCR use same endian-ness addressing,**	no byte reordering is needed for script patching.**	Macro cpu_to_scr() is to be used for script patching.**	Macro scr_to_cpu() is to be used for getting a DWORD **	from the script.*/#if	defined(__BIG_ENDIAN) && !defined(SCSI_NCR_BIG_ENDIAN)

⌨️ 快捷键说明

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