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

📄 sym53c8xx.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
****	This wrapper allows to get rid of old kernel PCI interface **	and still allows to preserve linux-2.0 compatibilty.**	In fact, it is mostly an incomplete emulation of the new **	PCI code for pre-2.2 kernels. When kernel-2.0 support **	will be dropped, we will just have to remove most of this **	code.*/#if LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0)typedef struct pci_dev *pcidev_t;#define PCIDEV_NULL		(0)#define PciBusNumber(d)		(d)->bus->number#define PciDeviceFn(d)		(d)->devfn#define PciVendorId(d)		(d)->vendor#define PciDeviceId(d)		(d)->device#define PciIrqLine(d)		(d)->irq#if LINUX_VERSION_CODE > LinuxVersionCode(2,3,12)static int __init pci_get_base_address(struct pci_dev *pdev, int index, u_long *base){	*base = pdev->resource[index].start;	if ((pdev->resource[index].flags & 0x7) == 0x4)		++index;	return ++index;}#elsestatic int __init pci_get_base_address(struct pci_dev *pdev, int index, u_long *base){	*base = pdev->base_address[index++];	if ((*base & 0x7) == 0x4) {#if BITS_PER_LONG > 32		*base |= (((u_long)pdev->base_address[index]) << 32);#endif		++index;	}	return index;}#endif#else	/* Incomplete emulation of current PCI code for pre-2.2 kernels */typedef unsigned int pcidev_t;#define PCIDEV_NULL		(~0u)#define PciBusNumber(d)		((d)>>8)#define PciDeviceFn(d)		((d)&0xff)#define __PciDev(busn, devfn)	(((busn)<<8)+(devfn))#define pci_present pcibios_present#define pci_read_config_byte(d, w, v) \	pcibios_read_config_byte(PciBusNumber(d), PciDeviceFn(d), w, v)#define pci_read_config_word(d, w, v) \	pcibios_read_config_word(PciBusNumber(d), PciDeviceFn(d), w, v)#define pci_read_config_dword(d, w, v) \	pcibios_read_config_dword(PciBusNumber(d), PciDeviceFn(d), w, v)#define pci_write_config_byte(d, w, v) \	pcibios_write_config_byte(PciBusNumber(d), PciDeviceFn(d), w, v)#define pci_write_config_word(d, w, v) \	pcibios_write_config_word(PciBusNumber(d), PciDeviceFn(d), w, v)#define pci_write_config_dword(d, w, v) \	pcibios_write_config_dword(PciBusNumber(d), PciDeviceFn(d), w, v)static pcidev_t __initpci_find_device(unsigned int vendor, unsigned int device, pcidev_t prev){	static unsigned short pci_index;	int retv;	unsigned char bus_number, device_fn;	if (prev == PCIDEV_NULL)		pci_index = 0;	else		++pci_index;	retv = pcibios_find_device (vendor, device, pci_index,				    &bus_number, &device_fn);	return retv ? PCIDEV_NULL : __PciDev(bus_number, device_fn);}static u_short __init PciVendorId(pcidev_t dev){	u_short vendor_id;	pci_read_config_word(dev, PCI_VENDOR_ID, &vendor_id);	return vendor_id;}static u_short __init PciDeviceId(pcidev_t dev){	u_short device_id;	pci_read_config_word(dev, PCI_DEVICE_ID, &device_id);	return device_id;}static u_int __init PciIrqLine(pcidev_t dev){	u_char irq;	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);	return irq;}static int __init pci_get_base_address(pcidev_t dev, int offset, u_long *base){	u_int32 tmp;		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &tmp);	*base = tmp;	offset += sizeof(u_int32);	if ((tmp & 0x7) == 0x4) {#if BITS_PER_LONG > 32		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + offset, &tmp);		*base |= (((u_long)tmp) << 32);#endif		offset += sizeof(u_int32);	}	return offset;}#endif	/* LINUX_VERSION_CODE >= LinuxVersionCode(2,2,0) *//*==========================================================****	Debugging tags****==========================================================*/#define DEBUG_ALLOC    (0x0001)#define DEBUG_PHASE    (0x0002)#define DEBUG_QUEUE    (0x0008)#define DEBUG_RESULT   (0x0010)#define DEBUG_POINTER  (0x0020)#define DEBUG_SCRIPT   (0x0040)#define DEBUG_TINY     (0x0080)#define DEBUG_TIMING   (0x0100)#define DEBUG_NEGO     (0x0200)#define DEBUG_TAGS     (0x0400)#define DEBUG_IC       (0x0800)/***    Enable/Disable debug messages.**    Can be changed at runtime too.*/#ifdef SCSI_NCR_DEBUG_INFO_SUPPORTstatic int ncr_debug = SCSI_NCR_DEBUG_FLAGS;	#define DEBUG_FLAGS ncr_debug#else	#define DEBUG_FLAGS	SCSI_NCR_DEBUG_FLAGS#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)spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;#define	NCR_LOCK_DRIVER(flags)     spin_lock_irqsave(&sym53c8xx_lock, flags)#define	NCR_UNLOCK_DRIVER(flags)   spin_unlock_irqrestore(&sym53c8xx_lock,flags)#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)#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_DRIVER(flags)     do { save_flags(flags); cli(); } while (0)#define	NCR_UNLOCK_DRIVER(flags)   do { restore_flags(flags); } while (0)#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/***	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#ifdef __sparc__#  include <asm/irq.h>#  define pcivtobus(p)			bus_dvma_to_mem(p)#  define memcpy_to_pci(a, b, c)	memcpy_toio((a), (b), (c))#elif defined(__alpha__)#  define pcivtobus(p)			((p) & 0xfffffffful)#  define memcpy_to_pci(a, b, c)	memcpy_toio((a), (b), (c))#elif defined(CONFIG_PPC)#  define pcivtobus(p)			phys_to_bus(p)#  define memcpy_to_pci(a, b, c)	memcpy_toio((a), (b), (c))#else	/* others */#  define pcivtobus(p)			(p)#  define memcpy_to_pci(a, b, c)	memcpy_toio((a), (b), (c))#endif#ifndef SCSI_NCR_PCI_MEM_NOT_SUPPORTEDstatic u_long __init 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 page_remapped? (page_remapped + page_offs) : 0UL;}static void __init unmap_pci_mem(u_long vaddr, u_long size){	if (vaddr)		iounmap((void *) (vaddr & PAGE_MASK));}#endif /* not def SCSI_NCR_PCI_MEM_NOT_SUPPORTED *//***	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/***	Simple power of two buddy-like allocator**	----------------------------------------**	This simple code is not intended to be fast, but to provide **	power of 2 aligned memory allocations.**	Since the SCRIPTS processor only supplies 8 bit arithmetic,**	this allocator allows simple and fast address calculations  **	from the SCRIPTS code. In addition, cache line alignment **	is guaranteed for power of 2 cache line size.**	Enhanced in linux-2.3.44 to provide a memory pool per pcidev **	to support dynamic dma mapping. (I would have preferred a **	real bus astraction, btw).*/#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)#define __GetFreePages(flags, order) __get_free_pages(flags, order)#else#define __GetFreePages(flags, order) __get_free_pages(flags, order, 0)#endif#define MEMO_SHIFT	4	/* 16 bytes minimum memory chunk */#if PAGE_SIZE >= 8192#define MEMO_PAGE_ORDER	0	/* 1 PAGE  maximum */#else#define MEMO_PAGE_ORDER	1	/* 2 PAGES maximum */#endif#define MEMO_FREE_UNUSED	/* Free unused pages immediately */#define MEMO_WARN	1#define MEMO_GFP_FLAGS	GFP_ATOMIC#define MEMO_CLUSTER_SHIFT	(PAGE_SHIFT+MEMO_PAGE_ORDER)#define MEMO_CLUSTER_SIZE	(1UL << MEMO_CLUSTER_SHIFT)#define MEMO_CLUSTER_MASK	(MEMO_CLUSTER_SIZE-1)typedef u_long m_addr_t;	/* Enough bits to bit-hack addresses */typedef pcidev_t m_bush_t;	/* Something that addresses DMAable */typedef struct m_link {		/* Link between free memory chunks */	struct m_link *next;} m_link_s;#ifdef	SCSI_NCR_DYNAMIC_DMA_MAPPINGtypedef struct m_vtob {		/* Virtual to Bus address translation */	struct m_vtob *next;	m_addr_t vaddr;	m_addr_t baddr;} m_vtob_s;#define VTOB_HASH_SHIFT		5#define VTOB_HASH_SIZE		(1UL << VTOB_HASH_SHIFT)#define VTOB_HASH_MASK		(VTOB_HASH_SIZE-1)#define VTOB_HASH_CODE(m)	\	((((m_addr_t) (m)) >> MEMO_CLUSTER_SHIFT) & VTOB_HASH_MASK)#endiftypedef struct m_pool {		/* Memory pool of a given kind */#ifdef	SCSI_NCR_DYNAMIC_DMA_MAPPING	m_bush_t bush;	m_addr_t (*getp)(struct m_pool *);	void (*freep)(struct m_pool *, m_addr_t);#define M_GETP()		mp->getp(mp)#define M_FREEP(p)		mp->freep(mp, p)#define GetPages()		__GetFreePages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER)#define FreePages(p)		free_pages(p, MEMO_PAGE_ORDER)	int nump;	m_vtob_s *(vtob[VTOB_HASH_SIZE]);	struct m_pool *next;#else#define M_GETP()		__GetFreePages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER)#define M_FREEP(p)		free_pages(p, MEMO_PAGE_ORDER)#endif	/* SCSI_NCR_DYNAMIC_DMA_MAPPING */	struct m_link h[PAGE_SHIFT-MEMO_SHIFT+MEMO_PAGE_ORDER+1];} m_pool_s;static void *___m_alloc(m_pool_s *mp, int size){	int i = 0;	int s = (1 << MEMO_SHIFT);	int j;	m_addr_t a;	m_link_s *h = mp->h;	if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))		return 0;	while (size > s) {		s <<= 1;		++i;	}	j = i;	while (!h[j].next) {		if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {			h[j].next = (m_link_s *) M_GETP();			if (h[j].next)				h[j].next->next = 0;			break;		}		++j;		s <<= 1;	}	a = (m_addr_t) h[j].next;	if (a) {		h[j].next = h[j].next->next;		while (j > i) {			j -= 1;			s >>= 1;			h[j].next = (m_link_s *) (a+s);			h[j].next->next = 0;		}	}#ifdef DEBUG	printk("___m_alloc(%d) = %p\n", size, (void *) a);#endif	return (void *) a;}static void ___m_free(m_pool_s *mp, void *ptr, int size){	int i = 0;	int s = (1 << MEMO_SHIFT);	m_link_s *q;	m_addr_t a, b;	m_link_s *h = mp->h;#ifdef DEBUG	printk("___m_free(%p, %d)\n", ptr, size);#endif	if (size > (PAGE_SIZE << MEMO_PAGE_ORDER))		return;	while (size > s) {		s <<= 1;		++i;	}	a = (m_addr_t) ptr;	while (1) {#ifdef MEMO_FREE_UNUSED		if (s == (PAGE_SIZE << MEMO_PAGE_ORDER)) {			M_FREEP(a);			break;		}#endif		b = a ^ s;		q = &h[i];		while (q->next && q->next != (m_link_s *) b) {			q = q->next;		}		if (!q->next) {			((m_link_s *) a)->next = h[i].next;			h[i].next = (m_link_s *) a;			break;		}		q->next = q->next->next;		a = a & b;		s <<= 1;		++i;	}}static void *__m_calloc2(m_pool_s *mp, int size, char *name, int uflags){	void *p;	p = ___m_alloc(mp, size);	if (DEBUG_FLAGS & DEBUG_ALLOC)		printk ("new %-10s[%4d] @%p.\n", name, size, p);	if (p)		bzero(p, size);	else if (uflags & MEMO_WARN)		printk (NAME53C8XX ": failed to allocate %s[%d]\n", name, size);	return p;}#define __m_calloc(mp, s, n)	__m_calloc2(mp, s, n, MEMO_WARN)static void __m_free(m_pool_s *mp, void *ptr, int size, char *name){	if (DEBUG_FLAGS & DEBUG_ALLOC)		printk ("freeing %-10s[%4d] @%p.\n", name, size, ptr);	___m_free(mp, ptr, size);}/* * With pci bus iommu support, we use a default pool of unmapped memory  * for memory we donnot need to DMA from/to and one pool per pcidev for  * memory accessed by the PCI chip. `mp0' is the default not DMAable pool. */#ifndef	SCSI_NCR_DYNAMIC_DMA_MAPPINGstatic m_pool_s mp0;#elsestatic m_addr_t ___mp0_getp(m_pool_s *mp){	m_addr_t m = GetPages();	if (m)		++mp->nump;	return m;}static void ___mp0_freep(m_pool_s *mp, m_addr_t m)

⌨️ 快捷键说明

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