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

📄 buslogic.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters  Copyright 1995-1998 by Leonard N. Zubkoff <lnz@dandelion.com>  This program is free software; you may redistribute and/or modify it under  the terms of the GNU General Public License Version 2 as published by the  Free Software Foundation.  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 complete details.  The author respectfully requests that any modifications to this software be  sent directly to him for evaluation and testing.  Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose  advice has been invaluable, to David Gentzel, for writing the original Linux  BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site.  Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB  Manager available as freely redistributable source code.*/#define BusLogic_DriverVersion		"2.1.16"#define BusLogic_DriverDate		"18 July 2002"#include <linux/module.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/types.h>#include <linux/blkdev.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/stat.h>#include <linux/pci.h>#include <linux/spinlock.h>#include <linux/jiffies.h>#include <linux/dma-mapping.h>#include <scsi/scsicam.h>#include <asm/dma.h>#include <asm/io.h>#include <asm/system.h>#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_device.h>#include <scsi/scsi_host.h>#include <scsi/scsi_tcq.h>#include "BusLogic.h"#include "FlashPoint.c"#ifndef FAILURE#define FAILURE (-1)#endifstatic struct scsi_host_template Bus_Logic_template;/*  BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver  Options specifications provided via the Linux Kernel Command Line or via  the Loadable Kernel Module Installation Facility.*/static int BusLogic_DriverOptionsCount;/*  BusLogic_DriverOptions is an array of Driver Options structures representing  BusLogic Driver Options specifications provided via the Linux Kernel Command  Line or via the Loadable Kernel Module Installation Facility.*/static struct BusLogic_DriverOptions BusLogic_DriverOptions[BusLogic_MaxHostAdapters];/*  BusLogic can be assigned a string by insmod.*/MODULE_LICENSE("GPL");#ifdef MODULEstatic char *BusLogic;module_param(BusLogic, charp, 0);#endif/*  BusLogic_ProbeOptions is a set of Probe Options to be applied across  all BusLogic Host Adapters.*/static struct BusLogic_ProbeOptions BusLogic_ProbeOptions;/*  BusLogic_GlobalOptions is a set of Global Options to be applied across  all BusLogic Host Adapters.*/static struct BusLogic_GlobalOptions BusLogic_GlobalOptions;static LIST_HEAD(BusLogic_host_list);/*  BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.*/static int BusLogic_ProbeInfoCount;/*  BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information  to be checked for potential BusLogic Host Adapters.  It is initialized by  interrogating the PCI Configuration Space on PCI machines as well as from the  list of standard BusLogic I/O Addresses.*/static struct BusLogic_ProbeInfo *BusLogic_ProbeInfoList;/*  BusLogic_CommandFailureReason holds a string identifying the reason why a  call to BusLogic_Command failed.  It is only non-NULL when BusLogic_Command  returns a failure code.*/static char *BusLogic_CommandFailureReason;/*  BusLogic_AnnounceDriver announces the Driver Version and Date, Author's  Name, Copyright Notice, and Electronic Mail Address.*/static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter){	BusLogic_Announce("***** BusLogic SCSI Driver Version " BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n", HostAdapter);	BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", HostAdapter);}/*  BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI  Driver and Host Adapter.*/static const char *BusLogic_DriverInfo(struct Scsi_Host *Host){	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;	return HostAdapter->FullModelName;}/*  BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)  for Host Adapter from the BlockSize bytes located at BlockPointer.  The newly  created CCBs are added to Host Adapter's free list.*/static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, void *BlockPointer, int BlockSize, dma_addr_t BlockPointerHandle){	struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer;	unsigned int offset = 0;	memset(BlockPointer, 0, BlockSize);	CCB->AllocationGroupHead = BlockPointerHandle;	CCB->AllocationGroupSize = BlockSize;	while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0) {		CCB->Status = BusLogic_CCB_Free;		CCB->HostAdapter = HostAdapter;		CCB->DMA_Handle = (u32) BlockPointerHandle + offset;		if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {			CCB->CallbackFunction = BusLogic_QueueCompletedCCB;			CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;		}		CCB->Next = HostAdapter->Free_CCBs;		CCB->NextAll = HostAdapter->All_CCBs;		HostAdapter->Free_CCBs = CCB;		HostAdapter->All_CCBs = CCB;		HostAdapter->AllocatedCCBs++;		CCB++;		offset += sizeof(struct BusLogic_CCB);	}}/*  BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.*/static bool __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter){	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);	void *BlockPointer;	dma_addr_t BlockPointerHandle;	while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) {		BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);		if (BlockPointer == NULL) {			BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", HostAdapter);			return false;		}		BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);	}	return true;}/*  BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter.*/static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter){	struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL;	HostAdapter->All_CCBs = NULL;	HostAdapter->Free_CCBs = NULL;	while ((CCB = NextCCB) != NULL) {		NextCCB = CCB->NextAll;		if (CCB->AllocationGroupHead) {			if (Last_CCB)				pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);			Last_CCB = CCB;		}	}	if (Last_CCB)		pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);}/*  BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter.  If  allocation fails and there are no remaining CCBs available, the Driver Queue  Depth is decreased to a known safe value to avoid potential deadlocks when  multiple host adapters share the same IRQ Channel.*/static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, bool SuccessMessageP){	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);	int PreviouslyAllocated = HostAdapter->AllocatedCCBs;	void *BlockPointer;	dma_addr_t BlockPointerHandle;	if (AdditionalCCBs <= 0)		return;	while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) {		BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);		if (BlockPointer == NULL)			break;		BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);	}	if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) {		if (SuccessMessageP)			BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", HostAdapter, HostAdapter->AllocatedCCBs - PreviouslyAllocated, HostAdapter->AllocatedCCBs);		return;	}	BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);	if (HostAdapter->DriverQueueDepth > HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) {		HostAdapter->DriverQueueDepth = HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;		HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;	}}/*  BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list,  allocating more memory from the Kernel if necessary.  The Host Adapter's  Lock should already have been acquired by the caller.*/static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter						 *HostAdapter){	static unsigned long SerialNumber = 0;	struct BusLogic_CCB *CCB;	CCB = HostAdapter->Free_CCBs;	if (CCB != NULL) {		CCB->SerialNumber = ++SerialNumber;		HostAdapter->Free_CCBs = CCB->Next;		CCB->Next = NULL;		if (HostAdapter->Free_CCBs == NULL)			BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);		return CCB;	}	BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);	CCB = HostAdapter->Free_CCBs;	if (CCB == NULL)		return NULL;	CCB->SerialNumber = ++SerialNumber;	HostAdapter->Free_CCBs = CCB->Next;	CCB->Next = NULL;	return CCB;}/*  BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's  free list.  The Host Adapter's Lock should already have been acquired by the  caller.*/static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB){	struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;	scsi_dma_unmap(CCB->Command);	pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,			 CCB->SenseDataLength, PCI_DMA_FROMDEVICE);	CCB->Command = NULL;	CCB->Status = BusLogic_CCB_Free;	CCB->Next = HostAdapter->Free_CCBs;	HostAdapter->Free_CCBs = CCB;}

⌨️ 快捷键说明

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