ini9100u.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 728 行 · 第 1/2 页
C
728 行
/************************************************************************** * Initio 9100 device driver for Linux. * * Copyright (c) 1994-1998 Initio Corporation * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl> * All rights reserved. * * 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, 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; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * -------------------------------------------------------------------------- * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Where this Software is combined with software released under the terms of * the GNU General Public License ("GPL") and the terms of the GPL would require the * combined work to also be released under the terms of the GPL, the terms * and conditions of this License will apply in addition to those of the * GPL with the exception of any terms or conditions of this License that * conflict with, or are expressly prohibited by, the GPL. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ************************************************************************* * * DESCRIPTION: * * This is the Linux low-level SCSI driver for Initio INI-9X00U/UW SCSI host * adapters * * 08/06/97 hc - v1.01h * - Support inic-940 and inic-935 * 09/26/97 hc - v1.01i * - Make correction from J.W. Schultz suggestion * 10/13/97 hc - Support reset function * 10/21/97 hc - v1.01j * - Support 32 LUN (SCSI 3) * 01/14/98 hc - v1.01k * - Fix memory allocation problem * 03/04/98 hc - v1.01l * - Fix tape rewind which will hang the system problem * - Set can_queue to tul_num_scb * 06/25/98 hc - v1.01m * - Get it work for kernel version >= 2.1.75 * - Dynamic assign SCSI bus reset holding time in init_tulip() * 07/02/98 hc - v1.01n * - Support 0002134A * 08/07/98 hc - v1.01o * - Change the tul_abort_srb routine to use scsi_done. <01> * 09/07/98 hl - v1.02 * - Change the INI9100U define and proc_dir_entry to * reflect the newer Kernel 2.1.118, but the v1.o1o * should work with Kernel 2.1.118. * 09/20/98 wh - v1.02a * - Support Abort command. * - Handle reset routine. * 09/21/98 hl - v1.03 * - remove comments. * 12/09/98 bv - v1.03a * - Removed unused code * 12/13/98 bv - v1.03b * - Remove cli() locking for kernels >= 2.1.95. This uses * spinlocks to serialize access to the pSRB_head and * pSRB_tail members of the HCS structure. * 09/01/99 bv - v1.03d * - Fixed a deadlock problem in SMP. * 21/01/99 bv - v1.03e * - Add support for the Domex 3192U PCI SCSI * This is a slightly modified patch by * Brian Macy <bmacy@sunshinecomputing.com> * 22/02/99 bv - v1.03f * - Didn't detect the INIC-950 in 2.0.x correctly. * Now fixed. * 05/07/99 bv - v1.03g * - Changed the assumption that HZ = 100 * 10/17/03 mc - v1.04 * - added new DMA API support * 06/01/04 jmd - v1.04a * - Re-add reset_bus support **************************************************************************/#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)#ifndef LINUX_VERSION_CODE#include <linux/version.h>#endif#include <linux/module.h>#include <linux/errno.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/blkdev.h>#include <linux/spinlock.h>#include <linux/stat.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/proc_fs.h>#include <linux/string.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/slab.h>#include <asm/io.h>#include "scsi.h"#include <scsi/scsi_host.h>#include "ini9100u.h"#ifdef DEBUG_i91uunsigned int i91u_debug = DEBUG_DEFAULT;#endifstatic Scsi_Host_Template driver_template = { .proc_name = "INI9100U", .name = i91u_REVID, .detect = i91u_detect, .release = i91u_release, .queuecommand = i91u_queue,// .abort = i91u_abort,// .reset = i91u_reset, .eh_bus_reset_handler = i91u_bus_reset, .bios_param = i91u_biosparam, .can_queue = 1, .this_id = 1, .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING,};#include "scsi_module.c"char *i91uCopyright = "Copyright (C) 1996-98";char *i91uInitioName = "by Initio Corporation";char *i91uProductName = "INI-9X00U/UW";char *i91uVersion = "v1.04a";#define TULSZ(sz) (sizeof(sz) / sizeof(sz[0]))#define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))/* set by i91_setup according to the command line */static int setup_called = 0;static int tul_num_ch = 4; /* Maximum 4 adapters */static int tul_num_scb;static int tul_tag_enable = 1;static SCB *tul_scb;#ifdef DEBUG_i91ustatic int setup_debug = 0;#endifstatic char *setup_str = (char *) NULL;static void i91u_panic(char *msg);static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); /* ---- EXTERNAL FUNCTIONS ---- */ /* Get total number of adapters */extern void init_i91uAdapter_table(void);extern int Addi91u_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE);extern int tul_ReturnNumberOfAdapters(void);extern void get_tulipPCIConfig(HCS * pHCB, int iChannel_index);extern int init_tulip(HCS * pHCB, SCB * pSCB, int tul_num_scb, BYTE * pbBiosAdr, int reset_time);extern SCB *tul_alloc_scb(HCS * pHCB);extern int tul_abort_srb(HCS * pHCB, Scsi_Cmnd * pSRB);extern void tul_exec_scb(HCS * pHCB, SCB * pSCB);extern void tul_release_scb(HCS * pHCB, SCB * pSCB);extern void tul_stop_bm(HCS * pHCB);extern int tul_reset_scsi(HCS * pCurHcb, int seconds);extern int tul_isr(HCS * pHCB);extern int tul_reset(HCS * pHCB, Scsi_Cmnd * pSRB, unsigned char target);extern int tul_reset_scsi_bus(HCS * pCurHcb);extern int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags); /* ---- EXTERNAL VARIABLES ---- */extern HCS tul_hcs[];const PCI_ID i91u_pci_devices[] = { { INI_VENDOR_ID, I950_DEVICE_ID }, { INI_VENDOR_ID, I940_DEVICE_ID }, { INI_VENDOR_ID, I935_DEVICE_ID }, { INI_VENDOR_ID, I920_DEVICE_ID }, { DMX_VENDOR_ID, I920_DEVICE_ID },};/* * queue services: *//***************************************************************************** Function name : i91uAppendSRBToQueue Description : This function will push current request into save list Input : pSRB - Pointer to SCSI request block. pHCB - Pointer to host adapter structure Output : None. Return : None.*****************************************************************************/static void i91uAppendSRBToQueue(HCS * pHCB, Scsi_Cmnd * pSRB){ ULONG flags; spin_lock_irqsave(&(pHCB->pSRB_lock), flags); pSRB->host_scribble = NULL; /* Pointer to next */ if (pHCB->pSRB_head == NULL) pHCB->pSRB_head = pSRB; else pHCB->pSRB_tail->host_scribble = (char *)pSRB; /* Pointer to next */ pHCB->pSRB_tail = pSRB; spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); return;}/***************************************************************************** Function name : i91uPopSRBFromQueue Description : This function will pop current request from save list Input : pHCB - Pointer to host adapter structure Output : None. Return : pSRB - Pointer to SCSI request block.*****************************************************************************/static Scsi_Cmnd *i91uPopSRBFromQueue(HCS * pHCB){ Scsi_Cmnd *pSRB; ULONG flags; spin_lock_irqsave(&(pHCB->pSRB_lock), flags); if ((pSRB = pHCB->pSRB_head) != NULL) { pHCB->pSRB_head = (struct scsi_cmnd *)pHCB->pSRB_head->host_scribble; pSRB->host_scribble = NULL; } spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags); return (pSRB);}static irqreturn_t i91u_intr(int irqno, void *dev_id, struct pt_regs *regs){ struct Scsi_Host *dev = dev_id; unsigned long flags; spin_lock_irqsave(dev->host_lock, flags); tul_isr((HCS *)dev->base); spin_unlock_irqrestore(dev->host_lock, flags); return IRQ_HANDLED;}/* called from init/main.c */void i91u_setup(char *str, int *ints){ if (setup_called) i91u_panic("i91u: i91u_setup called twice.\n"); setup_called = ints[0]; setup_str = str;#ifdef DEBUG_i91u setup_debug = ints[0] >= 1 ? ints[1] : DEBUG_DEFAULT;#endif}int tul_NewReturnNumberOfAdapters(void){ struct pci_dev *pDev = NULL; /* Start from none */ int iAdapters = 0; long dRegValue; WORD wBIOS; int i = 0; init_i91uAdapter_table(); for (i = 0; i < TULSZ(i91u_pci_devices); i++) { while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) { if (pci_enable_device(pDev)) continue; pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); wBIOS = (UWORD) (dRegValue & 0xFF); if (((dRegValue & 0xFF00) >> 8) == 0xFF) dRegValue = 0; wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); if (pci_set_dma_mask(pDev, 0xffffffff)) { printk(KERN_WARNING "i91u: Could not set 32 bit DMA mask\n"); continue; } if (Addi91u_into_Adapter_table(wBIOS, (pDev->resource[0].start), pDev->irq, pDev->bus->number, (pDev->devfn >> 3) ) == 0) iAdapters++; } } return (iAdapters);}int i91u_detect(Scsi_Host_Template * tpnt){ HCS *pHCB; struct Scsi_Host *hreg; unsigned long i; /* 01/14/98 */ int ok = 0, iAdapters; ULONG dBiosAdr; BYTE *pbBiosAdr; tpnt->proc_name = "INI9100U"; if (setup_called) { /* Setup by i91u_setup */ printk("i91u: processing commandline: ");#ifdef DEBUG_i91u if (setup_called > 1) { printk("\ni91u: %s\n", setup_str); printk("i91u: usage: i91u[=<DEBUG>]\n"); i91u_panic("i91u panics in line %d", __LINE__); } i91u_debug = setup_debug;#endif } /* Get total number of adapters in the motherboard */ iAdapters = tul_NewReturnNumberOfAdapters(); if (iAdapters == 0) /* If no tulip founded, return */ return (0); tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters; /* Update actually channel number */ if (tul_tag_enable) { /* 1.01i */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?