📄 aic7xxx.c
字号:
static unsigned int aic7xxx_no_reset = 0;/* * Certain PCI motherboards will scan PCI devices from highest to lowest, * others scan from lowest to highest, and they tend to do all kinds of * strange things when they come into contact with PCI bridge chips. The * net result of all this is that the PCI card that is actually used to boot * the machine is very hard to detect. Most motherboards go from lowest * PCI slot number to highest, and the first SCSI controller found is the * one you boot from. The only exceptions to this are when a controller * has its BIOS disabled. So, we by default sort all of our SCSI controllers * from lowest PCI slot number to highest PCI slot number. We also force * all controllers with their BIOS disabled to the end of the list. This * works on *almost* all computers. Where it doesn't work, we have this * option. Setting this option to non-0 will reverse the order of the sort * to highest first, then lowest, but will still leave cards with their BIOS * disabled at the very end. That should fix everyone up unless there are * really strange cirumstances. */static int aic7xxx_reverse_scan = 0;/* * Should we force EXTENDED translation on a controller. * 0 == Use whatever is in the SEEPROM or default to off * 1 == Use whatever is in the SEEPROM or default to on */static unsigned int aic7xxx_extended = 0;/* * The IRQ trigger method used on EISA controllers. Does not effect PCI cards. * -1 = Use detected settings. * 0 = Force Edge triggered mode. * 1 = Force Level triggered mode. */static int aic7xxx_irq_trigger = -1;/* * This variable is used to override the termination settings on a controller. * This should not be used under normal conditions. However, in the case * that a controller does not have a readable SEEPROM (so that we can't * read the SEEPROM settings directly) and that a controller has a buggered * version of the cable detection logic, this can be used to force the * correct termination. It is preferable to use the manual termination * settings in the BIOS if possible, but some motherboard controllers store * those settings in a format we can't read. In other cases, auto term * should also work, but the chipset was put together with no auto term * logic (common on motherboard controllers). In those cases, we have * 32 bits here to work with. That's good for 8 controllers/channels. The * bits are organized as 4 bits per channel, with scsi0 getting the lowest * 4 bits in the int. A 1 in a bit position indicates the termination setting * that corresponds to that bit should be enabled, a 0 is disabled. * It looks something like this: * * 0x0f = 1111-Single Ended Low Byte Termination on/off * ||\-Single Ended High Byte Termination on/off * |\-LVD Low Byte Termination on/off * \-LVD High Byte Termination on/off * * For non-Ultra2 controllers, the upper 2 bits are not important. So, to * enable both high byte and low byte termination on scsi0, I would need to * make sure that the override_term variable was set to 0x03 (bits 0011). * To make sure that all termination is enabled on an Ultra2 controller at * scsi2 and only high byte termination on scsi1 and high and low byte * termination on scsi0, I would set override_term=0xf23 (bits 1111 0010 0011) * * For the most part, users should never have to use this, that's why I * left it fairly cryptic instead of easy to understand. If you need it, * most likely someone will be telling you what your's needs to be set to. */static int aic7xxx_override_term = -1;/* * Certain motherboard chipset controllers tend to screw * up the polarity of the term enable output pin. Use this variable * to force the correct polarity for your system. This is a bitfield variable * similar to the previous one, but this one has one bit per channel instead * of four. * 0 = Force the setting to active low. * 1 = Force setting to active high. * Most Adaptec cards are active high, several motherboards are active low. * To force a 2940 card at SCSI 0 to active high and a motherboard 7895 * controller at scsi1 and scsi2 to active low, and a 2910 card at scsi3 * to active high, you would need to set stpwlev=0x9 (bits 1001). * * People shouldn't need to use this, but if you are experiencing lots of * SCSI timeout problems, this may help. There is one sure way to test what * this option needs to be. Using a boot floppy to boot the system, configure * your system to enable all SCSI termination (in the Adaptec SCSI BIOS) and * if needed then also pass a value to override_term to make sure that the * driver is enabling SCSI termination, then set this variable to either 0 * or 1. When the driver boots, make sure there are *NO* SCSI cables * connected to your controller. If it finds and inits the controller * without problem, then the setting you passed to stpwlev was correct. If * the driver goes into a reset loop and hangs the system, then you need the * other setting for this variable. If neither setting lets the machine * boot then you have definite termination problems that may not be fixable. */static int aic7xxx_stpwlev = -1;/* * Set this to non-0 in order to force the driver to panic the kernel * and print out debugging info on a SCSI abort or reset cycle. */static int aic7xxx_panic_on_abort = 0;/* * PCI bus parity checking of the Adaptec controllers. This is somewhat * dubious at best. To my knowledge, this option has never actually * solved a PCI parity problem, but on certain machines with broken PCI * chipset configurations, it can generate tons of false error messages. * It's included in the driver for completeness. * 0 = Shut off PCI parity check * -1 = Normal polarity pci parity checking * 1 = reverse polarity pci parity checking * * NOTE: you can't actually pass -1 on the lilo prompt. So, to set this * variable to -1 you would actually want to simply pass the variable * name without a number. That will invert the 0 which will result in * -1. */static int aic7xxx_pci_parity = 0;/* * Set this to any non-0 value to cause us to dump the contents of all * the card's registers in a hex dump format tailored to each model of * controller. * * NOTE: THE CONTROLLER IS LEFT IN AN UNUSEABLE STATE BY THIS OPTION. * YOU CANNOT BOOT UP WITH THIS OPTION, IT IS FOR DEBUGGING PURPOSES * ONLY */static int aic7xxx_dump_card = 0;/* * Set this to a non-0 value to make us dump out the 32 bit instruction * registers on the card after completing the sequencer download. This * allows the actual sequencer download to be verified. It is possible * to use this option and still boot up and run your system. This is * only intended for debugging purposes. */static int aic7xxx_dump_sequencer = 0;/* * Certain newer motherboards have put new PCI based devices into the * IO spaces that used to typically be occupied by VLB or EISA cards. * This overlap can cause these newer motherboards to lock up when scanned * for older EISA and VLB devices. Setting this option to non-0 will * cause the driver to skip scanning for any VLB or EISA controllers and * only support the PCI controllers. NOTE: this means that if the kernel * os compiled with PCI support disabled, then setting this to non-0 * would result in never finding any devices :) */static int aic7xxx_no_probe = 0;/* * So that insmod can find the variable and make it point to something */#ifdef MODULEstatic char * aic7xxx = NULL;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,18)MODULE_PARM(aic7xxx, "s");#endif/* * Just in case someone uses commas to separate items on the insmod * command line, we define a dummy buffer here to avoid having insmod * write wild stuff into our code segment */static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n";#endif#define VERBOSE_NORMAL 0x0000#define VERBOSE_NEGOTIATION 0x0001#define VERBOSE_SEQINT 0x0002#define VERBOSE_SCSIINT 0x0004#define VERBOSE_PROBE 0x0008#define VERBOSE_PROBE2 0x0010#define VERBOSE_NEGOTIATION2 0x0020#define VERBOSE_MINOR_ERROR 0x0040#define VERBOSE_TRACING 0x0080#define VERBOSE_ABORT 0x0f00#define VERBOSE_ABORT_MID 0x0100#define VERBOSE_ABORT_FIND 0x0200#define VERBOSE_ABORT_PROCESS 0x0400#define VERBOSE_ABORT_RETURN 0x0800#define VERBOSE_RESET 0xf000#define VERBOSE_RESET_MID 0x1000#define VERBOSE_RESET_FIND 0x2000#define VERBOSE_RESET_PROCESS 0x4000#define VERBOSE_RESET_RETURN 0x8000static int aic7xxx_verbose = VERBOSE_NORMAL | VERBOSE_NEGOTIATION | VERBOSE_PROBE; /* verbose messages *//**************************************************************************** * * We're going to start putting in function declarations so that order of * functions is no longer important. As needed, they are added here. * ***************************************************************************/static void aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd);static void aic7xxx_print_card(struct aic7xxx_host *p);static void aic7xxx_print_scratch_ram(struct aic7xxx_host *p);static void aic7xxx_print_sequencer(struct aic7xxx_host *p, int downloaded);#ifdef AIC7XXX_VERBOSE_DEBUGGINGstatic void aic7xxx_check_scbs(struct aic7xxx_host *p, char *buffer);#endif/**************************************************************************** * * These functions are now used. They happen to be wrapped in useless * inb/outb port read/writes around the real reads and writes because it * seems that certain very fast CPUs have a problem dealing with us when * going at full speed. * ***************************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)static inline voidmdelay(int milliseconds){ int i; for(i=0; i<milliseconds; i++) udelay(1000);}static inline inttime_after_eq(unsigned long a, unsigned long b){ return((long)((a) - (b)) >= 0L);}static inline inttimer_pending(struct timer_list *timer){ return( timer->prev != NULL );}#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075#endifstatic inline unsigned charaic_inb(struct aic7xxx_host *p, long port){#ifdef MMAPIO unsigned char x; if(p->maddr) { x = p->maddr[port]; } else { x = inb(p->base + port); } mb(); return(x);#else return(inb(p->base + port));#endif}static inline voidaic_outb(struct aic7xxx_host *p, unsigned char val, long port){#ifdef MMAPIO if(p->maddr) { p->maddr[port] = val; } else { outb(val, p->base + port); } mb();#else outb(val, p->base + port);#endif}/*+F************************************************************************* * Function: * aic7xxx_setup * * Description: * Handle Linux boot parameters. This routine allows for assigning a value * to a parameter with a ':' between the parameter and the value. * ie. aic7xxx=unpause:0x0A,extended *-F*************************************************************************/voidaic7xxx_setup(char *s, int *dummy){ int i, n; char *p; char *end; static struct { const char *name; unsigned int *flag; } options[] = { { "extended", &aic7xxx_extended }, { "no_reset", &aic7xxx_no_reset }, { "irq_trigger", &aic7xxx_irq_trigger }, { "verbose", &aic7xxx_verbose }, { "reverse_scan",&aic7xxx_reverse_scan }, { "override_term", &aic7xxx_override_term }, { "stpwlev", &aic7xxx_stpwlev }, { "no_probe", &aic7xxx_no_probe }, { "panic_on_abort", &aic7xxx_panic_on_abort }, { "pci_parity", &aic7xxx_pci_parity }, { "dump_card", &aic7xxx_dump_card }, { "dump_sequencer", &aic7xxx_dump_sequencer }, { "tag_info", NULL } }; end = strchr(s, '\0'); for (p = strtok(s, ",."); p; p = strtok(NULL, ",.")) { for (i = 0; i < NUMBER(options); i++) { n = strlen(options[i].name); if (!strncmp(options[i].name, p, n)) { if (!strncmp(p, "tag_info", n))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -