📄 53c7xx.c
字号:
/* * 53c710 driver. Modified from Drew Eckhardts driver * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk] * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]). * There are also currently some defines at the top of 53c7xx.scr. * The chip type is #defined in script_asm.pl, as well as the Makefile. * Host scsi ID expected to be 7 - see NCR53c7x0_init(). * * I have removed the PCI code and some of the 53c8xx specific code - * simply to make this file smaller and easier to manage. * * MVME16x issues: * Problems trying to read any chip registers in NCR53c7x0_init(), as they * may never have been set by 16xBug (eg. If kernel has come in over tftp). *//* * Adapted for Linux/m68k Amiga platforms for the A4000T/A4091 and * WarpEngine SCSI controllers. * By Alan Hourihane <alanh@fairlite.demon.co.uk> * Thanks to Richard Hirst for making it possible with the MVME additions *//* * 53c710 rev 0 doesn't support add with carry. Rev 1 and 2 does. To * overcome this problem you can define FORCE_DSA_ALIGNMENT, which ensures * that the DSA address is always xxxxxx00. If disconnection is not allowed, * then the script only ever tries to add small (< 256) positive offsets to * DSA, so lack of carry isn't a problem. FORCE_DSA_ALIGNMENT can, of course, * be defined for all chip revisions at a small cost in memory usage. */#define FORCE_DSA_ALIGNMENT/* * Selection timer does not always work on the 53c710, depending on the * timing at the last disconnect, if this is a problem for you, try * using validids as detailed below. * * Options for the NCR7xx driver * * noasync:0 - disables sync and asynchronous negotiation * nosync:0 - disables synchronous negotiation (does async) * nodisconnect:0 - disables disconnection * validids:0x?? - Bitmask field that disallows certain ID's. * - e.g. 0x03 allows ID 0,1 * - 0x1F allows ID 0,1,2,3,4 * opthi:n - replace top word of options with 'n' * optlo:n - replace bottom word of options with 'n' * - ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<< *//* * PERM_OPTIONS are driver options which will be enabled for all NCR boards * in the system at driver initialization time. * * Don't THINK about touching these in PERM_OPTIONS : * OPTION_MEMORY_MAPPED * 680x0 doesn't have an IO map! * * OPTION_DEBUG_TEST1 * Test 1 does bus mastering and interrupt tests, which will help weed * out brain damaged main boards. * * Other PERM_OPTIONS settings are listed below. Note the actual options * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc): * * OPTION_NO_ASYNC * Don't negotiate for asynchronous transfers on the first command * when OPTION_ALWAYS_SYNCHRONOUS is set. Useful for dain bramaged * devices which do something bad rather than sending a MESSAGE * REJECT back to us like they should if they can't cope. * * OPTION_SYNCHRONOUS * Enable support for synchronous transfers. Target negotiated * synchronous transfers will be responded to. To initiate * a synchronous transfer request, call * * request_synchronous (hostno, target) * * from within KGDB. * * OPTION_ALWAYS_SYNCHRONOUS * Negotiate for synchronous transfers with every target after * driver initialization or a SCSI bus reset. This is a bit dangerous, * since there are some dain bramaged SCSI devices which will accept * SDTR messages but keep talking asynchronously. * * OPTION_DISCONNECT * Enable support for disconnect/reconnect. To change the * default setting on a given host adapter, call * * request_disconnect (hostno, allow) * * where allow is non-zero to allow, 0 to disallow. * * If you really want to run 10MHz FAST SCSI-II transfers, you should * know that the NCR driver currently ignores parity information. Most * systems do 5MHz SCSI fine. I've seen a lot that have problems faster * than 8MHz. To play it safe, we only request 5MHz transfers. * * If you'd rather get 10MHz transfers, edit sdtr_message and change * the fourth byte from 50 to 25. *//* * Sponsored by * iX Multiuser Multitasking Magazine * Hannover, Germany * hm@ix.de * * Copyright 1993, 1994, 1995 Drew Eckhardt * Visionary Computing * (Unix and Linux consulting and custom programming) * drew@PoohSticks.ORG * +1 (303) 786-7975 * * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. * * For more information, please consult * * NCR53C810 * SCSI I/O Processor * Programmer's Guide * * NCR 53C810 * PCI-SCSI I/O Processor * Data Manual * * NCR 53C810/53C820 * PCI-SCSI I/O Processor Design In Guide * * For literature on Symbios Logic Inc. formerly NCR, SCSI, * and Communication products please call (800) 334-5454 or * (719) 536-3300. * * PCI BIOS Specification Revision * PCI Local Bus Specification * PCI System Design Guide * * PCI Special Interest Group * M/S HF3-15A * 5200 N.E. Elam Young Parkway * Hillsboro, Oregon 97124-6497 * +1 (503) 696-2000 * +1 (800) 433-5177 *//* * Design issues : * The cumulative latency needed to propagate a read/write request * through the file system, buffer cache, driver stacks, SCSI host, and * SCSI device is ultimately the limiting factor in throughput once we * have a sufficiently fast host adapter. * * So, to maximize performance we want to keep the ratio of latency to data * transfer time to a minimum by * 1. Minimizing the total number of commands sent (typical command latency * including drive and bus mastering host overhead is as high as 4.5ms) * to transfer a given amount of data. * * This is accomplished by placing no arbitrary limit on the number * of scatter/gather buffers supported, since we can transfer 1K * per scatter/gather buffer without Eric's cluster patches, * 4K with. * * 2. Minimizing the number of fatal interrupts serviced, since * fatal interrupts halt the SCSI I/O processor. Basically, * this means offloading the practical maximum amount of processing * to the SCSI chip. * * On the NCR53c810/820/720, this is accomplished by using * interrupt-on-the-fly signals when commands complete, * and only handling fatal errors and SDTR / WDTR messages * in the host code. * * On the NCR53c710, interrupts are generated as on the NCR53c8x0, * only the lack of a interrupt-on-the-fly facility complicates * things. Also, SCSI ID registers and commands are * bit fielded rather than binary encoded. * * On the NCR53c700 and NCR53c700-66, operations that are done via * indirect, table mode on the more advanced chips must be * replaced by calls through a jump table which * acts as a surrogate for the DSA. Unfortunately, this * will mean that we must service an interrupt for each * disconnect/reconnect. * * 3. Eliminating latency by pipelining operations at the different levels. * * This driver allows a configurable number of commands to be enqueued * for each target/lun combination (experimentally, I have discovered * that two seems to work best) and will ultimately allow for * SCSI-II tagged queuing. * * * Architecture : * This driver is built around a Linux queue of commands waiting to * be executed, and a shared Linux/NCR array of commands to start. Commands * are transfered to the array by the run_process_issue_queue() function * which is called whenever a command completes. * * As commands are completed, the interrupt routine is triggered, * looks for commands in the linked list of completed commands with * valid status, removes these commands from a list of running commands, * calls the done routine, and flags their target/luns as not busy. * * Due to limitations in the intelligence of the NCR chips, certain * concessions are made. In many cases, it is easier to dynamically * generate/fix-up code rather than calculate on the NCR at run time. * So, code is generated or fixed up for * * - Handling data transfers, using a variable number of MOVE instructions * interspersed with CALL MSG_IN, WHEN MSGIN instructions. * * The DATAIN and DATAOUT routines are separate, so that an incorrect * direction can be trapped, and space isn't wasted. * * It may turn out that we're better off using some sort * of table indirect instruction in a loop with a variable * sized table on the NCR53c710 and newer chips. * * - Checking for reselection (NCR53c710 and better) * * - Handling the details of SCSI context switches (NCR53c710 and better), * such as reprogramming appropriate synchronous parameters, * removing the dsa structure from the NCR's queue of outstanding * commands, etc. * */#ifdef MODULE#include <linux/module.h>#endif#include <linux/config.h>#include <linux/types.h>#include <asm/setup.h>#include <asm/dma.h>#include <asm/io.h>#include <asm/system.h>#include <linux/delay.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/malloc.h>#include <linux/vmalloc.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/time.h>#include <linux/blk.h>#include <linux/spinlock.h>#include <asm/pgtable.h>#ifdef CONFIG_AMIGA#include <asm/amigahw.h>#include <asm/amigaints.h>#include <asm/irq.h>#define BIG_ENDIAN#define NO_IO_SPACE#endif#ifdef CONFIG_MVME16x#include <asm/mvme16xhw.h>#define BIG_ENDIAN#define NO_IO_SPACE#define VALID_IDS#endif#ifdef CONFIG_BVME6000#include <asm/bvme6000hw.h>#define BIG_ENDIAN#define NO_IO_SPACE#define VALID_IDS#endif#include "scsi.h"#include "hosts.h"#include "53c7xx.h"#include "constants.h"#include "sd.h"#include <linux/stat.h>#include <linux/stddef.h>#ifdef NO_IO_SPACE/* * The following make the definitions in 53c7xx.h (write8, etc) smaller, * we don't have separate i/o space anyway. */#undef inb#undef outb#undef inw#undef outw#undef inl#undef outl#define inb(x) 1#define inw(x) 1#define inl(x) 1#define outb(x,y) 1#define outw(x,y) 1#define outl(x,y) 1#endifstatic int check_address (unsigned long addr, int size);static void dump_events (struct Scsi_Host *host, int count);static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, int free, int issue);static void hard_reset (struct Scsi_Host *host);static void ncr_scsi_reset (struct Scsi_Host *host);static void print_lots (struct Scsi_Host *host);static void set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3, int now_connected);static int datapath_residual (struct Scsi_Host *host);static const char * sbcl_to_phase (int sbcl);static void print_progress (Scsi_Cmnd *cmd);static void print_queues (struct Scsi_Host *host);static void process_issue_queue (unsigned long flags);static int shutdown (struct Scsi_Host *host);static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);static int disable (struct Scsi_Host *host);static int NCR53c7xx_run_tests (struct Scsi_Host *host);static void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);static void NCR53c7x0_intfly (struct Scsi_Host *host);static int ncr_halt (struct Scsi_Host *host);static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);static void print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix);static int print_insn (struct Scsi_Host *host, const u32 *insn, const char *prefix, int kernel);static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd);static void NCR53c7x0_init_fixup (struct Scsi_Host *host);static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);static void NCR53c7x0_soft_reset (struct Scsi_Host *host);/* Size of event list (per host adapter) */static int track_events = 0;static struct Scsi_Host *first_host = NULL; /* Head of list of NCR boards */static Scsi_Host_Template *the_template = NULL; /* NCR53c710 script handling code */#include "53c7xx_d.h"#ifdef A_int_debug_sync#define DEBUG_SYNC_INTR A_int_debug_sync#endifint NCR53c7xx_script_len = sizeof (SCRIPT);int NCR53c7xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template;#ifdef FORCE_DSA_ALIGNMENTint CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff;#endifstatic char *setup_strings[] = {"","","","","","","",""};#define MAX_SETUP_STRINGS (sizeof(setup_strings) / sizeof(char *))#define SETUP_BUFFER_SIZE 200static char setup_buffer[SETUP_BUFFER_SIZE];static char setup_used[MAX_SETUP_STRINGS];void ncr53c7xx_setup (char *str, int *ints){ int i; char *p1, *p2; p1 = setup_buffer; *p1 = '\0'; if (str) strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer)); setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0'; p1 = setup_buffer; i = 0; while (*p1 && (i < MAX_SETUP_STRINGS)) { p2 = strchr(p1, ','); if (p2) { *p2 = '\0'; if (p1 != p2) setup_strings[i] = p1; p1 = p2 + 1; i++; } else { setup_strings[i] = p1; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -