📄 aic7xxx.c
字号:
/*+M************************************************************************* * Adaptec AIC7xxx device driver for Linux. * * Copyright (c) 1994 John Aycock * The University of Calgary Department of Computer Science. * * 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. * * Sources include the Adaptec 1740 driver (aha1740.c), the Ultrastor 24F * driver (ultrastor.c), various Linux kernel source, the Adaptec EISA * config file (!adp7771.cfg), the Adaptec AHA-2740A Series User's Guide, * the Linux Kernel Hacker's Guide, Writing a SCSI Device Driver for Linux, * the Adaptec 1542 driver (aha1542.c), the Adaptec EISA overlay file * (adp7770.ovl), the Adaptec AHA-2740 Series Technical Reference Manual, * the Adaptec AIC-7770 Data Book, the ANSI SCSI specification, the * ANSI SCSI-2 specification (draft 10c), ... * * -------------------------------------------------------------------------- * * Modifications by Daniel M. Eischen (deischen@iworks.InterWorks.org): * * Substantially modified to include support for wide and twin bus * adapters, DMAing of SCBs, tagged queueing, IRQ sharing, bug fixes, * SCB paging, and other rework of the code. * * Parts of this driver were also based on the FreeBSD driver by * Justin T. Gibbs. His copyright follows: * * -------------------------------------------------------------------------- * Copyright (c) 1994-1997 Justin Gibbs. * All rights reserved. * * 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 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. * * $Id: aic7xxx.c,v 1.1.4.1 2004/01/16 22:41:26 roland Exp $ *--------------------------------------------------------------------------- * * Thanks also go to (in alphabetical order) the following: * * Rory Bolt - Sequencer bug fixes * Jay Estabrook - Initial DEC Alpha support * Doug Ledford - Much needed abort/reset bug fixes * Kai Makisara - DMAing of SCBs * * A Boot time option was also added for not resetting the scsi bus. * * Form: aic7xxx=extended * aic7xxx=no_reset * aic7xxx=ultra * aic7xxx=irq_trigger:[0,1] # 0 edge, 1 level * aic7xxx=verbose * * Daniel M. Eischen, deischen@iworks.InterWorks.org, 1/23/97 * *-M*************************************************************************//*+M************************************************************************** * * Further driver modifications made by Doug Ledford <dledford@redhat.com> * * Copyright (c) 1997-1998 Doug Ledford * * These changes are released under the same licensing terms as the FreeBSD * driver written by Justin Gibbs. Please see his Copyright notice above * for the exact terms and conditions covering my changes as well as the * warranty statement. * * Modifications made to the aic7xxx.c,v 4.1 driver from Dan Eischen include * but are not limited to: * * 1: Import of the latest FreeBSD sequencer code for this driver * 2: Modification of kernel code to accomodate different sequencer semantics * 3: Extensive changes throughout kernel portion of driver to improve * abort/reset processing and error hanndling * 4: Other work contributed by various people on the Internet * 5: Changes to printk information and verbosity selection code * 6: General reliability related changes, especially in IRQ management * 7: Modifications to the default probe/attach order for supported cards * 8: SMP friendliness has been improved * * Overall, this driver represents a significant departure from the official * aic7xxx driver released by Dan Eischen in two ways. First, in the code * itself. A diff between the two version of the driver is now a several * thousand line diff. Second, in approach to solving the same problem. The * problem is importing the FreeBSD aic7xxx driver code to linux can be a * difficult and time consuming process, that also can be error prone. Dan * Eischen's official driver uses the approach that the linux and FreeBSD * drivers should be as identical as possible. To that end, his next version * of this driver will be using a mid-layer code library that he is developing * to moderate communications between the linux mid-level SCSI code and the * low level FreeBSD driver. He intends to be able to essentially drop the * FreeBSD driver into the linux kernel with only a few minor tweaks to some * include files and the like and get things working, making for fast easy * imports of the FreeBSD code into linux. * * I disagree with Dan's approach. Not that I don't think his way of doing * things would be nice, easy to maintain, and create a more uniform driver * between FreeBSD and Linux. I have no objection to those issues. My * disagreement is on the needed functionality. There simply are certain * things that are done differently in FreeBSD than linux that will cause * problems for this driver regardless of any middle ware Dan implements. * The biggest example of this at the moment is interrupt semantics. Linux * doesn't provide the same protection techniques as FreeBSD does, nor can * they be easily implemented in any middle ware code since they would truly * belong in the kernel proper and would effect all drivers. For the time * being, I see issues such as these as major stumbling blocks to the * reliability of code based upon such middle ware. Therefore, I choose to * use a different approach to importing the FreeBSD code that doesn't * involve any middle ware type code. My approach is to import the sequencer * code from FreeBSD wholesale. Then, to only make changes in the kernel * portion of the driver as they are needed for the new sequencer semantics. * In this way, the portion of the driver that speaks to the rest of the * linux kernel is fairly static and can be changed/modified to solve * any problems one might encounter without concern for the FreeBSD driver. * * Note: If time and experience should prove me wrong that the middle ware * code Dan writes is reliable in its operation, then I'll retract my above * statements. But, for those that don't know, I'm from Missouri (in the US) * and our state motto is "The Show-Me State". Well, before I will put * faith into it, you'll have to show me that it works :) * *_M*************************************************************************//* * The next three defines are user configurable. These should be the only * defines a user might need to get in here and change. There are other * defines buried deeper in the code, but those really shouldn't need touched * under normal conditions. *//* * AIC7XXX_FAKE_NEGOTIATION_CMDS * We now have two distinctly different methods of device negotiation * in this code. The two methods are selected by either defining or not * defining this option. The difference is as follows: * * With AIC7XXX_FAKE_NEGOTIATION_CMDS not set (commented out) * When the driver is in need of issuing a negotiation command for any * given device, it will add the negotiation message on to part of a * regular SCSI command for the device. In the process, if the device * is configured for and using tagged queueing, then the code will * also issue that single command as a non-tagged command, attach the * negotiation message to that one command, and use a temporary * queue depth of one to keep the untagged and tagged commands from * overlapping. * Pros: This doesn't use any extra SCB structures, it's simple, it * works most of the time (if not all of the time now), and * since we get the device capability info frmo the INQUIRY data * now, shouldn't cause any problems. * Cons: When we need to send a negotiation command to a device, we * must use a command that is being sent to LUN 0 of the device. * If we try sending one to high LUN numbers, then some devices * get noticeably upset. Since we have to wait for a command with * LUN == 0 to come along, we may not be able to renegotiate when * we want if the user is actually using say LUN 1 of a CD Changer * instead of using LUN 0 for an extended period of time. * * With AIC7XXX_FAKE_NEGOTIATION_CMDS defined * When we need to negotiate with a device, instead of attaching our * negotiation message to an existing command, we insert our own * fictional Scsi_Cmnd into the chain that has the negotiation message * attached to it. We send this one command as untagged regardless * of the device type, and we fiddle with the queue depth the same as * we would with the option unset to avoid overlapping commands. The * primary difference between this and the unset option is that the * negotiation message is no longer attached to a specific command, * instead it is its own command and is merely triggered by a * combination of both A) We need to negotiate and B) The mid level * SCSI code has sent us a command. We still don't do any negotiation * unless there is a valid SCSI command to be processed. * Pros: This fixes the problem above in the Cons section. Since we * issue our own fake command, we can set the LUN to 0 regardless * of what the LUN is in the real command. It also means that if * the device get's nasty over negotiation issues, it won't be * showing up on a regular command, so we won't get any SENSE buffer * data or STATUS_BYTE returns to the mid level code that are caused * by snits in the negotiation code. * Cons: We add more code, and more complexity. This means more ways * in which things could break. It means a larger driver. It means * more resource consumption for the fake commands. However, the * biggest problem is this. Take a system where there is a CD-ROM * on the SCSI bus. Someone has a CD in the CD-ROM and is using it. * For some reason the SCSI bus gets reset. We don't touch the * CD-ROM again for quite a period of time (so we don't renegotiate * after the reset until we do touch the CD-ROM again). In the * time while we aren't using the CD-ROM, the current disc is * removed and a new one put in. When we go to check that disc, we * will first have to renegotiate. In so doing, we issue our fake * SCSI command, which happens to be TEST_UNIT_READY. The CD-ROM * negotiates with us, then responds to our fake command with a * CHECK_CONDITION status. We REQUEST_SENSE from the CD-ROM, it * then sends the SENSE data to our fake command to tell it that * it has been through a disc change. There, now we've cleared out * the SENSE data along with our negotiation command, and when the * real command executes, it won't pick up that the CD was changed. * That's the biggest Con to this approach. In the future, I could * probably code around this problem though, so this option is still * viable. * * So, which command style should you use? I would appreciate it if people * could try out both types. I want to know about any cases where one * method works and the other doesn't. If one method works on significantly * more systems than another, then it will become the default. If the second * option turns out to work best, then I'll find a way to work around that * big con I listed. * * -- July 7, 02:33 * OK...I just added some code that should make the Con listed for the * fake commands a non issue now. However, it needs testing. For now, * I'm going to make the default to use the fake commands, we'll see how * it goes. */#define AIC7XXX_FAKE_NEGOTIATION_CMDS/* * AIC7XXX_STRICT_PCI_SETUP * Should we assume the PCI config options on our controllers are set with * sane and proper values, or should we be anal about our PCI config * registers and force them to what we want? The main advantage to * defining this option is on non-Intel hardware where the BIOS may not * have been run to set things up, or if you have one of the BIOSless * Adaptec controllers, such as a 2910, that don't get set up by the * BIOS. However, keep in mind that we really do set the most important * items in the driver regardless of this setting, this only controls some * of the more esoteric PCI options on these cards. In that sense, I * would default to leaving this off. However, if people wish to try * things both ways, that would also help me to know if there are some * machines where it works one way but not another. * * -- July 7, 17:09 * OK...I need this on my machine for testing, so the default is to * leave it defined. * * -- July 7, 18:49 * I needed it for testing, but it didn't make any difference, so back * off she goes. * * -- July 16, 23:04 * I turned it back on to try and compensate for the 2.1.x PCI code * which no longer relies solely on the BIOS and now tries to set * things itself. */#define AIC7XXX_STRICT_PCI_SETUP/* * AIC7XXX_VERBOSE_DEBUGGING * This option enables a lot of extra printk();s in the code, surrounded * by if (aic7xxx_verbose ...) statements. Executing all of those if * statements and the extra checks can get to where it actually does have * an impact on CPU usage and such, as well as code size. Disabling this * define will keep some of those from becoming part of the code. * * NOTE: Currently, this option has no real effect, I will be adding the * various #ifdef's in the code later when I've decided a section is * complete and no longer needs debugging. OK...a lot of things are now * surrounded by this define, so turning this off does have an impact. *//* * #define AIC7XXX_VERBOSE_DEBUGGING */#if defined(MODULE) || defined(PCMCIA)#include <linux/module.h>#endif#if defined(PCMCIA)# undef MODULE#endif#include <stdarg.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/byteorder.h>#include <linux/version.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/kernel.h>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -