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

📄 sym53c8xx_comm.h

📁 讲述linux的初始化过程
💻 H
📖 第 1 页 / 共 5 页
字号:
/********************************************************************************  High Performance device driver for the Symbios 53C896 controller.****  Copyright (C) 1998-2000  Gerard Roudier <groudier@club-internet.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@club-internet.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.*/#define MIN(a,b)        (((a) < (b)) ? (a) : (b))#define MAX(a,b)        (((a) > (b)) ? (a) : (b))/*==========================================================****	Hmmm... What complex some PCI-HOST bridges actually **	are, despite the fact that the PCI specifications **	are looking so smart and simple! ;-)****==========================================================*/#if LINUX_VERSION_CODE >= LinuxVersionCode(2,3,47)#define SCSI_NCR_DYNAMIC_DMA_MAPPING#endif/*==========================================================****    Io mapped versus memory mapped.****==========================================================*/#if defined(SCSI_NCR_IOMAPPED) || defined(SCSI_NCR_PCI_MEM_NOT_SUPPORTED)#define NCR_IOMAPPED#endif/*==========================================================****	Miscallaneous defines.****==========================================================*/#define u_char		unsigned char#define u_short		unsigned short#define u_int		unsigned int#define u_long		unsigned long#ifndef bcopy#define bcopy(s, d, n)	memcpy((d), (s), (n))#endif#ifndef bcmp#define bcmp(s, d, n)	memcmp((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/*==========================================================****	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 = 0;	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;}/*==========================================================****	On x86 architecture, write buffers management does **	not reorder writes to memory. So, using compiler **	optimization barriers is enough to guarantee some **	ordering when the CPU is writing data accessed by **	the NCR.**	On Alpha architecture, explicit memory barriers have **	to be used.**	Other architectures are defaulted to mb() macro if  **	defined, otherwise use compiler barrier.****==========================================================*/#if defined(__i386__)#define MEMORY_BARRIER()	barrier()#elif defined(__alpha__)#define MEMORY_BARRIER()	mb()#else#  ifdef mb#  define MEMORY_BARRIER()	mb()#  else#  define MEMORY_BARRIER()	barrier()#  endif#endif/*==========================================================****	Simple Wrapper to kernel PCI bus interface.****	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) *//*==========================================================****	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).****==========================================================*/#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93)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(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 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.****==========================================================*/#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))#else	/* others */#  define pcivtobus(p)			(p)#  define memcpy_to_pci(a, b, c)	memcpy_toio((a), (b), (c))#endif#if (defined(SCSI_NCR_NVRAM_SUPPORT) && !defined(NCR_IOMAPPED)) || \	(defined(__i386__) && !defined(SCSI_NCR_PCI_MEM_NOT_SUPPORTED))static 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)

⌨️ 快捷键说明

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