📄 53c78xx.c
字号:
/* * 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_IO_MAPPED * Memory mapped IO does not work under i86 Linux. * * OPTION_DEBUG_TEST1 * Test 1 does bus mastering and interrupt tests, which will help weed * out brain damaged main boards. * * These are development kernel changes. Code for them included in this * driver release may or may not work. If you turn them on, you should be * running the latest copy of the development sources from * * ftp://tsx-11.mit.edu/pub/linux/ALPHA/scsi/53c7,8xx * * and be subscribed to the ncr53c810@colorado.edu mailing list. To * subscribe, send mail to majordomo@colorado.edu with * * subscribe ncr53c810 * * in the text. * * * 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. */#include <linux/config.h>#ifdef CONFIG_SCSI_NCR53C7xx_sync#ifdef CONFIG_SCSI_NCR53C7xx_DISCONNECT#define PERM_OPTIONS (OPTION_IO_MAPPED|OPTION_DEBUG_TEST1|OPTION_DISCONNECT|\ OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS)#else#define PERM_OPTIONS (OPTION_IO_MAPPED|OPTION_DEBUG_TEST1|\ OPTION_SYNCHRONOUS|OPTION_ALWAYS_SYNCHRONOUS)#endif#else#ifdef CONFIG_SCSI_NCR53C7xx_DISCONNECT#define PERM_OPTIONS (OPTION_IO_MAPPED|OPTION_DEBUG_TEST1|OPTION_DISCONNECT|\ OPTION_SYNCHRONOUS)#else#define PERM_OPTIONS (OPTION_IO_MAPPED|OPTION_DEBUG_TEST1|OPTION_SYNCHRONOUS)#endif#endif/* * 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. * *//* * Accommodate differences between stock 1.2.x and 1.3.x asm-i386/types.h * so lusers can drop in 53c7,8xx.* and get something which compiles * without warnings. */#if !defined(LINUX_1_2) && !defined(LINUX_1_3)#include <linux/version.h>#if LINUX_VERSION_CODE > 65536 + 3 * 256#define LINUX_1_3#else#define LINUX_1_2#endif#endif#ifdef LINUX_1_2#define u32 bogus_u32#define s32 bogus_s32#include <asm/types.h>#undef u32#undef s32typedef __signed__ int s32;typedef unsigned int u32;#endif /* def LINUX_1_2 */#ifdef MODULE#include <linux/module.h>#endif#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/bios32.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/string.h>#include <linux/malloc.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/time.h>#ifdef LINUX_1_2#include "../block/blk.h"#else#include <linux/blk.h>#endif#undef current#include "scsi.h"#include "hosts.h"#include "53c7,8xx.h"#include "constants.h"#include "sd.h"#include <linux/stat.h>#include <linux/stddef.h>#ifndef LINUX_1_2struct proc_dir_entry proc_scsi_ncr53c7xx = { PROC_SCSI_NCR53C7xx, 9, "ncr53c7xx", S_IFDIR | S_IRUGO | S_IXUGO, 2};#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 NCR53c8xx_run_tests (struct Scsi_Host *host);static int NCR53c8xx_script_len;static int NCR53c8xx_dsa_len;static void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);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 NCR53c8xx_dsa_fixup (struct NCR53c7x0_cmd *cmd);static void NCR53c8x0_init_fixup (struct Scsi_Host *host);static int NCR53c8x0_dstat_sir_intr (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd);static void NCR53c8x0_soft_reset (struct Scsi_Host *host);/* INSMOD variables */static long long perm_options = PERM_OPTIONS;/* 14 = .5s; 15 is max; decreasing divides by two. */static int selection_timeout = 14;/* 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; /* * KNOWN BUGS : * - There is some sort of conflict when the PPP driver is compiled with * support for 16 channels? * * - On systems which predate the 1.3.x initialization order change, * the NCR driver will cause Cannot get free page messages to appear. * These are harmless, but I don't know of an easy way to avoid them. * * - With OPTION_DISCONNECT, on two systems under unknown circumstances, * we get a PHASE MISMATCH with DSA set to zero (suggests that we * are occurring somewhere in the reselection code) where * DSP=some value DCMD|DBC=same value. * * Closer inspection suggests that we may be trying to execute * some portion of the DSA? * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) * scsi0 : no current command : unexpected phase MSGIN. * DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0 * DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80 * scsi0 : DSP-> * 001c46cc : 0x001c46cc 0x00000000 * 001c46d4 : 0x001c5ea0 0x000011f8 * * Changed the print code in the phase_mismatch handler so * that we call print_lots to try to diagnose this. * *//* * Possible future direction of architecture for max performance : * * We're using a single start array for the NCR chip. This is * sub-optimal, because we cannot add a command which would conflict with * an executing command to this start queue, and therefore must insert the * next command for a given I/T/L combination after the first has completed; * incurring our interrupt latency between SCSI commands. * * To allow further pipelining of the NCR and host CPU operation, we want * to set things up so that immediately on termination of a command destined * for a given LUN, we get that LUN busy again. * * To do this, we need to add a 32 bit pointer to which is jumped to * on completion of a command. If no new command is available, this * would point to the usual DSA issue queue select routine. * * If one were, it would point to a per-NCR53c7x0_cmd select routine * which starts execution immediately, inserting the command at the head * of the start queue if the NCR chip is selected or reselected. * * We would change so that we keep a list of outstanding commands * for each unit, rather than a single running_list. We'd insert * a new command into the right running list; if the NCR didn't * have something running for that yet, we'd put it in the * start queue as well. Some magic needs to happen to handle the * race condition between the first command terminating before the * new one is written. * * Potential for profiling : * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution. *//* * TODO : * 1. To support WIDE transfers, not much needs to happen. We * should do CHMOVE instructions instead of MOVEs when * we have scatter/gather segments of uneven length. When
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -