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

📄 sym53c8xx_comm.h

📁 Linux Kernel 2.6.9 for OMAP1710
💻 H
📖 第 1 页 / 共 2 页
字号:
/********************************************************************************  High Performance device driver for the Symbios 53C896 controller.****  Copyright (C) 1998-2001  Gerard Roudier <groudier@free.fr>****  This driver also supports all the Symbios 53C8XX controller family, **  except 53C810 revisions < 16, 53C825 revisions < 16 and all **  revisions of 53C815 controllers.****  This driver is based on the Linux port of the FreeBSD ncr driver.** **  Copyright (C) 1994  Wolfgang Stanglmeier**  **-----------------------------------------------------------------------------**  **  This program is free software; you can redistribute it and/or modify**  it under the terms of the GNU General Public License as published by**  the Free Software Foundation; either version 2 of the License, or**  (at your option) any later version.****  This program is distributed in the hope that it will be useful,**  but WITHOUT ANY WARRANTY; without even the implied warranty of**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the**  GNU General Public License for more details.****  You should have received a copy of the GNU General Public License**  along with this program; if not, write to the Free Software**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.****-----------------------------------------------------------------------------****  The Linux port of the FreeBSD ncr driver has been achieved in **  november 1995 by:****          Gerard Roudier              <groudier@free.fr>****  Being given that this driver originates from the FreeBSD version, and**  in order to keep synergy on both, any suggested enhancements and corrections**  received on Linux are automatically a potential candidate for the FreeBSD **  version.****  The original driver has been written for 386bsd and FreeBSD by**          Wolfgang Stanglmeier        <wolf@cologne.de>**          Stefan Esser                <se@mi.Uni-Koeln.de>****-----------------------------------------------------------------------------****  Major contributions:**  --------------------****  NVRAM detection and reading.**    Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>**********************************************************************************//***	This file contains definitions and code that the **	sym53c8xx and ncr53c8xx drivers should share.**	The sharing will be achieved in a further version  **	of the driver bundle. For now, only the ncr53c8xx **	driver includes this file.*//*==========================================================****	Hmmm... What complex some PCI-HOST bridges actually **	are, despite the fact that the PCI specifications **	are looking so smart and simple! ;-)****==========================================================*//*==========================================================****	Miscallaneous defines.****==========================================================*/#define u_char		unsigned char#define u_long		unsigned long#ifndef bzero#define bzero(d, n)	memset((d), 0, (n))#endif /*==========================================================****	assert ()****==========================================================****	modified copy from 386bsd:/usr/include/sys/assert.h****----------------------------------------------------------*/#define	assert(expression) { \	if (!(expression)) { \		(void)panic( \			"assertion \"%s\" failed: file \"%s\", line %d\n", \			#expression, \			__FILE__, __LINE__); \	} \}/*==========================================================****	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_SCATTER  (0x0800)#define DEBUG_IC        (0x1000)/***    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/*==========================================================****	A la VMS/CAM-3 queue management.**	Implemented from linux list management.****==========================================================*/typedef struct xpt_quehead {	struct xpt_quehead *flink;	/* Forward  pointer */	struct xpt_quehead *blink;	/* Backward pointer */} XPT_QUEHEAD;#define xpt_que_init(ptr) do { \	(ptr)->flink = (ptr); (ptr)->blink = (ptr); \} while (0)static inline void __xpt_que_add(struct xpt_quehead * new,	struct xpt_quehead * blink,	struct xpt_quehead * flink){	flink->blink	= new;	new->flink	= flink;	new->blink	= blink;	blink->flink	= new;}static inline void __xpt_que_del(struct xpt_quehead * blink,	struct xpt_quehead * flink){	flink->blink = blink;	blink->flink = flink;}static inline int xpt_que_empty(struct xpt_quehead *head){	return head->flink == head;}static inline void xpt_que_splice(struct xpt_quehead *list,	struct xpt_quehead *head){	struct xpt_quehead *first = list->flink;	if (first != list) {		struct xpt_quehead *last = list->blink;		struct xpt_quehead *at   = head->flink;		first->blink = head;		head->flink  = first;		last->flink = at;		at->blink   = last;	}}#define xpt_que_entry(ptr, type, member) \	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))#define xpt_insque(new, pos)		__xpt_que_add(new, pos, (pos)->flink)#define xpt_remque(el)			__xpt_que_del((el)->blink, (el)->flink)#define xpt_insque_head(new, head)	__xpt_que_add(new, head, (head)->flink)static inline struct xpt_quehead *xpt_remque_head(struct xpt_quehead *head){	struct xpt_quehead *elem = head->flink;	if (elem != head)		__xpt_que_del(head, elem->flink);	else		elem = NULL;	return elem;}#define xpt_insque_tail(new, head)	__xpt_que_add(new, (head)->blink, head)static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head){	struct xpt_quehead *elem = head->blink;	if (elem != head)		__xpt_que_del(elem->blink, head);	else		elem = 0;	return elem;}/*==========================================================****	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.: by controller).****==========================================================*/spinlock_t DRIVER_SMP_LOCK = SPIN_LOCK_UNLOCKED;#define	NCR_LOCK_DRIVER(flags)     spin_lock_irqsave(&DRIVER_SMP_LOCK, flags)#define	NCR_UNLOCK_DRIVER(flags)   \		spin_unlock_irqrestore(&DRIVER_SMP_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(host, flags) \		spin_lock_irqsave((host)->host_lock, flags)#define	NCR_UNLOCK_SCSI_DONE(host, flags) \		spin_unlock_irqrestore(((host)->host_lock), flags)/*==========================================================****	Memory mapped IO****	Since linux-2.1, we must use ioremap() to map the io **	memory space and iounmap() to unmap it. This 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.****==========================================================*/#ifdef __sparc__#include <asm/irq.h>#endif#define memcpy_to_pci(a, b, c)	memcpy_toio((a), (b), (c))/*==========================================================****	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.****==========================================================*/#define UDELAY udelay#define MDELAY mdelay/*==========================================================****	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).****==========================================================*/#define __GetFreePages(flags, order) __get_free_pages(flags, order)#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 struct device *m_bush_t;	/* Something that addresses DMAable */typedef struct m_link {		/* Link between free memory chunks */	struct m_link *next;} m_link_s;typedef 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)typedef struct m_pool {		/* Memory pool of a given kind */	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;	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 NULL;	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 = NULL;			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 = NULL;		}	}#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. */static 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){	FreePages(m);	--mp->nump;}static m_pool_s mp0 = {NULL, ___mp0_getp, ___mp0_freep};/* * DMAable pools. *//* * With pci bus iommu support, we maintain one pool per pcidev and a  * hashed reverse table for virtual to bus physical address translations. */static m_addr_t ___dma_getp(m_pool_s *mp){	m_addr_t vp;	m_vtob_s *vbp;	vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB");	if (vbp) {		dma_addr_t daddr;		vp = (m_addr_t) dma_alloc_coherent(mp->bush,						PAGE_SIZE<<MEMO_PAGE_ORDER,						&daddr, GFP_ATOMIC);		if (vp) {			int hc = VTOB_HASH_CODE(vp);			vbp->vaddr = vp;			vbp->baddr = daddr;			vbp->next = mp->vtob[hc];			mp->vtob[hc] = vbp;			++mp->nump;			return vp;		}	}	if (vbp)		__m_free(&mp0, vbp, sizeof(*vbp), "VTOB");	return 0;}static void ___dma_freep(m_pool_s *mp, m_addr_t m){	m_vtob_s **vbpp, *vbp;	int hc = VTOB_HASH_CODE(m);

⌨️ 快捷键说明

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