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

📄 dpt_i2o.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************                          dpti.c  -  description                             -------------------    begin                : Thu Sep 7 2000    copyright            : (C) 2000 by Adaptec    email                : deanna_bonds@adaptec.com    			   July 30, 2001 First version being submitted			   for inclusion in the kernel.  V2.4    See README.dpti for history, notes, license info, and credits ***************************************************************************//*************************************************************************** *                                                                         * *   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.                                   * *                                                                         * ***************************************************************************///#define DEBUG 1//#define UARTDELAY 1// On the real kernel ADDR32 should always be zero for 2.4. GFP_HIGH allocates// high pages. Keep the macro around because of the broken unmerged ia64 tree#define ADDR32 (0)#include <linux/version.h>#include <linux/module.h>MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn");MODULE_DESCRIPTION("Adaptec I2O RAID Driver");////////////////////////////////////////////////////////////////#include <linux/ioctl.h>	/* For SCSI-Passthrough */#include <asm/uaccess.h>#include <linux/stat.h>#include <linux/slab.h>		/* for kmalloc() */#include <linux/config.h>	/* for CONFIG_PCI */#include <linux/pci.h>		/* for PCI support */#include <linux/proc_fs.h>#include <linux/blk.h>#include <linux/delay.h>	/* for udelay */#include <linux/tqueue.h>#include <linux/interrupt.h>#include <linux/kernel.h>	/* for printk */#include <linux/sched.h>#include <linux/reboot.h>#include <linux/smp_lock.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/ioport.h>#include <linux/stat.h>#include <asm/processor.h>	/* for boot_cpu_data */#include <asm/pgtable.h>#include <asm/io.h>		/* for virt_to_bus, etc. */#include "scsi.h"#include "hosts.h"#include "sd.h"#include "dpt/dptsig.h"#include "dpti.h"/*============================================================================ * Create a binary signature - this is read by dptsig * Needed for our management apps *============================================================================ */static dpt_sig_S DPTI_sig = {	{'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION,#ifdef __i386__	PROC_INTEL, PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM,#elif defined(__ia64__)	PROC_INTEL, PROC_IA64,#elif defined(__sparc__)	PROC_ULTRASPARC,#elif defined(__alpha__)	PROC_ALPHA ,#else	(-1),#endif	 FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL,	ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION,	DPT_MONTH, DPT_DAY, DPT_YEAR, "Adaptec Linux I2O RAID Driver"};/*============================================================================ * Globals *============================================================================ */DECLARE_MUTEX(adpt_configuration_lock);static struct i2o_sys_tbl *sys_tbl = NULL;static int sys_tbl_ind = 0;static int sys_tbl_len = 0;static adpt_hba* hbas[DPTI_MAX_HBA];static adpt_hba* hba_chain = NULL;static int hba_count = 0;// Debug flags to be put into the HBA flags field when initialized// Make sure to enable DEBUG_PRINT for these flags to workstatic unsigned long DebugFlags = HBA_FLAGS_DBG_SCAN_B | HBA_FLAGS_DBG_FLAGS_MASK;static struct file_operations adpt_fops = {	ioctl: adpt_ioctl,	open: adpt_open,	release: adpt_close};#ifdef REBOOT_NOTIFIERstatic struct notifier_block adpt_reboot_notifier ={	 adpt_reboot_event,	 NULL,	 0};#endif/* Structures and definitions for synchronous message posting. * See adpt_i2o_post_wait() for description * */struct adpt_i2o_post_wait_data{	int status;	u32 id;	adpt_wait_queue_head_t *wq;	struct adpt_i2o_post_wait_data *next;};static struct adpt_i2o_post_wait_data *adpt_post_wait_queue = NULL;static u32 adpt_post_wait_id = 0;static spinlock_t adpt_post_wait_lock = SPIN_LOCK_UNLOCKED;/*============================================================================ * 				Functions *============================================================================ */static u8 adpt_read_blink_led(adpt_hba* host){	if(host->FwDebugBLEDflag_P != 0) {		if( readb(host->FwDebugBLEDflag_P) == 0xbc ){			return readb(host->FwDebugBLEDvalue_P);		}	}	return 0;}/*============================================================================ * Scsi host template interface functions *============================================================================ */static struct pci_device_id dptids[] = {	{ PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},	{ PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},	{ 0, }};MODULE_DEVICE_TABLE(pci,dptids);static int adpt_detect(Scsi_Host_Template* sht){	struct pci_dev *pDev = NULL;	adpt_hba* pHba;	adpt_init();	sht->use_new_eh_code = 1;	PINFO("Detecting Adaptec I2O RAID controllers...\n");        /* search for all Adatpec I2O RAID cards */	while ((pDev = pci_find_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) {		if(pDev->device == PCI_DPT_DEVICE_ID ||		   pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){			if(adpt_install_hba(sht, pDev) ){				PERROR("Could not Init an I2O RAID device\n");				PERROR("Will not try to detect others.\n");				return hba_count-1;			}		}	}	/* In INIT state, Activate IOPs */	for (pHba = hba_chain; pHba; pHba = pHba->next) {		// Activate does get status , init outbound, and get hrt		if (adpt_i2o_activate_hba(pHba) < 0) {			adpt_i2o_delete_hba(pHba);		}	}	/* Active IOPs in HOLD state */rebuild_sys_tab:	if (hba_chain == NULL) 		return 0;	/*	 * If build_sys_table fails, we kill everything and bail	 * as we can't init the IOPs w/o a system table	 */		if (adpt_i2o_build_sys_table() < 0) {		adpt_i2o_sys_shutdown();		return 0;	}	PDEBUG("HBA's in HOLD state\n");	/* If IOP don't get online, we need to rebuild the System table */	for (pHba = hba_chain; pHba; pHba = pHba->next) {		if (adpt_i2o_online_hba(pHba) < 0) {			adpt_i2o_delete_hba(pHba);				goto rebuild_sys_tab;		}	}	/* Active IOPs now in OPERATIONAL state */	PDEBUG("HBA's in OPERATIONAL state\n");	printk(KERN_INFO"dpti: If you have a lot of devices this could take a few minutes.\n");	for (pHba = hba_chain; pHba; pHba = pHba->next) {		printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name);		if (adpt_i2o_lct_get(pHba) < 0){			adpt_i2o_delete_hba(pHba);			continue;		}		if (adpt_i2o_parse_lct(pHba) < 0){			adpt_i2o_delete_hba(pHba);			continue;		}		adpt_inquiry(pHba);	}	for (pHba = hba_chain; pHba; pHba = pHba->next) {		if( adpt_scsi_register(pHba,sht) < 0){			adpt_i2o_delete_hba(pHba);			continue;		}		pHba->initialized = TRUE;		pHba->state &= ~DPTI_STATE_RESET;	}	// Register our control device node	// nodes will need to be created in /dev to access this	// the nodes can not be created from within the driver	if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) {		adpt_i2o_sys_shutdown();		return 0;	}	return hba_count;}/* * scsi_unregister will be called AFTER we return.  */static int adpt_release(struct Scsi_Host *host){	adpt_hba* pHba = (adpt_hba*) host->hostdata[0];//	adpt_i2o_quiesce_hba(pHba);	adpt_i2o_delete_hba(pHba);	return 0;}static void adpt_inquiry(adpt_hba* pHba){	u32 msg[14]; 	u32 *mptr;	u32 *lenptr;	int direction;	int scsidir;	u32 len;	u32 reqlen;	u8* buf;	u8  scb[16];	s32 rcode;	memset(msg, 0, sizeof(msg));	buf = (u8*)kmalloc(80,GFP_KERNEL|ADDR32);	if(!buf){		printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name);		return;	}	memset((void*)buf, 0, 36);		len = 36;	direction = 0x00000000;		scsidir  =0x40000000;	// DATA IN  (iop<--dev)	reqlen = 14;		// SINGLE SGE	/* Stick the headers on */	msg[0] = reqlen<<16 | SGL_OFFSET_12;	msg[1] = (0xff<<24|HOST_TID<<12|ADAPTER_TID);	msg[2] = 0;	msg[3]  = 0;	// Adaptec/DPT Private stuff 	msg[4] = I2O_CMD_SCSI_EXEC|DPT_ORGANIZATION_ID<<16;	msg[5] = ADAPTER_TID | 1<<16 /* Interpret*/;	/* Direction, disconnect ok | sense data | simple queue , CDBLen */	// I2O_SCB_FLAG_ENABLE_DISCONNECT | 	// I2O_SCB_FLAG_SIMPLE_QUEUE_TAG | 	// I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE;	msg[6] = scsidir|0x20a00000| 6 /* cmd len*/;	mptr=msg+7;	memset(scb, 0, sizeof(scb));	// Write SCSI command into the message - always 16 byte block 	scb[0] = INQUIRY;	scb[1] = 0;	scb[2] = 0;	scb[3] = 0;	scb[4] = 36;	scb[5] = 0;	// Don't care about the rest of scb	memcpy(mptr, scb, sizeof(scb));	mptr+=4;	lenptr=mptr++;		/* Remember me - fill in when we know */	/* Now fill in the SGList and command */	*lenptr = len;	*mptr++ = 0xD0000000|direction|len;	*mptr++ = virt_to_bus(buf);	// Send it on it's way	rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120);	if (rcode != 0) {		sprintf(pHba->detail, "Adaptec I2O RAID");		printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode);	} else {		memset(pHba->detail, 0, sizeof(pHba->detail));		memcpy(&(pHba->detail), "Vendor: Adaptec ", 16);		memcpy(&(pHba->detail[16]), " Model: ", 8);		memcpy(&(pHba->detail[24]), (u8*) &buf[16], 16);		memcpy(&(pHba->detail[40]), " FW: ", 4);		memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4);		pHba->detail[48] = '\0';	/* precautionary */	}	kfree(buf);	adpt_i2o_status_get(pHba);	return ;}static void adpt_select_queue_depths(struct Scsi_Host *host, Scsi_Device * devicelist){	Scsi_Device *device;	/* scsi layer per device information */	adpt_hba* pHba;	pHba = (adpt_hba *) host->hostdata[0];	for (device = devicelist; device != NULL; device = device->next) {		if (device->host != host) {			continue;		}		if (host->can_queue) {			device->queue_depth =  host->can_queue - 1;		} else {			device->queue_depth = 1;		}	}}static int adpt_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)){	adpt_hba* pHba = NULL;	struct adpt_device* pDev = NULL;	/* dpt per device information */	ulong timeout = jiffies + (TMOUT_SCSI*HZ);	cmd->scsi_done = done;	/*	 * SCSI REQUEST_SENSE commands will be executed automatically by the 	 * Host Adapter for any errors, so they should not be executed 	 * explicitly unless the Sense Data is zero indicating that no error 	 * occurred.	 */	if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) {		cmd->result = (DID_OK << 16);		cmd->scsi_done(cmd);		return 0;	}	pHba = (adpt_hba*)cmd->host->hostdata[0];	if (!pHba) {		return FAILED;	}	rmb();	/*	 * TODO: I need to block here if I am processing ioctl cmds	 * but if the outstanding cmds all finish before the ioctl,	 * the scsi-core will not know to start sending cmds to me again.	 * I need to a way to restart the scsi-cores queues or should I block	 * calling scsi_done on the outstanding cmds instead	 * for now we don't set the IOCTL state	 */	if(((pHba->state) & DPTI_STATE_IOCTL) || ((pHba->state) & DPTI_STATE_RESET)) {		pHba->host->last_reset = jiffies;		pHba->host->resetting = 1;		return 1;	}	if(cmd->eh_state != SCSI_STATE_QUEUED){		// If we are not doing error recovery		mod_timer(&cmd->eh_timeout, timeout);	}	// TODO if the cmd->device if offline then I may need to issue a bus rescan	// followed by a get_lct to see if the device is there anymore	if((pDev = (struct adpt_device*) (cmd->device->hostdata)) == NULL) {		/*		 * First command request for this device.  Set up a pointer		 * to the device structure.  This should be a TEST_UNIT_READY		 * command from scan_scsis_single.		 */		if ((pDev = adpt_find_device(pHba, (u32)cmd->channel, (u32)cmd->target, (u32)cmd-> lun)) == NULL) {			// TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response 			// with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue.			cmd->result = (DID_NO_CONNECT << 16);			cmd->scsi_done(cmd);			return 0;		}		(struct adpt_device*)(cmd->device->hostdata) = pDev;	}	pDev->pScsi_dev = cmd->device;	/*	 * If we are being called from when the device is being reset, 	 * delay processing of the command until later.	 */	if (pDev->state & DPTI_DEV_RESET ) {		return FAILED;	}	return adpt_scsi_to_i2o(pHba, cmd, pDev);}static int adpt_bios_param(Disk* disk, kdev_t dev, int geom[]){	int heads=-1;	int sectors=-1;	int cylinders=-1;	// *** First lets set the default geometry ****		// If the capacity is less than ox2000	if (disk->capacity < 0x2000 ) {	// floppy		heads = 18;		sectors = 2;	} 	// else if between 0x2000 and 0x20000	else if (disk->capacity < 0x20000) {		heads = 64;		sectors = 32;	}	// else if between 0x20000 and 0x40000	else if (disk->capacity < 0x40000) {		heads = 65;		sectors = 63;	}	// else if between 0x4000 and 0x80000	else if (disk->capacity < 0x80000) {		heads = 128;		sectors = 63;	}	// else if greater than 0x80000	else {		heads = 255;		sectors = 63;	}	cylinders = disk->capacity / (heads * sectors);	// Special case if CDROM	if(disk->device->type == 5) {  // CDROM		heads = 252;		sectors = 63;		cylinders = 1111;	}	geom[0] = heads;	geom[1] = sectors;

⌨️ 快捷键说明

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