| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * 53c710 driver.  Modified from Drew Eckhardts driver | 
 | 3 |  * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk] | 
 | 4 |  * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the | 
 | 5 |  * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]). | 
 | 6 |  * There are also currently some defines at the top of 53c7xx.scr. | 
 | 7 |  * The chip type is #defined in script_asm.pl, as well as the Makefile. | 
 | 8 |  * Host scsi ID expected to be 7 - see NCR53c7x0_init(). | 
 | 9 |  * | 
 | 10 |  * I have removed the PCI code and some of the 53c8xx specific code -  | 
 | 11 |  * simply to make this file smaller and easier to manage. | 
 | 12 |  * | 
 | 13 |  * MVME16x issues: | 
 | 14 |  *   Problems trying to read any chip registers in NCR53c7x0_init(), as they | 
 | 15 |  *   may never have been set by 16xBug (eg. If kernel has come in over tftp). | 
 | 16 |  */ | 
 | 17 |  | 
 | 18 | /* | 
 | 19 |  * Adapted for Linux/m68k Amiga platforms for the A4000T/A4091 and | 
 | 20 |  * WarpEngine SCSI controllers. | 
 | 21 |  * By Alan Hourihane <alanh@fairlite.demon.co.uk> | 
 | 22 |  * Thanks to Richard Hirst for making it possible with the MVME additions | 
 | 23 |  */ | 
 | 24 |  | 
 | 25 | /* | 
 | 26 |  * 53c710 rev 0 doesn't support add with carry.  Rev 1 and 2 does.  To | 
 | 27 |  * overcome this problem you can define FORCE_DSA_ALIGNMENT, which ensures | 
 | 28 |  * that the DSA address is always xxxxxx00.  If disconnection is not allowed, | 
 | 29 |  * then the script only ever tries to add small (< 256) positive offsets to | 
 | 30 |  * DSA, so lack of carry isn't a problem.  FORCE_DSA_ALIGNMENT can, of course, | 
 | 31 |  * be defined for all chip revisions at a small cost in memory usage. | 
 | 32 |  */ | 
 | 33 |  | 
 | 34 | #define FORCE_DSA_ALIGNMENT | 
 | 35 |  | 
 | 36 | /* | 
 | 37 |  * Selection timer does not always work on the 53c710, depending on the | 
 | 38 |  * timing at the last disconnect, if this is a problem for you, try | 
 | 39 |  * using validids as detailed below. | 
 | 40 |  * | 
 | 41 |  * Options for the NCR7xx driver | 
 | 42 |  * | 
 | 43 |  * noasync:0		-	disables sync and asynchronous negotiation | 
 | 44 |  * nosync:0		-	disables synchronous negotiation (does async) | 
 | 45 |  * nodisconnect:0	-	disables disconnection | 
 | 46 |  * validids:0x??	-	Bitmask field that disallows certain ID's. | 
 | 47 |  *			-	e.g.	0x03	allows ID 0,1 | 
 | 48 |  *			-		0x1F	allows ID 0,1,2,3,4 | 
 | 49 |  * opthi:n		-	replace top word of options with 'n' | 
 | 50 |  * optlo:n		-	replace bottom word of options with 'n' | 
 | 51 |  *			-	ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<< | 
 | 52 |  */ | 
 | 53 |  | 
 | 54 | /* | 
 | 55 |  * PERM_OPTIONS are driver options which will be enabled for all NCR boards | 
 | 56 |  * in the system at driver initialization time. | 
 | 57 |  * | 
 | 58 |  * Don't THINK about touching these in PERM_OPTIONS :  | 
 | 59 |  *   OPTION_MEMORY_MAPPED  | 
 | 60 |  * 	680x0 doesn't have an IO map! | 
 | 61 |  * | 
 | 62 |  *   OPTION_DEBUG_TEST1 | 
 | 63 |  *	Test 1 does bus mastering and interrupt tests, which will help weed  | 
 | 64 |  *	out brain damaged main boards. | 
 | 65 |  * | 
 | 66 |  * Other PERM_OPTIONS settings are listed below.  Note the actual options | 
 | 67 |  * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc): | 
 | 68 |  * | 
 | 69 |  *   OPTION_NO_ASYNC | 
 | 70 |  *	Don't negotiate for asynchronous transfers on the first command  | 
 | 71 |  *	when OPTION_ALWAYS_SYNCHRONOUS is set.  Useful for dain bramaged | 
 | 72 |  *	devices which do something bad rather than sending a MESSAGE  | 
 | 73 |  *	REJECT back to us like they should if they can't cope. | 
 | 74 |  * | 
 | 75 |  *   OPTION_SYNCHRONOUS | 
 | 76 |  *	Enable support for synchronous transfers.  Target negotiated  | 
 | 77 |  *	synchronous transfers will be responded to.  To initiate  | 
 | 78 |  *	a synchronous transfer request,  call  | 
 | 79 |  * | 
 | 80 |  *	    request_synchronous (hostno, target)  | 
 | 81 |  * | 
 | 82 |  *	from within KGDB. | 
 | 83 |  * | 
 | 84 |  *   OPTION_ALWAYS_SYNCHRONOUS | 
 | 85 |  *	Negotiate for synchronous transfers with every target after | 
 | 86 |  *	driver initialization or a SCSI bus reset.  This is a bit dangerous,  | 
 | 87 |  *	since there are some dain bramaged SCSI devices which will accept | 
 | 88 |  *	SDTR messages but keep talking asynchronously. | 
 | 89 |  * | 
 | 90 |  *   OPTION_DISCONNECT | 
 | 91 |  *	Enable support for disconnect/reconnect.  To change the  | 
 | 92 |  *	default setting on a given host adapter, call | 
 | 93 |  * | 
 | 94 |  *	    request_disconnect (hostno, allow) | 
 | 95 |  * | 
 | 96 |  *	where allow is non-zero to allow, 0 to disallow. | 
 | 97 |  *  | 
 | 98 |  *  If you really want to run 10MHz FAST SCSI-II transfers, you should  | 
 | 99 |  *  know that the NCR driver currently ignores parity information.  Most | 
 | 100 |  *  systems do 5MHz SCSI fine.  I've seen a lot that have problems faster | 
 | 101 |  *  than 8MHz.  To play it safe, we only request 5MHz transfers. | 
 | 102 |  * | 
 | 103 |  *  If you'd rather get 10MHz transfers, edit sdtr_message and change  | 
 | 104 |  *  the fourth byte from 50 to 25. | 
 | 105 |  */ | 
 | 106 |  | 
 | 107 | /* | 
 | 108 |  * Sponsored by  | 
 | 109 |  *	iX Multiuser Multitasking Magazine | 
 | 110 |  *	Hannover, Germany | 
 | 111 |  *	hm@ix.de | 
 | 112 |  * | 
 | 113 |  * Copyright 1993, 1994, 1995 Drew Eckhardt | 
 | 114 |  *      Visionary Computing  | 
 | 115 |  *      (Unix and Linux consulting and custom programming) | 
 | 116 |  *      drew@PoohSticks.ORG | 
 | 117 |  *	+1 (303) 786-7975 | 
 | 118 |  * | 
 | 119 |  * TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation. | 
 | 120 |  *  | 
 | 121 |  * For more information, please consult  | 
 | 122 |  * | 
 | 123 |  * NCR53C810  | 
 | 124 |  * SCSI I/O Processor | 
 | 125 |  * Programmer's Guide | 
 | 126 |  * | 
 | 127 |  * NCR 53C810 | 
 | 128 |  * PCI-SCSI I/O Processor | 
 | 129 |  * Data Manual | 
 | 130 |  * | 
 | 131 |  * NCR 53C810/53C820 | 
 | 132 |  * PCI-SCSI I/O Processor Design In Guide | 
 | 133 |  * | 
 | 134 |  * For literature on Symbios Logic Inc. formerly NCR, SCSI,  | 
 | 135 |  * and Communication products please call (800) 334-5454 or | 
 | 136 |  * (719) 536-3300.  | 
 | 137 |  *  | 
 | 138 |  * PCI BIOS Specification Revision | 
 | 139 |  * PCI Local Bus Specification | 
 | 140 |  * PCI System Design Guide | 
 | 141 |  * | 
 | 142 |  * PCI Special Interest Group | 
 | 143 |  * M/S HF3-15A | 
 | 144 |  * 5200 N.E. Elam Young Parkway | 
 | 145 |  * Hillsboro, Oregon 97124-6497 | 
 | 146 |  * +1 (503) 696-2000  | 
 | 147 |  * +1 (800) 433-5177 | 
 | 148 |  */ | 
 | 149 |  | 
 | 150 | /* | 
 | 151 |  * Design issues :  | 
 | 152 |  * The cumulative latency needed to propagate a read/write request  | 
 | 153 |  * through the file system, buffer cache, driver stacks, SCSI host, and  | 
 | 154 |  * SCSI device is ultimately the limiting factor in throughput once we  | 
 | 155 |  * have a sufficiently fast host adapter. | 
 | 156 |  *   | 
 | 157 |  * So, to maximize performance we want to keep the ratio of latency to data  | 
 | 158 |  * transfer time to a minimum by | 
 | 159 |  * 1.  Minimizing the total number of commands sent (typical command latency | 
 | 160 |  *	including drive and bus mastering host overhead is as high as 4.5ms) | 
 | 161 |  *	to transfer a given amount of data.   | 
 | 162 |  * | 
 | 163 |  *      This is accomplished by placing no arbitrary limit on the number | 
 | 164 |  *	of scatter/gather buffers supported, since we can transfer 1K | 
 | 165 |  *	per scatter/gather buffer without Eric's cluster patches,  | 
 | 166 |  *	4K with.   | 
 | 167 |  * | 
 | 168 |  * 2.  Minimizing the number of fatal interrupts serviced, since | 
 | 169 |  * 	fatal interrupts halt the SCSI I/O processor.  Basically, | 
 | 170 |  *	this means offloading the practical maximum amount of processing  | 
 | 171 |  *	to the SCSI chip. | 
 | 172 |  *  | 
 | 173 |  *	On the NCR53c810/820/720,  this is accomplished by using  | 
 | 174 |  *		interrupt-on-the-fly signals when commands complete,  | 
 | 175 |  *		and only handling fatal errors and SDTR / WDTR 	messages  | 
 | 176 |  *		in the host code. | 
 | 177 |  * | 
 | 178 |  *	On the NCR53c710, interrupts are generated as on the NCR53c8x0, | 
 | 179 |  *		only the lack of a interrupt-on-the-fly facility complicates | 
 | 180 |  *		things.   Also, SCSI ID registers and commands are  | 
 | 181 |  *		bit fielded rather than binary encoded. | 
 | 182 |  *		 | 
 | 183 |  * 	On the NCR53c700 and NCR53c700-66, operations that are done via  | 
 | 184 |  *		indirect, table mode on the more advanced chips must be | 
 | 185 |  *	        replaced by calls through a jump table which  | 
 | 186 |  *		acts as a surrogate for the DSA.  Unfortunately, this  | 
 | 187 |  * 		will mean that we must service an interrupt for each  | 
 | 188 |  *		disconnect/reconnect. | 
 | 189 |  *  | 
 | 190 |  * 3.  Eliminating latency by pipelining operations at the different levels. | 
 | 191 |  * 	 | 
 | 192 |  *	This driver allows a configurable number of commands to be enqueued | 
 | 193 |  *	for each target/lun combination (experimentally, I have discovered | 
 | 194 |  *	that two seems to work best) and will ultimately allow for  | 
 | 195 |  *	SCSI-II tagged queuing. | 
 | 196 |  * 	 | 
 | 197 |  * | 
 | 198 |  * Architecture :  | 
 | 199 |  * This driver is built around a Linux queue of commands waiting to  | 
 | 200 |  * be executed, and a shared Linux/NCR array of commands to start.  Commands | 
 | 201 |  * are transferred to the array  by the run_process_issue_queue() function  | 
 | 202 |  * which is called whenever a command completes. | 
 | 203 |  * | 
 | 204 |  * As commands are completed, the interrupt routine is triggered, | 
 | 205 |  * looks for commands in the linked list of completed commands with | 
 | 206 |  * valid status, removes these commands from a list of running commands,  | 
 | 207 |  * calls the done routine, and flags their target/luns as not busy. | 
 | 208 |  * | 
 | 209 |  * Due to limitations in the intelligence of the NCR chips, certain | 
 | 210 |  * concessions are made.  In many cases, it is easier to dynamically  | 
 | 211 |  * generate/fix-up code rather than calculate on the NCR at run time.   | 
 | 212 |  * So, code is generated or fixed up for | 
 | 213 |  * | 
 | 214 |  * - Handling data transfers, using a variable number of MOVE instructions | 
 | 215 |  *	interspersed with CALL MSG_IN, WHEN MSGIN instructions. | 
 | 216 |  * | 
 | 217 |  * 	The DATAIN and DATAOUT routines	are separate, so that an incorrect | 
 | 218 |  *	direction can be trapped, and space isn't wasted.  | 
 | 219 |  * | 
 | 220 |  *	It may turn out that we're better off using some sort  | 
 | 221 |  *	of table indirect instruction in a loop with a variable | 
 | 222 |  *	sized table on the NCR53c710 and newer chips. | 
 | 223 |  * | 
 | 224 |  * - Checking for reselection (NCR53c710 and better) | 
 | 225 |  * | 
 | 226 |  * - Handling the details of SCSI context switches (NCR53c710 and better), | 
 | 227 |  *	such as reprogramming appropriate synchronous parameters,  | 
 | 228 |  *	removing the dsa structure from the NCR's queue of outstanding | 
 | 229 |  *	commands, etc. | 
 | 230 |  * | 
 | 231 |  */ | 
 | 232 |  | 
 | 233 | #include <linux/module.h> | 
 | 234 |  | 
 | 235 | #include <linux/config.h> | 
 | 236 |  | 
 | 237 | #include <linux/types.h> | 
 | 238 | #include <asm/setup.h> | 
 | 239 | #include <asm/dma.h> | 
 | 240 | #include <asm/io.h> | 
 | 241 | #include <asm/system.h> | 
 | 242 | #include <linux/delay.h> | 
 | 243 | #include <linux/signal.h> | 
 | 244 | #include <linux/sched.h> | 
 | 245 | #include <linux/errno.h> | 
 | 246 | #include <linux/string.h> | 
 | 247 | #include <linux/slab.h> | 
 | 248 | #include <linux/vmalloc.h> | 
 | 249 | #include <linux/mm.h> | 
 | 250 | #include <linux/ioport.h> | 
 | 251 | #include <linux/time.h> | 
 | 252 | #include <linux/blkdev.h> | 
 | 253 | #include <linux/spinlock.h> | 
 | 254 | #include <linux/interrupt.h> | 
 | 255 | #include <asm/pgtable.h> | 
 | 256 |  | 
 | 257 | #ifdef CONFIG_AMIGA | 
 | 258 | #include <asm/amigahw.h> | 
 | 259 | #include <asm/amigaints.h> | 
 | 260 | #include <asm/irq.h> | 
 | 261 |  | 
 | 262 | #define BIG_ENDIAN | 
 | 263 | #define NO_IO_SPACE | 
 | 264 | #endif | 
 | 265 |  | 
 | 266 | #ifdef CONFIG_MVME16x | 
 | 267 | #include <asm/mvme16xhw.h> | 
 | 268 |  | 
 | 269 | #define BIG_ENDIAN | 
 | 270 | #define NO_IO_SPACE | 
 | 271 | #define VALID_IDS | 
 | 272 | #endif | 
 | 273 |  | 
 | 274 | #ifdef CONFIG_BVME6000 | 
 | 275 | #include <asm/bvme6000hw.h> | 
 | 276 |  | 
 | 277 | #define BIG_ENDIAN | 
 | 278 | #define NO_IO_SPACE | 
 | 279 | #define VALID_IDS | 
 | 280 | #endif | 
 | 281 |  | 
 | 282 | #include "scsi.h" | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 283 | #include <scsi/scsi_dbg.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 284 | #include <scsi/scsi_host.h> | 
 | 285 | #include "53c7xx.h" | 
 | 286 | #include <linux/stat.h> | 
 | 287 | #include <linux/stddef.h> | 
 | 288 |  | 
 | 289 | #ifdef NO_IO_SPACE | 
 | 290 | /* | 
 | 291 |  * The following make the definitions in 53c7xx.h (write8, etc) smaller, | 
 | 292 |  * we don't have separate i/o space anyway. | 
 | 293 |  */ | 
 | 294 | #undef inb | 
 | 295 | #undef outb | 
 | 296 | #undef inw | 
 | 297 | #undef outw | 
 | 298 | #undef inl | 
 | 299 | #undef outl | 
 | 300 | #define inb(x)          1 | 
 | 301 | #define inw(x)          1 | 
 | 302 | #define inl(x)          1 | 
 | 303 | #define outb(x,y)       1 | 
 | 304 | #define outw(x,y)       1 | 
 | 305 | #define outl(x,y)       1 | 
 | 306 | #endif | 
 | 307 |  | 
 | 308 | static int check_address (unsigned long addr, int size); | 
 | 309 | static void dump_events (struct Scsi_Host *host, int count); | 
 | 310 | static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host,  | 
 | 311 |     int free, int issue); | 
 | 312 | static void hard_reset (struct Scsi_Host *host); | 
 | 313 | static void ncr_scsi_reset (struct Scsi_Host *host); | 
 | 314 | static void print_lots (struct Scsi_Host *host); | 
 | 315 | static void set_synchronous (struct Scsi_Host *host, int target, int sxfer,  | 
 | 316 |     int scntl3, int now_connected); | 
 | 317 | static int datapath_residual (struct Scsi_Host *host); | 
 | 318 | static const char * sbcl_to_phase (int sbcl); | 
 | 319 | static void print_progress (Scsi_Cmnd *cmd); | 
 | 320 | static void print_queues (struct Scsi_Host *host); | 
 | 321 | static void process_issue_queue (unsigned long flags); | 
 | 322 | static int shutdown (struct Scsi_Host *host); | 
 | 323 | static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result); | 
 | 324 | static int disable (struct Scsi_Host *host); | 
 | 325 | static int NCR53c7xx_run_tests (struct Scsi_Host *host); | 
 | 326 | static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs); | 
 | 327 | static void NCR53c7x0_intfly (struct Scsi_Host *host); | 
 | 328 | static int ncr_halt (struct Scsi_Host *host); | 
 | 329 | static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd  | 
 | 330 |     *cmd); | 
 | 331 | static void intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd); | 
 | 332 | static void print_dsa (struct Scsi_Host *host, u32 *dsa, | 
 | 333 |     const char *prefix); | 
 | 334 | static int print_insn (struct Scsi_Host *host, const u32 *insn, | 
 | 335 |     const char *prefix, int kernel); | 
 | 336 |  | 
 | 337 | static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd); | 
 | 338 | static void NCR53c7x0_init_fixup (struct Scsi_Host *host); | 
 | 339 | static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct  | 
 | 340 |     NCR53c7x0_cmd *cmd); | 
 | 341 | static void NCR53c7x0_soft_reset (struct Scsi_Host *host); | 
 | 342 |  | 
 | 343 | /* Size of event list (per host adapter) */ | 
 | 344 | static int track_events = 0; | 
 | 345 | static struct Scsi_Host *first_host = NULL;	/* Head of list of NCR boards */ | 
 | 346 | static Scsi_Host_Template *the_template = NULL;	 | 
 | 347 |  | 
 | 348 | /* NCR53c710 script handling code */ | 
 | 349 |  | 
 | 350 | #include "53c7xx_d.h" | 
 | 351 | #ifdef A_int_debug_sync | 
 | 352 | #define DEBUG_SYNC_INTR A_int_debug_sync | 
 | 353 | #endif | 
 | 354 | int NCR53c7xx_script_len = sizeof (SCRIPT); | 
 | 355 | int NCR53c7xx_dsa_len = A_dsa_end + Ent_dsa_zero - Ent_dsa_code_template; | 
 | 356 | #ifdef FORCE_DSA_ALIGNMENT | 
 | 357 | int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff; | 
 | 358 | #endif | 
 | 359 |  | 
 | 360 | static char *setup_strings[] = | 
 | 361 | 	{"","","","","","","",""}; | 
 | 362 |  | 
 | 363 | #define MAX_SETUP_STRINGS (sizeof(setup_strings) / sizeof(char *)) | 
 | 364 | #define SETUP_BUFFER_SIZE 200 | 
 | 365 | static char setup_buffer[SETUP_BUFFER_SIZE]; | 
 | 366 | static char setup_used[MAX_SETUP_STRINGS]; | 
 | 367 |  | 
 | 368 | void ncr53c7xx_setup (char *str, int *ints) | 
 | 369 | { | 
 | 370 |    int i; | 
 | 371 |    char *p1, *p2; | 
 | 372 |  | 
 | 373 |    p1 = setup_buffer; | 
 | 374 |    *p1 = '\0'; | 
 | 375 |    if (str) | 
 | 376 |       strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer)); | 
 | 377 |    setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0'; | 
 | 378 |    p1 = setup_buffer; | 
 | 379 |    i = 0; | 
 | 380 |    while (*p1 && (i < MAX_SETUP_STRINGS)) { | 
 | 381 |       p2 = strchr(p1, ','); | 
 | 382 |       if (p2) { | 
 | 383 |          *p2 = '\0'; | 
 | 384 |          if (p1 != p2) | 
 | 385 |             setup_strings[i] = p1; | 
 | 386 |          p1 = p2 + 1; | 
 | 387 |          i++; | 
 | 388 |          } | 
 | 389 |       else { | 
 | 390 |          setup_strings[i] = p1; | 
 | 391 |          break; | 
 | 392 |          } | 
 | 393 |       } | 
 | 394 |    for (i=0; i<MAX_SETUP_STRINGS; i++) | 
 | 395 |       setup_used[i] = 0; | 
 | 396 | } | 
 | 397 |  | 
 | 398 |  | 
 | 399 | /* check_setup_strings() returns index if key found, 0 if not | 
 | 400 |  */ | 
 | 401 |  | 
 | 402 | static int check_setup_strings(char *key, int *flags, int *val, char *buf) | 
 | 403 | { | 
 | 404 | int x; | 
 | 405 | char *cp; | 
 | 406 |  | 
 | 407 |    for  (x=0; x<MAX_SETUP_STRINGS; x++) { | 
 | 408 |       if (setup_used[x]) | 
 | 409 |          continue; | 
 | 410 |       if (!strncmp(setup_strings[x], key, strlen(key))) | 
 | 411 |          break; | 
 | 412 |       if (!strncmp(setup_strings[x], "next", strlen("next"))) | 
 | 413 |          return 0; | 
 | 414 |       } | 
 | 415 |    if (x == MAX_SETUP_STRINGS) | 
 | 416 |       return 0; | 
 | 417 |    setup_used[x] = 1; | 
 | 418 |    cp = setup_strings[x] + strlen(key); | 
 | 419 |    *val = -1; | 
 | 420 |    if (*cp != ':') | 
 | 421 |       return ++x; | 
 | 422 |    cp++; | 
 | 423 |    if ((*cp >= '0') && (*cp <= '9')) { | 
 | 424 |       *val = simple_strtoul(cp,NULL,0); | 
 | 425 |       } | 
 | 426 |    return ++x; | 
 | 427 | } | 
 | 428 |  | 
 | 429 |  | 
 | 430 |  | 
 | 431 | /* | 
 | 432 |  * KNOWN BUGS : | 
 | 433 |  * - There is some sort of conflict when the PPP driver is compiled with  | 
 | 434 |  * 	support for 16 channels? | 
 | 435 |  *  | 
 | 436 |  * - On systems which predate the 1.3.x initialization order change, | 
 | 437 |  *      the NCR driver will cause Cannot get free page messages to appear.   | 
 | 438 |  *      These are harmless, but I don't know of an easy way to avoid them. | 
 | 439 |  * | 
 | 440 |  * - With OPTION_DISCONNECT, on two systems under unknown circumstances, | 
 | 441 |  *	we get a PHASE MISMATCH with DSA set to zero (suggests that we  | 
 | 442 |  *	are occurring somewhere in the reselection code) where  | 
 | 443 |  *	DSP=some value DCMD|DBC=same value.   | 
 | 444 |  * 	 | 
 | 445 |  *	Closer inspection suggests that we may be trying to execute | 
 | 446 |  *	some portion of the DSA? | 
 | 447 |  * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) | 
 | 448 |  * scsi0 : handling residual transfer (+ 0 bytes from DMA FIFO) | 
 | 449 |  * scsi0 : no current command : unexpected phase MSGIN. | 
 | 450 |  *         DSP=0x1c46cc, DCMD|DBC=0x1c46ac, DSA=0x0 | 
 | 451 |  *         DSPS=0x0, TEMP=0x1c3e70, DMODE=0x80 | 
 | 452 |  * scsi0 : DSP-> | 
 | 453 |  * 001c46cc : 0x001c46cc 0x00000000 | 
 | 454 |  * 001c46d4 : 0x001c5ea0 0x000011f8 | 
 | 455 |  * | 
 | 456 |  *	Changed the print code in the phase_mismatch handler so | 
 | 457 |  *	that we call print_lots to try to diagnose this. | 
 | 458 |  * | 
 | 459 |  */ | 
 | 460 |  | 
 | 461 | /*  | 
 | 462 |  * Possible future direction of architecture for max performance : | 
 | 463 |  * | 
 | 464 |  * We're using a single start array for the NCR chip.  This is  | 
 | 465 |  * sub-optimal, because we cannot add a command which would conflict with  | 
 | 466 |  * an executing command to this start queue, and therefore must insert the  | 
 | 467 |  * next command for a given I/T/L combination after the first has completed; | 
 | 468 |  * incurring our interrupt latency between SCSI commands. | 
 | 469 |  * | 
 | 470 |  * To allow further pipelining of the NCR and host CPU operation, we want  | 
 | 471 |  * to set things up so that immediately on termination of a command destined  | 
 | 472 |  * for a given LUN, we get that LUN busy again.   | 
 | 473 |  *  | 
 | 474 |  * To do this, we need to add a 32 bit pointer to which is jumped to  | 
 | 475 |  * on completion of a command.  If no new command is available, this  | 
 | 476 |  * would point to the usual DSA issue queue select routine. | 
 | 477 |  * | 
 | 478 |  * If one were, it would point to a per-NCR53c7x0_cmd select routine  | 
 | 479 |  * which starts execution immediately, inserting the command at the head  | 
 | 480 |  * of the start queue if the NCR chip is selected or reselected. | 
 | 481 |  * | 
 | 482 |  * We would change so that we keep a list of outstanding commands  | 
 | 483 |  * for each unit, rather than a single running_list.  We'd insert  | 
 | 484 |  * a new command into the right running list; if the NCR didn't  | 
 | 485 |  * have something running for that yet, we'd put it in the  | 
 | 486 |  * start queue as well.  Some magic needs to happen to handle the  | 
 | 487 |  * race condition between the first command terminating before the  | 
 | 488 |  * new one is written. | 
 | 489 |  * | 
 | 490 |  * Potential for profiling :  | 
 | 491 |  * Call do_gettimeofday(struct timeval *tv) to get 800ns resolution. | 
 | 492 |  */ | 
 | 493 |  | 
 | 494 |  | 
 | 495 | /* | 
 | 496 |  * TODO :  | 
 | 497 |  * 1.  To support WIDE transfers, not much needs to happen.  We | 
 | 498 |  *	should do CHMOVE instructions instead of MOVEs when | 
 | 499 |  *	we have scatter/gather segments of uneven length.  When | 
 | 500 |  * 	we do this, we need to handle the case where we disconnect | 
 | 501 |  *	between segments. | 
 | 502 |  *  | 
 | 503 |  * 2.  Currently, when Icky things happen we do a FATAL().  Instead, | 
 | 504 |  *     we want to do an integrity check on the parts of the NCR hostdata | 
 | 505 |  *     structure which were initialized at boot time; FATAL() if that  | 
 | 506 |  *     fails, and otherwise try to recover.  Keep track of how many | 
 | 507 |  *     times this has happened within a single SCSI command; if it  | 
 | 508 |  *     gets excessive, then FATAL(). | 
 | 509 |  * | 
 | 510 |  * 3.  Parity checking is currently disabled, and a few things should  | 
 | 511 |  *     happen here now that we support synchronous SCSI transfers : | 
 | 512 |  *     1.  On soft-reset, we shoould set the EPC (Enable Parity Checking) | 
 | 513 |  *	   and AAP (Assert SATN/ on parity error) bits in SCNTL0. | 
 | 514 |  *	 | 
 | 515 |  *     2.  We should enable the parity interrupt in the SIEN0 register. | 
 | 516 |  *  | 
 | 517 |  *     3.  intr_phase_mismatch() needs to believe that message out is  | 
 | 518 |  *	   always an "acceptable" phase to have a mismatch in.  If  | 
 | 519 |  *	   the old phase was MSG_IN, we should send a MESSAGE PARITY  | 
 | 520 |  *	   error.  If the old phase was something else, we should send | 
 | 521 |  *	   a INITIATOR_DETECTED_ERROR message.  Note that this could | 
 | 522 |  *	   cause a RESTORE POINTERS message; so we should handle that  | 
 | 523 |  *	   correctly first.  Instead, we should probably do an  | 
 | 524 |  *	   initiator_abort. | 
 | 525 |  * | 
 | 526 |  * 4.  MPEE bit of CTEST4 should be set so we get interrupted if  | 
 | 527 |  *     we detect an error. | 
 | 528 |  * | 
 | 529 |  *   | 
 | 530 |  * 5.  The initial code has been tested on the NCR53c810.  I don't  | 
 | 531 |  *     have access to NCR53c700, 700-66 (Forex boards), NCR53c710 | 
 | 532 |  *     (NCR Pentium systems), NCR53c720, NCR53c820, or NCR53c825 boards to  | 
 | 533 |  *     finish development on those platforms. | 
 | 534 |  * | 
 | 535 |  *     NCR53c820/825/720 - need to add wide transfer support, including WDTR  | 
 | 536 |  *     		negotiation, programming of wide transfer capabilities | 
 | 537 |  *		on reselection and table indirect selection. | 
 | 538 |  * | 
 | 539 |  *     NCR53c710 - need to add fatal interrupt or GEN code for  | 
 | 540 |  *		command completion signaling.   Need to modify all  | 
 | 541 |  *		SDID, SCID, etc. registers, and table indirect select code  | 
 | 542 |  *		since these use bit fielded (ie 1<<target) instead of  | 
 | 543 |  *		binary encoded target ids.  Need to accommodate | 
 | 544 |  *		different register mappings, probably scan through | 
 | 545 |  *		the SCRIPT code and change the non SFBR register operand | 
 | 546 |  *		of all MOVE instructions. | 
 | 547 |  * | 
 | 548 |  *		It is rather worse than this actually, the 710 corrupts | 
 | 549 |  *		both TEMP and DSA when you do a MOVE MEMORY.  This | 
 | 550 |  *		screws you up all over the place.  MOVE MEMORY 4 with a | 
 | 551 |  *		destination of DSA seems to work OK, which helps some. | 
 | 552 |  *		Richard Hirst  richard@sleepie.demon.co.uk | 
 | 553 |  *  | 
 | 554 |  *     NCR53c700/700-66 - need to add code to refix addresses on  | 
 | 555 |  *		every nexus change, eliminate all table indirect code, | 
 | 556 |  *		very messy. | 
 | 557 |  * | 
 | 558 |  * 6.  The NCR53c7x0 series is very popular on other platforms that  | 
 | 559 |  *     could be running Linux - ie, some high performance AMIGA SCSI  | 
 | 560 |  *     boards use it.   | 
 | 561 |  *	 | 
 | 562 |  *     So, I should include #ifdef'd code so that it is  | 
 | 563 |  *     compatible with these systems. | 
 | 564 |  *	 | 
 | 565 |  *     Specifically, the little Endian assumptions I made in my  | 
 | 566 |  *     bit fields need to change, and if the NCR doesn't see memory | 
 | 567 |  *     the right way, we need to provide options to reverse words | 
 | 568 |  *     when the scripts are relocated. | 
 | 569 |  * | 
 | 570 |  * 7.  Use vremap() to access memory mapped boards.   | 
 | 571 |  */ | 
 | 572 |  | 
 | 573 | /*  | 
 | 574 |  * Allow for simultaneous existence of multiple SCSI scripts so we  | 
 | 575 |  * can have a single driver binary for all of the family. | 
 | 576 |  * | 
 | 577 |  * - one for NCR53c700 and NCR53c700-66 chips	(not yet supported) | 
 | 578 |  * - one for rest (only the NCR53c810, 815, 820, and 825 are currently  | 
 | 579 |  *	supported) | 
 | 580 |  *  | 
 | 581 |  * So that we only need two SCSI scripts, we need to modify things so | 
 | 582 |  * that we fixup register accesses in READ/WRITE instructions, and  | 
 | 583 |  * we'll also have to accommodate the bit vs. binary encoding of IDs | 
 | 584 |  * with the 7xx chips. | 
 | 585 |  */ | 
 | 586 |  | 
 | 587 | #define ROUNDUP(adr,type)	\ | 
 | 588 |   ((void *) (((long) (adr) + sizeof(type) - 1) & ~(sizeof(type) - 1))) | 
 | 589 |  | 
 | 590 |  | 
 | 591 | /* | 
 | 592 |  * Function: issue_to_cmd | 
 | 593 |  * | 
 | 594 |  * Purpose: convert jump instruction in issue array to NCR53c7x0_cmd | 
 | 595 |  *	structure pointer.   | 
 | 596 |  * | 
 | 597 |  * Inputs; issue - pointer to start of NOP or JUMP instruction | 
 | 598 |  *	in issue array. | 
 | 599 |  * | 
 | 600 |  * Returns: pointer to command on success; 0 if opcode is NOP. | 
 | 601 |  */ | 
 | 602 |  | 
 | 603 | static inline struct NCR53c7x0_cmd * | 
 | 604 | issue_to_cmd (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, | 
 | 605 |     u32 *issue) | 
 | 606 | { | 
 | 607 |     return (issue[0] != hostdata->NOP_insn) ?  | 
 | 608 |     /*  | 
 | 609 |      * If the IF TRUE bit is set, it's a JUMP instruction.  The | 
 | 610 |      * operand is a bus pointer to the dsa_begin routine for this DSA.  The | 
 | 611 |      * dsa field of the NCR53c7x0_cmd structure starts with the  | 
 | 612 |      * DSA code template.  By converting to a virtual address, | 
 | 613 |      * subtracting the code template size, and offset of the  | 
 | 614 |      * dsa field, we end up with a pointer to the start of the  | 
 | 615 |      * structure (alternatively, we could use the  | 
 | 616 |      * dsa_cmnd field, an anachronism from when we weren't | 
 | 617 |      * sure what the relationship between the NCR structures | 
 | 618 |      * and host structures were going to be. | 
 | 619 |      */ | 
 | 620 | 	(struct NCR53c7x0_cmd *) ((char *) bus_to_virt (issue[1]) -  | 
 | 621 | 	    (hostdata->E_dsa_code_begin - hostdata->E_dsa_code_template) - | 
 | 622 | 	    offsetof(struct NCR53c7x0_cmd, dsa))  | 
 | 623 |     /* If the IF TRUE bit is not set, it's a NOP */ | 
 | 624 | 	: NULL; | 
 | 625 | } | 
 | 626 |  | 
 | 627 |  | 
 | 628 | /*  | 
 | 629 |  * FIXME: we should junk these, in favor of synchronous_want and  | 
 | 630 |  * wide_want in the NCR53c7x0_hostdata structure. | 
 | 631 |  */ | 
 | 632 |  | 
 | 633 | /* Template for "preferred" synchronous transfer parameters. */ | 
 | 634 |  | 
 | 635 | static const unsigned char sdtr_message[] = { | 
 | 636 | #ifdef CONFIG_SCSI_NCR53C7xx_FAST | 
 | 637 |     EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 25 /* *4ns */, 8 /* off */ | 
 | 638 | #else | 
 | 639 |     EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 50 /* *4ns */, 8 /* off */  | 
 | 640 | #endif | 
 | 641 | }; | 
 | 642 |  | 
 | 643 | /* Template to request asynchronous transfers */ | 
 | 644 |  | 
 | 645 | static const unsigned char async_message[] = { | 
 | 646 |     EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */ | 
 | 647 | }; | 
 | 648 |  | 
 | 649 | /* Template for "preferred" WIDE transfer parameters */ | 
 | 650 |  | 
 | 651 | static const unsigned char wdtr_message[] = { | 
 | 652 |     EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */ | 
 | 653 | }; | 
 | 654 |  | 
 | 655 | #if 0 | 
 | 656 | /* | 
 | 657 |  * Function : struct Scsi_Host *find_host (int host) | 
 | 658 |  *  | 
 | 659 |  * Purpose : KGDB support function which translates a host number  | 
 | 660 |  * 	to a host structure.  | 
 | 661 |  * | 
 | 662 |  * Inputs : host - number of SCSI host | 
 | 663 |  * | 
 | 664 |  * Returns : NULL on failure, pointer to host structure on success. | 
 | 665 |  */ | 
 | 666 |  | 
 | 667 | static struct Scsi_Host * | 
 | 668 | find_host (int host) { | 
 | 669 |     struct Scsi_Host *h; | 
 | 670 |     for (h = first_host; h && h->host_no != host; h = h->next); | 
 | 671 |     if (!h) { | 
 | 672 | 	printk (KERN_ALERT "scsi%d not found\n", host); | 
 | 673 | 	return NULL; | 
 | 674 |     } else if (h->hostt != the_template) { | 
 | 675 | 	printk (KERN_ALERT "scsi%d is not a NCR board\n", host); | 
 | 676 | 	return NULL; | 
 | 677 |     } | 
 | 678 |     return h; | 
 | 679 | } | 
 | 680 |  | 
 | 681 | #if 0 | 
 | 682 | /* | 
 | 683 |  * Function : request_synchronous (int host, int target) | 
 | 684 |  *  | 
 | 685 |  * Purpose : KGDB interface which will allow us to negotiate for  | 
 | 686 |  * 	synchronous transfers.  This ill be replaced with a more  | 
 | 687 |  * 	integrated function; perhaps a new entry in the scsi_host  | 
 | 688 |  *	structure, accessible via an ioctl() or perhaps /proc/scsi. | 
 | 689 |  * | 
 | 690 |  * Inputs : host - number of SCSI host; target - number of target. | 
 | 691 |  * | 
 | 692 |  * Returns : 0 when negotiation has been setup for next SCSI command, | 
 | 693 |  *	-1 on failure. | 
 | 694 |  */ | 
 | 695 |  | 
 | 696 | static int | 
 | 697 | request_synchronous (int host, int target) { | 
 | 698 |     struct Scsi_Host *h; | 
 | 699 |     struct NCR53c7x0_hostdata *hostdata; | 
 | 700 |     unsigned long flags; | 
 | 701 |     if (target < 0) { | 
 | 702 | 	printk (KERN_ALERT "target %d is bogus\n", target); | 
 | 703 | 	return -1; | 
 | 704 |     } | 
 | 705 |     if (!(h = find_host (host))) | 
 | 706 | 	return -1; | 
 | 707 |     else if (h->this_id == target) { | 
 | 708 | 	printk (KERN_ALERT "target %d is host ID\n", target); | 
 | 709 | 	return -1; | 
 | 710 |     }  | 
 | 711 |     else if (target > h->max_id) { | 
 | 712 | 	printk (KERN_ALERT "target %d exceeds maximum of %d\n", target, | 
 | 713 | 	    h->max_id); | 
 | 714 | 	return -1; | 
 | 715 |     } | 
 | 716 |     hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0]; | 
 | 717 |  | 
 | 718 |     local_irq_save(flags); | 
 | 719 |     if (hostdata->initiate_sdtr & (1 << target)) { | 
 | 720 | 	local_irq_restore(flags); | 
 | 721 | 	printk (KERN_ALERT "target %d already doing SDTR\n", target); | 
 | 722 | 	return -1; | 
 | 723 |     }  | 
 | 724 |     hostdata->initiate_sdtr |= (1 << target); | 
 | 725 |     local_irq_restore(flags); | 
 | 726 |     return 0; | 
 | 727 | } | 
 | 728 | #endif | 
 | 729 |  | 
 | 730 | /* | 
 | 731 |  * Function : request_disconnect (int host, int on_or_off) | 
 | 732 |  *  | 
 | 733 |  * Purpose : KGDB support function, tells us to allow or disallow  | 
 | 734 |  *	disconnections. | 
 | 735 |  * | 
 | 736 |  * Inputs : host - number of SCSI host; on_or_off - non-zero to allow, | 
 | 737 |  *	zero to disallow. | 
 | 738 |  * | 
 | 739 |  * Returns : 0 on success, *	-1 on failure. | 
 | 740 |  */ | 
 | 741 |  | 
 | 742 | static int  | 
 | 743 | request_disconnect (int host, int on_or_off) { | 
 | 744 |     struct Scsi_Host *h; | 
 | 745 |     struct NCR53c7x0_hostdata *hostdata; | 
 | 746 |     if (!(h = find_host (host))) | 
 | 747 | 	return -1; | 
 | 748 |     hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0]; | 
 | 749 |     if (on_or_off)  | 
 | 750 | 	hostdata->options |= OPTION_DISCONNECT; | 
 | 751 |     else | 
 | 752 | 	hostdata->options &= ~OPTION_DISCONNECT; | 
 | 753 |     return 0; | 
 | 754 | } | 
 | 755 | #endif | 
 | 756 |  | 
 | 757 | /* | 
 | 758 |  * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host) | 
 | 759 |  * | 
 | 760 |  * Purpose : Initialize internal structures, as required on startup, or  | 
 | 761 |  *	after a SCSI bus reset. | 
 | 762 |  *  | 
 | 763 |  * Inputs : host - pointer to this host adapter's structure | 
 | 764 |  */ | 
 | 765 |  | 
 | 766 | static void  | 
 | 767 | NCR53c7x0_driver_init (struct Scsi_Host *host) { | 
 | 768 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 769 | 	host->hostdata[0]; | 
 | 770 |     int i, j; | 
 | 771 |     u32 *ncrcurrent; | 
 | 772 |  | 
 | 773 |     for (i = 0; i < 16; ++i) { | 
 | 774 | 	hostdata->request_sense[i] = 0; | 
 | 775 |     	for (j = 0; j < 8; ++j)  | 
 | 776 | 	    hostdata->busy[i][j] = 0; | 
 | 777 | 	set_synchronous (host, i, /* sxfer */ 0, hostdata->saved_scntl3, 0); | 
 | 778 |     } | 
 | 779 |     hostdata->issue_queue = NULL; | 
 | 780 |     hostdata->running_list = hostdata->finished_queue =  | 
 | 781 | 	hostdata->ncrcurrent = NULL; | 
 | 782 |     for (i = 0, ncrcurrent = (u32 *) hostdata->schedule;  | 
 | 783 | 	i < host->can_queue; ++i, ncrcurrent += 2) { | 
 | 784 | 	ncrcurrent[0] = hostdata->NOP_insn; | 
 | 785 | 	ncrcurrent[1] = 0xdeadbeef; | 
 | 786 |     } | 
 | 787 |     ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | DBC_TCI_TRUE; | 
 | 788 |     ncrcurrent[1] = (u32) virt_to_bus (hostdata->script) + | 
 | 789 | 	hostdata->E_wait_reselect; | 
 | 790 |     hostdata->reconnect_dsa_head = 0; | 
 | 791 |     hostdata->addr_reconnect_dsa_head = (u32)  | 
 | 792 | 	virt_to_bus((void *) &(hostdata->reconnect_dsa_head)); | 
 | 793 |     hostdata->expecting_iid = 0; | 
 | 794 |     hostdata->expecting_sto = 0; | 
 | 795 |     if (hostdata->options & OPTION_ALWAYS_SYNCHRONOUS)  | 
 | 796 | 	hostdata->initiate_sdtr = 0xffff;  | 
 | 797 |     else | 
 | 798 |     	hostdata->initiate_sdtr = 0; | 
 | 799 |     hostdata->talked_to = 0; | 
 | 800 |     hostdata->idle = 1; | 
 | 801 | } | 
 | 802 |  | 
 | 803 | /*  | 
 | 804 |  * Function : static int clock_to_ccf_710 (int clock) | 
 | 805 |  * | 
 | 806 |  * Purpose :  Return the clock conversion factor for a given SCSI clock. | 
 | 807 |  * | 
 | 808 |  * Inputs : clock - SCSI clock expressed in Hz. | 
 | 809 |  * | 
 | 810 |  * Returns : ccf on success, -1 on failure. | 
 | 811 |  */ | 
 | 812 |  | 
 | 813 | static int  | 
 | 814 | clock_to_ccf_710 (int clock) { | 
 | 815 |     if (clock <= 16666666) | 
 | 816 | 	return -1; | 
 | 817 |     if (clock <= 25000000) | 
 | 818 | 	return 2; 	/* Divide by 1.0 */ | 
 | 819 |     else if (clock <= 37500000) | 
 | 820 | 	return 1; 	/* Divide by 1.5 */ | 
 | 821 |     else if (clock <= 50000000) | 
 | 822 | 	return 0;	/* Divide by 2.0 */ | 
 | 823 |     else if (clock <= 66000000) | 
 | 824 | 	return 3;	/* Divide by 3.0 */ | 
 | 825 |     else  | 
 | 826 | 	return -1; | 
 | 827 | } | 
 | 828 |      | 
 | 829 | /*  | 
 | 830 |  * Function : static int NCR53c7x0_init (struct Scsi_Host *host) | 
 | 831 |  * | 
 | 832 |  * Purpose :  initialize the internal structures for a given SCSI host | 
 | 833 |  * | 
 | 834 |  * Inputs : host - pointer to this host adapter's structure | 
 | 835 |  * | 
 | 836 |  * Preconditions : when this function is called, the chip_type  | 
 | 837 |  * 	field of the hostdata structure MUST have been set. | 
 | 838 |  * | 
 | 839 |  * Returns : 0 on success, -1 on failure. | 
 | 840 |  */ | 
 | 841 |  | 
 | 842 | int  | 
 | 843 | NCR53c7x0_init (struct Scsi_Host *host) { | 
 | 844 |     NCR53c7x0_local_declare(); | 
 | 845 |     int i, ccf; | 
 | 846 |     unsigned char revision; | 
 | 847 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 848 | 	host->hostdata[0]; | 
 | 849 |     /*  | 
 | 850 |      * There are some things which we need to know about in order to provide | 
 | 851 |      * a semblance of support.  Print 'em if they aren't what we expect,  | 
 | 852 |      * otherwise don't add to the noise. | 
 | 853 |      *  | 
 | 854 |      * -1 means we don't know what to expect. | 
 | 855 |      */ | 
 | 856 |     int val, flags; | 
 | 857 |     char buf[32]; | 
 | 858 |     int expected_id = -1; | 
 | 859 |     int expected_clock = -1; | 
 | 860 |     int uninitialized = 0; | 
 | 861 | #ifdef NO_IO_SPACE | 
 | 862 |     int expected_mapping = OPTION_MEMORY_MAPPED; | 
 | 863 | #else | 
 | 864 |     int expected_mapping = OPTION_IO_MAPPED; | 
 | 865 | #endif | 
 | 866 |     for (i=0;i<7;i++) | 
 | 867 | 	hostdata->valid_ids[i] = 1;	/* Default all ID's to scan */ | 
 | 868 |  | 
 | 869 |     /* Parse commandline flags */ | 
 | 870 |     if (check_setup_strings("noasync",&flags,&val,buf)) | 
 | 871 |     { | 
 | 872 | 	hostdata->options |= OPTION_NO_ASYNC; | 
 | 873 | 	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS); | 
 | 874 |     } | 
 | 875 |  | 
 | 876 |     if (check_setup_strings("nosync",&flags,&val,buf)) | 
 | 877 |     { | 
 | 878 | 	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS); | 
 | 879 |     } | 
 | 880 |  | 
 | 881 |     if (check_setup_strings("nodisconnect",&flags,&val,buf)) | 
 | 882 | 	hostdata->options &= ~OPTION_DISCONNECT; | 
 | 883 |  | 
 | 884 |     if (check_setup_strings("validids",&flags,&val,buf)) | 
 | 885 |     { | 
 | 886 | 	for (i=0;i<7;i++)  | 
 | 887 | 		hostdata->valid_ids[i] = val & (1<<i); | 
 | 888 |     } | 
 | 889 |   | 
 | 890 |     if  ((i = check_setup_strings("next",&flags,&val,buf))) | 
 | 891 |     { | 
 | 892 | 	while (i) | 
 | 893 | 		setup_used[--i] = 1; | 
 | 894 |     } | 
 | 895 |  | 
 | 896 |     if (check_setup_strings("opthi",&flags,&val,buf)) | 
 | 897 | 	hostdata->options = (long long)val << 32; | 
 | 898 |     if (check_setup_strings("optlo",&flags,&val,buf)) | 
 | 899 | 	hostdata->options |= val; | 
 | 900 |  | 
 | 901 |     NCR53c7x0_local_setup(host); | 
 | 902 |     switch (hostdata->chip) { | 
 | 903 |     case 710: | 
 | 904 |     case 770: | 
 | 905 |     	hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr; | 
 | 906 |     	hostdata->init_save_regs = NULL; | 
 | 907 |     	hostdata->dsa_fixup = NCR53c7xx_dsa_fixup; | 
 | 908 |     	hostdata->init_fixup = NCR53c7x0_init_fixup; | 
 | 909 |     	hostdata->soft_reset = NCR53c7x0_soft_reset; | 
 | 910 | 	hostdata->run_tests = NCR53c7xx_run_tests; | 
 | 911 | 	expected_clock = hostdata->scsi_clock; | 
 | 912 | 	expected_id = 7; | 
 | 913 |     	break; | 
 | 914 |     default: | 
 | 915 | 	printk ("scsi%d : chip type of %d is not supported yet, detaching.\n", | 
 | 916 | 	    host->host_no, hostdata->chip); | 
 | 917 | 	scsi_unregister (host); | 
 | 918 | 	return -1; | 
 | 919 |     } | 
 | 920 |  | 
 | 921 |     /* Assign constants accessed by NCR */ | 
 | 922 |     hostdata->NCR53c7xx_zero = 0;			 | 
 | 923 |     hostdata->NCR53c7xx_msg_reject = MESSAGE_REJECT; | 
 | 924 |     hostdata->NCR53c7xx_msg_abort = ABORT; | 
 | 925 |     hostdata->NCR53c7xx_msg_nop = NOP; | 
 | 926 |     hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24; | 
 | 927 |     if (expected_mapping == -1 ||  | 
 | 928 | 	(hostdata->options & (OPTION_MEMORY_MAPPED)) !=  | 
 | 929 | 	(expected_mapping & OPTION_MEMORY_MAPPED)) | 
 | 930 | 	printk ("scsi%d : using %s mapped access\n", host->host_no,  | 
 | 931 | 	    (hostdata->options & OPTION_MEMORY_MAPPED) ? "memory" :  | 
 | 932 | 	    "io"); | 
 | 933 |  | 
 | 934 |     hostdata->dmode = (hostdata->chip == 700 || hostdata->chip == 70066) ?  | 
 | 935 | 	DMODE_REG_00 : DMODE_REG_10; | 
 | 936 |     hostdata->istat = ((hostdata->chip / 100) == 8) ?  | 
 | 937 |     	ISTAT_REG_800 : ISTAT_REG_700; | 
 | 938 |  | 
 | 939 | /* We have to assume that this may be the first access to the chip, so | 
 | 940 |  * we must set EA in DCNTL. */ | 
 | 941 |  | 
 | 942 |     NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM); | 
 | 943 |  | 
 | 944 |  | 
 | 945 | /* Only the ISTAT register is readable when the NCR is running, so make  | 
 | 946 |    sure it's halted. */ | 
 | 947 |     ncr_halt(host); | 
 | 948 |  | 
 | 949 | /*  | 
 | 950 |  * XXX - the NCR53c700 uses bitfielded registers for SCID, SDID, etc, | 
 | 951 |  *	as does the 710 with one bit per SCSI ID.  Conversely, the NCR | 
 | 952 |  * 	uses a normal, 3 bit binary representation of these values. | 
 | 953 |  * | 
 | 954 |  * Get the rest of the NCR documentation, and FIND OUT where the change | 
 | 955 |  * was. | 
 | 956 |  */ | 
 | 957 |  | 
 | 958 | #if 0 | 
 | 959 | 	/* May not be able to do this - chip my not have been set up yet */ | 
 | 960 | 	tmp = hostdata->this_id_mask = NCR53c7x0_read8(SCID_REG); | 
 | 961 | 	for (host->this_id = 0; tmp != 1; tmp >>=1, ++host->this_id); | 
 | 962 | #else | 
 | 963 | 	host->this_id = 7; | 
 | 964 | #endif | 
 | 965 |  | 
 | 966 | /* | 
 | 967 |  * Note : we should never encounter a board setup for ID0.  So, | 
 | 968 |  * 	if we see ID0, assume that it was uninitialized and set it | 
 | 969 |  * 	to the industry standard 7. | 
 | 970 |  */ | 
 | 971 |     if (!host->this_id) { | 
 | 972 | 	printk("scsi%d : initiator ID was %d, changing to 7\n", | 
 | 973 | 	    host->host_no, host->this_id); | 
 | 974 | 	host->this_id = 7; | 
 | 975 | 	hostdata->this_id_mask = 1 << 7; | 
 | 976 | 	uninitialized = 1; | 
 | 977 |     }; | 
 | 978 |  | 
 | 979 |     if (expected_id == -1 || host->this_id != expected_id) | 
 | 980 |     	printk("scsi%d : using initiator ID %d\n", host->host_no, | 
 | 981 |     	    host->this_id); | 
 | 982 |  | 
 | 983 |     /* | 
 | 984 |      * Save important registers to allow a soft reset. | 
 | 985 |      */ | 
 | 986 |  | 
 | 987 |     /* | 
 | 988 |      * CTEST7 controls cache snooping, burst mode, and support for  | 
 | 989 |      * external differential drivers.  This isn't currently used - the | 
 | 990 |      * default value may not be optimal anyway. | 
 | 991 |      * Even worse, it may never have been set up since reset. | 
 | 992 |      */ | 
 | 993 |     hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE; | 
 | 994 |     revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4; | 
 | 995 |     switch (revision) { | 
 | 996 | 	case 1: revision = 0;    break; | 
 | 997 | 	case 2: revision = 1;    break; | 
 | 998 | 	case 4: revision = 2;    break; | 
 | 999 | 	case 8: revision = 3;    break; | 
 | 1000 | 	default: revision = 255; break; | 
 | 1001 |     } | 
 | 1002 |     printk("scsi%d: Revision 0x%x\n",host->host_no,revision); | 
 | 1003 |  | 
 | 1004 |     if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS))) | 
 | 1005 |     { | 
 | 1006 | 	printk ("scsi%d: Disabling sync working and disconnect/reselect\n", | 
 | 1007 | 							host->host_no); | 
 | 1008 | 	hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS); | 
 | 1009 |     } | 
 | 1010 |  | 
 | 1011 |     /* | 
 | 1012 |      * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor, | 
 | 1013 |      * on 800 series chips, it allows for a totem-pole IRQ driver. | 
 | 1014 |      * NOTE saved_dcntl currently overwritten in init function. | 
 | 1015 |      * The value read here may be garbage anyway, MVME16x board at least | 
 | 1016 |      * does not initialise chip if kernel arrived via tftp. | 
 | 1017 |      */ | 
 | 1018 |  | 
 | 1019 |     hostdata->saved_dcntl = NCR53c7x0_read8(DCNTL_REG); | 
 | 1020 |  | 
 | 1021 |     /* | 
 | 1022 |      * DMODE controls DMA burst length, and on 700 series chips, | 
 | 1023 |      * 286 mode and bus width   | 
 | 1024 |      * NOTE:  On MVME16x, chip may have been reset, so this could be a | 
 | 1025 |      * power-on/reset default value. | 
 | 1026 |      */ | 
 | 1027 |     hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode); | 
 | 1028 |  | 
 | 1029 |     /*  | 
 | 1030 |      * Now that burst length and enabled/disabled status is known,  | 
 | 1031 |      * clue the user in on it.   | 
 | 1032 |      */ | 
 | 1033 |     | 
 | 1034 |     ccf = clock_to_ccf_710 (expected_clock); | 
 | 1035 |  | 
 | 1036 |     for (i = 0; i < 16; ++i)  | 
 | 1037 | 	hostdata->cmd_allocated[i] = 0; | 
 | 1038 |  | 
 | 1039 |     if (hostdata->init_save_regs) | 
 | 1040 |     	hostdata->init_save_regs (host); | 
 | 1041 |     if (hostdata->init_fixup) | 
 | 1042 |     	hostdata->init_fixup (host); | 
 | 1043 |  | 
 | 1044 |     if (!the_template) { | 
 | 1045 | 	the_template = host->hostt; | 
 | 1046 | 	first_host = host; | 
 | 1047 |     } | 
 | 1048 |  | 
 | 1049 |     /*  | 
 | 1050 |      * Linux SCSI drivers have always been plagued with initialization  | 
 | 1051 |      * problems - some didn't work with the BIOS disabled since they expected | 
 | 1052 |      * initialization from it, some didn't work when the networking code | 
 | 1053 |      * was enabled and registers got scrambled, etc. | 
 | 1054 |      * | 
 | 1055 |      * To avoid problems like this, in the future, we will do a soft  | 
 | 1056 |      * reset on the SCSI chip, taking it back to a sane state. | 
 | 1057 |      */ | 
 | 1058 |  | 
 | 1059 |     hostdata->soft_reset (host); | 
 | 1060 |  | 
 | 1061 | #if 1 | 
 | 1062 |     hostdata->debug_count_limit = -1; | 
 | 1063 | #else | 
 | 1064 |     hostdata->debug_count_limit = 1; | 
 | 1065 | #endif | 
 | 1066 |     hostdata->intrs = -1; | 
 | 1067 |     hostdata->resets = -1; | 
 | 1068 |     memcpy ((void *) hostdata->synchronous_want, (void *) sdtr_message,  | 
 | 1069 | 	sizeof (hostdata->synchronous_want)); | 
 | 1070 |  | 
 | 1071 |     NCR53c7x0_driver_init (host); | 
 | 1072 |  | 
 | 1073 |     if (request_irq(host->irq, NCR53c7x0_intr, SA_SHIRQ, "53c7xx", host)) | 
 | 1074 |     { | 
 | 1075 | 	printk("scsi%d : IRQ%d not free, detaching\n", | 
 | 1076 | 		host->host_no, host->irq); | 
 | 1077 | 	goto err_unregister; | 
 | 1078 |     }  | 
 | 1079 |  | 
 | 1080 |     if ((hostdata->run_tests && hostdata->run_tests(host) == -1) || | 
 | 1081 |         (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) { | 
 | 1082 |     	/* XXX Should disable interrupts, etc. here */ | 
 | 1083 | 	goto err_free_irq; | 
 | 1084 |     } else { | 
 | 1085 | 	if (host->io_port)  { | 
 | 1086 | 	    host->n_io_port = 128; | 
 | 1087 | 	    if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx")) | 
 | 1088 | 		goto err_free_irq; | 
 | 1089 | 	} | 
 | 1090 |     } | 
 | 1091 |      | 
 | 1092 |     if (NCR53c7x0_read8 (SBCL_REG) & SBCL_BSY) { | 
 | 1093 | 	printk ("scsi%d : bus wedge, doing SCSI reset\n", host->host_no); | 
 | 1094 | 	hard_reset (host); | 
 | 1095 |     } | 
 | 1096 |     return 0; | 
 | 1097 |  | 
 | 1098 |  err_free_irq: | 
 | 1099 |     free_irq(host->irq,  NCR53c7x0_intr); | 
 | 1100 |  err_unregister: | 
 | 1101 |     scsi_unregister(host); | 
 | 1102 |     return -1; | 
 | 1103 | } | 
 | 1104 |  | 
 | 1105 | /*  | 
 | 1106 |  * Function : int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board, int chip, | 
 | 1107 |  *	unsigned long base, int io_port, int irq, int dma, long long options, | 
 | 1108 |  *	int clock); | 
 | 1109 |  * | 
 | 1110 |  * Purpose : initializes a NCR53c7,8x0 based on base addresses, | 
 | 1111 |  *	IRQ, and DMA channel.	 | 
 | 1112 |  *	 | 
 | 1113 |  * Inputs : tpnt - Template for this SCSI adapter, board - board level | 
 | 1114 |  *	product, chip - 710 | 
 | 1115 |  *  | 
 | 1116 |  * Returns : 0 on success, -1 on failure. | 
 | 1117 |  * | 
 | 1118 |  */ | 
 | 1119 |  | 
 | 1120 | int  | 
 | 1121 | ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, | 
 | 1122 |     unsigned long base, int io_port, int irq, int dma,  | 
 | 1123 |     long long options, int clock) | 
 | 1124 | { | 
 | 1125 |     struct Scsi_Host *instance; | 
 | 1126 |     struct NCR53c7x0_hostdata *hostdata; | 
 | 1127 |     char chip_str[80]; | 
 | 1128 |     int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0, | 
 | 1129 | 	schedule_size = 0, ok = 0; | 
 | 1130 |     void *tmp; | 
 | 1131 |     unsigned long page; | 
 | 1132 |  | 
 | 1133 |     switch (chip) { | 
 | 1134 |     case 710: | 
 | 1135 |     case 770: | 
 | 1136 | 	schedule_size = (tpnt->can_queue + 1) * 8 /* JUMP instruction size */; | 
 | 1137 | 	script_len = NCR53c7xx_script_len; | 
 | 1138 |     	dsa_len = NCR53c7xx_dsa_len; | 
 | 1139 |     	options |= OPTION_INTFLY; | 
 | 1140 |     	sprintf (chip_str, "NCR53c%d", chip); | 
 | 1141 |     	break; | 
 | 1142 |     default: | 
 | 1143 |     	printk("scsi-ncr53c7xx : unsupported SCSI chip %d\n", chip); | 
 | 1144 |     	return -1; | 
 | 1145 |     } | 
 | 1146 |  | 
 | 1147 |     printk("scsi-ncr53c7xx : %s at memory 0x%lx, io 0x%x, irq %d", | 
 | 1148 |     	chip_str, base, io_port, irq); | 
 | 1149 |     if (dma == DMA_NONE) | 
 | 1150 |     	printk("\n"); | 
 | 1151 |     else  | 
 | 1152 |     	printk(", dma %d\n", dma); | 
 | 1153 |  | 
 | 1154 |     if (options & OPTION_DEBUG_PROBE_ONLY) { | 
 | 1155 |     	printk ("scsi-ncr53c7xx : probe only enabled, aborting initialization\n"); | 
 | 1156 |     	return -1; | 
 | 1157 |     } | 
 | 1158 |  | 
 | 1159 |     max_cmd_size = sizeof(struct NCR53c7x0_cmd) + dsa_len + | 
 | 1160 |     	/* Size of dynamic part of command structure : */ | 
 | 1161 | 	2 * /* Worst case : we don't know if we need DATA IN or DATA out */ | 
 | 1162 | 		( 2 * /* Current instructions per scatter/gather segment */  | 
 | 1163 |         	  tpnt->sg_tablesize +  | 
 | 1164 |                   3 /* Current startup / termination required per phase */ | 
 | 1165 | 		) * | 
 | 1166 | 	8 /* Each instruction is eight bytes */; | 
 | 1167 |  | 
 | 1168 |     /* Allocate fixed part of hostdata, dynamic part to hold appropriate | 
 | 1169 |        SCSI SCRIPT(tm) plus a single, maximum-sized NCR53c7x0_cmd structure. | 
 | 1170 |  | 
 | 1171 |        We need a NCR53c7x0_cmd structure for scan_scsis() when we are  | 
 | 1172 |        not loaded as a module, and when we're loaded as a module, we  | 
 | 1173 |        can't use a non-dynamically allocated structure because modules | 
 | 1174 |        are vmalloc()'d, which can allow structures to cross page  | 
 | 1175 |        boundaries and breaks our physical/virtual address assumptions | 
 | 1176 |        for DMA. | 
 | 1177 |  | 
 | 1178 |        So, we stick it past the end of our hostdata structure. | 
 | 1179 |  | 
 | 1180 |        ASSUMPTION :  | 
 | 1181 |        	 Regardless of how many simultaneous SCSI commands we allow, | 
 | 1182 | 	 the probe code only executes a _single_ instruction at a time, | 
 | 1183 | 	 so we only need one here, and don't need to allocate NCR53c7x0_cmd | 
 | 1184 | 	 structures for each target until we are no longer in scan_scsis | 
 | 1185 | 	 and kmalloc() has become functional (memory_init() happens  | 
 | 1186 | 	 after all device driver initialization). | 
 | 1187 |     */ | 
 | 1188 |  | 
 | 1189 |     size = sizeof(struct NCR53c7x0_hostdata) + script_len +  | 
 | 1190 |     /* Note that alignment will be guaranteed, since we put the command | 
 | 1191 |        allocated at probe time after the fixed-up SCSI script, which  | 
 | 1192 |        consists of 32 bit words, aligned on a 32 bit boundary.  But | 
 | 1193 |        on a 64bit machine we need 8 byte alignment for hostdata->free, so | 
 | 1194 |        we add in another 4 bytes to take care of potential misalignment | 
 | 1195 |        */ | 
 | 1196 | 	(sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size; | 
 | 1197 |  | 
 | 1198 |     page = __get_free_pages(GFP_ATOMIC,1); | 
 | 1199 |     if(page==0) | 
 | 1200 |     { | 
 | 1201 |     	printk(KERN_ERR "53c7xx: out of memory.\n"); | 
 | 1202 |     	return -ENOMEM; | 
 | 1203 |     } | 
 | 1204 | #ifdef FORCE_DSA_ALIGNMENT | 
 | 1205 |     /* | 
 | 1206 |      * 53c710 rev.0 doesn't have an add-with-carry instruction. | 
 | 1207 |      * Ensure we allocate enough memory to force DSA alignment. | 
 | 1208 |     */ | 
 | 1209 |     size += 256; | 
 | 1210 | #endif | 
 | 1211 |     /* Size should be < 8K, so we can fit it in two pages. */ | 
 | 1212 |     if (size > 8192) { | 
 | 1213 |       printk(KERN_ERR "53c7xx: hostdata > 8K\n"); | 
 | 1214 |       return -1; | 
 | 1215 |     } | 
 | 1216 |  | 
 | 1217 |     instance = scsi_register (tpnt, 4); | 
 | 1218 |     if (!instance) | 
 | 1219 |     { | 
 | 1220 |         free_page(page); | 
 | 1221 | 	return -1; | 
 | 1222 |     } | 
 | 1223 |     instance->hostdata[0] = page; | 
 | 1224 |     memset((void *)instance->hostdata[0], 0, 8192); | 
 | 1225 |     cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192); | 
 | 1226 |     cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192); | 
 | 1227 |     kernel_set_cachemode((void *)instance->hostdata[0], 8192, IOMAP_NOCACHE_SER); | 
 | 1228 |  | 
 | 1229 |     /* FIXME : if we ever support an ISA NCR53c7xx based board, we | 
 | 1230 |        need to check if the chip is running in a 16 bit mode, and if so  | 
 | 1231 |        unregister it if it is past the 16M (0x1000000) mark */ | 
 | 1232 |  | 
 | 1233 |     hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0]; | 
 | 1234 |     hostdata->size = size; | 
 | 1235 |     hostdata->script_count = script_len / sizeof(u32); | 
 | 1236 |     hostdata->board = board; | 
 | 1237 |     hostdata->chip = chip; | 
 | 1238 |  | 
 | 1239 |     /* | 
 | 1240 |      * Being memory mapped is more desirable, since  | 
 | 1241 |      * | 
 | 1242 |      * - Memory accesses may be faster. | 
 | 1243 |      * | 
 | 1244 |      * - The destination and source address spaces are the same for  | 
 | 1245 |      *	 all instructions, meaning we don't have to twiddle dmode or  | 
 | 1246 |      *	 any other registers. | 
 | 1247 |      * | 
 | 1248 |      * So, we try for memory mapped, and if we don't get it, | 
 | 1249 |      * we go for port mapped, and that failing we tell the user | 
 | 1250 |      * it can't work. | 
 | 1251 |      */ | 
 | 1252 |  | 
 | 1253 |     if (base) { | 
 | 1254 | 	instance->base = base; | 
 | 1255 | 	/* Check for forced I/O mapping */ | 
 | 1256 |     	if (!(options & OPTION_IO_MAPPED)) { | 
 | 1257 | 	    options |= OPTION_MEMORY_MAPPED; | 
 | 1258 | 	    ok = 1; | 
 | 1259 | 	} | 
 | 1260 |     } else { | 
 | 1261 | 	options &= ~OPTION_MEMORY_MAPPED; | 
 | 1262 |     } | 
 | 1263 |  | 
 | 1264 |     if (io_port) { | 
 | 1265 | 	instance->io_port = io_port; | 
 | 1266 | 	options |= OPTION_IO_MAPPED; | 
 | 1267 | 	ok = 1; | 
 | 1268 |     } else { | 
 | 1269 | 	options &= ~OPTION_IO_MAPPED; | 
 | 1270 |     } | 
 | 1271 |  | 
 | 1272 |     if (!ok) { | 
 | 1273 | 	printk ("scsi%d : not initializing, no I/O or memory mapping known \n", | 
 | 1274 | 	    instance->host_no); | 
 | 1275 | 	scsi_unregister (instance); | 
 | 1276 | 	return -1; | 
 | 1277 |     } | 
 | 1278 |     instance->irq = irq; | 
 | 1279 |     instance->dma_channel = dma; | 
 | 1280 |  | 
 | 1281 |     hostdata->options = options; | 
 | 1282 |     hostdata->dsa_len = dsa_len; | 
 | 1283 |     hostdata->max_cmd_size = max_cmd_size; | 
 | 1284 |     hostdata->num_cmds = 1; | 
 | 1285 |     hostdata->scsi_clock = clock; | 
 | 1286 |     /* Initialize single command */ | 
 | 1287 |     tmp = (hostdata->script + hostdata->script_count); | 
 | 1288 | #ifdef FORCE_DSA_ALIGNMENT | 
 | 1289 |     { | 
 | 1290 | 	void *t = ROUNDUP(tmp, void *); | 
 | 1291 | 	if (((u32)t & 0xff) > CmdPageStart) | 
 | 1292 | 	    t = (void *)((u32)t + 255); | 
 | 1293 | 	t = (void *)(((u32)t & ~0xff) + CmdPageStart); | 
 | 1294 |         hostdata->free = t; | 
 | 1295 | #if 0 | 
 | 1296 | 	printk ("scsi: Registered size increased by 256 to %d\n", size); | 
 | 1297 | 	printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart); | 
 | 1298 | 	printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n", | 
 | 1299 | 			(u32)tmp, (u32)t); | 
 | 1300 | #endif | 
 | 1301 |     } | 
 | 1302 | #else | 
 | 1303 |     hostdata->free = ROUNDUP(tmp, void *); | 
 | 1304 | #endif | 
 | 1305 |     hostdata->free->real = tmp; | 
 | 1306 |     hostdata->free->size = max_cmd_size; | 
 | 1307 |     hostdata->free->free = NULL; | 
 | 1308 |     hostdata->free->next = NULL; | 
 | 1309 |     hostdata->extra_allocate = 0; | 
 | 1310 |  | 
 | 1311 |     /* Allocate command start code space */ | 
 | 1312 |     hostdata->schedule = (chip == 700 || chip == 70066) ? | 
 | 1313 | 	NULL : (u32 *) ((char *)hostdata->free + max_cmd_size); | 
 | 1314 |  | 
 | 1315 | /*  | 
 | 1316 |  * For diagnostic purposes, we don't really care how fast things blaze. | 
 | 1317 |  * For profiling, we want to access the 800ns resolution system clock, | 
 | 1318 |  * using a 'C' call on the host processor. | 
 | 1319 |  * | 
 | 1320 |  * Therefore, there's no need for the NCR chip to directly manipulate | 
 | 1321 |  * this data, and we should put it wherever is most convenient for  | 
 | 1322 |  * Linux. | 
 | 1323 |  */ | 
 | 1324 |     if (track_events)  | 
 | 1325 | 	hostdata->events = (struct NCR53c7x0_event *) (track_events ?  | 
 | 1326 | 	    vmalloc (sizeof (struct NCR53c7x0_event) * track_events) : NULL); | 
 | 1327 |     else | 
 | 1328 | 	hostdata->events = NULL; | 
 | 1329 |  | 
 | 1330 |     if (hostdata->events) { | 
 | 1331 | 	memset ((void *) hostdata->events, 0, sizeof(struct NCR53c7x0_event) * | 
 | 1332 | 	    track_events);	 | 
 | 1333 | 	hostdata->event_size = track_events; | 
 | 1334 | 	hostdata->event_index = 0; | 
 | 1335 |     } else  | 
 | 1336 | 	hostdata->event_size = 0; | 
 | 1337 |  | 
 | 1338 |     return NCR53c7x0_init(instance); | 
 | 1339 | } | 
 | 1340 |  | 
 | 1341 |  | 
 | 1342 | /*  | 
 | 1343 |  * Function : static void NCR53c7x0_init_fixup (struct Scsi_Host *host) | 
 | 1344 |  * | 
 | 1345 |  * Purpose :  copy and fixup the SCSI SCRIPTS(tm) code for this device. | 
 | 1346 |  * | 
 | 1347 |  * Inputs : host - pointer to this host adapter's structure | 
 | 1348 |  * | 
 | 1349 |  */ | 
 | 1350 |  | 
 | 1351 | static void  | 
 | 1352 | NCR53c7x0_init_fixup (struct Scsi_Host *host) { | 
 | 1353 |     NCR53c7x0_local_declare(); | 
 | 1354 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 1355 | 	host->hostdata[0]; | 
 | 1356 |     unsigned char tmp; | 
 | 1357 |     int i, ncr_to_memory, memory_to_ncr; | 
 | 1358 |     u32 base; | 
 | 1359 |     NCR53c7x0_local_setup(host); | 
 | 1360 |  | 
 | 1361 |  | 
 | 1362 |     /* XXX - NOTE : this code MUST be made endian aware */ | 
 | 1363 |     /*  Copy code into buffer that was allocated at detection time.  */ | 
 | 1364 |     memcpy ((void *) hostdata->script, (void *) SCRIPT,  | 
 | 1365 | 	sizeof(SCRIPT)); | 
 | 1366 |     /* Fixup labels */ | 
 | 1367 |     for (i = 0; i < PATCHES; ++i)  | 
 | 1368 | 	hostdata->script[LABELPATCHES[i]] +=  | 
 | 1369 |     	    virt_to_bus(hostdata->script); | 
 | 1370 |     /* Fixup addresses of constants that used to be EXTERNAL */ | 
 | 1371 |  | 
 | 1372 |     patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_abort,  | 
 | 1373 |     	virt_to_bus(&(hostdata->NCR53c7xx_msg_abort))); | 
 | 1374 |     patch_abs_32 (hostdata->script, 0, NCR53c7xx_msg_reject,  | 
 | 1375 |     	virt_to_bus(&(hostdata->NCR53c7xx_msg_reject))); | 
 | 1376 |     patch_abs_32 (hostdata->script, 0, NCR53c7xx_zero,  | 
 | 1377 |     	virt_to_bus(&(hostdata->NCR53c7xx_zero))); | 
 | 1378 |     patch_abs_32 (hostdata->script, 0, NCR53c7xx_sink,  | 
 | 1379 |     	virt_to_bus(&(hostdata->NCR53c7xx_sink))); | 
 | 1380 |     patch_abs_32 (hostdata->script, 0, NOP_insn, | 
 | 1381 | 	virt_to_bus(&(hostdata->NOP_insn))); | 
 | 1382 |     patch_abs_32 (hostdata->script, 0, schedule, | 
 | 1383 | 	virt_to_bus((void *) hostdata->schedule)); | 
 | 1384 |  | 
 | 1385 |     /* Fixup references to external variables: */ | 
 | 1386 |     for (i = 0; i < EXTERNAL_PATCHES_LEN; ++i) | 
 | 1387 |        hostdata->script[EXTERNAL_PATCHES[i].offset] += | 
 | 1388 |          virt_to_bus(EXTERNAL_PATCHES[i].address); | 
 | 1389 |  | 
 | 1390 |     /*  | 
 | 1391 |      * Fixup absolutes set at boot-time. | 
 | 1392 |      *  | 
 | 1393 |      * All non-code absolute variables suffixed with "dsa_" and "int_" | 
 | 1394 |      * are constants, and need no fixup provided the assembler has done  | 
 | 1395 |      * it for us (I don't know what the "real" NCR assembler does in  | 
 | 1396 |      * this case, my assembler does the right magic). | 
 | 1397 |      */ | 
 | 1398 |  | 
 | 1399 |     patch_abs_rwri_data (hostdata->script, 0, dsa_save_data_pointer,  | 
 | 1400 |     	Ent_dsa_code_save_data_pointer - Ent_dsa_zero); | 
 | 1401 |     patch_abs_rwri_data (hostdata->script, 0, dsa_restore_pointers, | 
 | 1402 |     	Ent_dsa_code_restore_pointers - Ent_dsa_zero); | 
 | 1403 |     patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, | 
 | 1404 |     	Ent_dsa_code_check_reselect - Ent_dsa_zero); | 
 | 1405 |  | 
 | 1406 |     /* | 
 | 1407 |      * Just for the hell of it, preserve the settings of  | 
 | 1408 |      * Burst Length and Enable Read Line bits from the DMODE  | 
 | 1409 |      * register.  Make sure SCRIPTS start automagically. | 
 | 1410 |      */ | 
 | 1411 |  | 
 | 1412 | #if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) | 
 | 1413 |     /* We know better what we want than 16xBug does! */ | 
 | 1414 |     tmp = DMODE_10_BL_8 | DMODE_10_FC2; | 
 | 1415 | #else | 
 | 1416 |     tmp = NCR53c7x0_read8(DMODE_REG_10); | 
 | 1417 |     tmp &= (DMODE_BL_MASK | DMODE_10_FC2 | DMODE_10_FC1 | DMODE_710_PD | | 
 | 1418 | 								DMODE_710_UO); | 
 | 1419 | #endif | 
 | 1420 |  | 
 | 1421 |     if (!(hostdata->options & OPTION_MEMORY_MAPPED)) { | 
 | 1422 |     	base = (u32) host->io_port; | 
 | 1423 |     	memory_to_ncr = tmp|DMODE_800_DIOM; | 
 | 1424 |     	ncr_to_memory = tmp|DMODE_800_SIOM; | 
 | 1425 |     } else { | 
 | 1426 |     	base = virt_to_bus((void *)host->base); | 
 | 1427 | 	memory_to_ncr = ncr_to_memory = tmp; | 
 | 1428 |     } | 
 | 1429 |  | 
 | 1430 |     /* SCRATCHB_REG_10 == SCRATCHA_REG_800, as it happens */ | 
 | 1431 |     patch_abs_32 (hostdata->script, 0, addr_scratch, base + SCRATCHA_REG_800); | 
 | 1432 |     patch_abs_32 (hostdata->script, 0, addr_temp, base + TEMP_REG); | 
 | 1433 |     patch_abs_32 (hostdata->script, 0, addr_dsa, base + DSA_REG); | 
 | 1434 |  | 
 | 1435 |     /* | 
 | 1436 |      * I needed some variables in the script to be accessible to  | 
 | 1437 |      * both the NCR chip and the host processor. For these variables, | 
 | 1438 |      * I made the arbitrary decision to store them directly in the  | 
 | 1439 |      * hostdata structure rather than in the RELATIVE area of the  | 
 | 1440 |      * SCRIPTS. | 
 | 1441 |      */ | 
 | 1442 |      | 
 | 1443 |  | 
 | 1444 |     patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_memory, tmp); | 
 | 1445 |     patch_abs_rwri_data (hostdata->script, 0, dmode_memory_to_ncr, memory_to_ncr); | 
 | 1446 |     patch_abs_rwri_data (hostdata->script, 0, dmode_ncr_to_memory, ncr_to_memory); | 
 | 1447 |  | 
 | 1448 |     patch_abs_32 (hostdata->script, 0, msg_buf,  | 
 | 1449 | 	virt_to_bus((void *)&(hostdata->msg_buf))); | 
 | 1450 |     patch_abs_32 (hostdata->script, 0, reconnect_dsa_head,  | 
 | 1451 |     	virt_to_bus((void *)&(hostdata->reconnect_dsa_head))); | 
 | 1452 |     patch_abs_32 (hostdata->script, 0, addr_reconnect_dsa_head,  | 
 | 1453 | 	virt_to_bus((void *)&(hostdata->addr_reconnect_dsa_head))); | 
 | 1454 |     patch_abs_32 (hostdata->script, 0, reselected_identify,  | 
 | 1455 |     	virt_to_bus((void *)&(hostdata->reselected_identify))); | 
 | 1456 | /* reselected_tag is currently unused */ | 
 | 1457 | #if 0 | 
 | 1458 |     patch_abs_32 (hostdata->script, 0, reselected_tag,  | 
 | 1459 |     	virt_to_bus((void *)&(hostdata->reselected_tag))); | 
 | 1460 | #endif | 
 | 1461 |  | 
 | 1462 |     patch_abs_32 (hostdata->script, 0, test_dest,  | 
 | 1463 | 	virt_to_bus((void*)&hostdata->test_dest)); | 
 | 1464 |     patch_abs_32 (hostdata->script, 0, test_src,  | 
 | 1465 | 	virt_to_bus(&hostdata->test_source)); | 
 | 1466 |     patch_abs_32 (hostdata->script, 0, saved_dsa, | 
 | 1467 | 	virt_to_bus((void *)&hostdata->saved2_dsa)); | 
 | 1468 |     patch_abs_32 (hostdata->script, 0, emulfly, | 
 | 1469 | 	virt_to_bus((void *)&hostdata->emulated_intfly)); | 
 | 1470 |  | 
 | 1471 |     patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect,  | 
 | 1472 | 	(unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero)); | 
 | 1473 |  | 
 | 1474 | /* These are for event logging; the ncr_event enum contains the  | 
 | 1475 |    actual interrupt numbers. */ | 
 | 1476 | #ifdef A_int_EVENT_SELECT | 
 | 1477 |    patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT, (u32) EVENT_SELECT); | 
 | 1478 | #endif | 
 | 1479 | #ifdef A_int_EVENT_DISCONNECT | 
 | 1480 |    patch_abs_32 (hostdata->script, 0, int_EVENT_DISCONNECT, (u32) EVENT_DISCONNECT); | 
 | 1481 | #endif | 
 | 1482 | #ifdef A_int_EVENT_RESELECT | 
 | 1483 |    patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT, (u32) EVENT_RESELECT); | 
 | 1484 | #endif | 
 | 1485 | #ifdef A_int_EVENT_COMPLETE | 
 | 1486 |    patch_abs_32 (hostdata->script, 0, int_EVENT_COMPLETE, (u32) EVENT_COMPLETE); | 
 | 1487 | #endif | 
 | 1488 | #ifdef A_int_EVENT_IDLE | 
 | 1489 |    patch_abs_32 (hostdata->script, 0, int_EVENT_IDLE, (u32) EVENT_IDLE); | 
 | 1490 | #endif | 
 | 1491 | #ifdef A_int_EVENT_SELECT_FAILED | 
 | 1492 |    patch_abs_32 (hostdata->script, 0, int_EVENT_SELECT_FAILED,  | 
 | 1493 | 	(u32) EVENT_SELECT_FAILED); | 
 | 1494 | #endif | 
 | 1495 | #ifdef A_int_EVENT_BEFORE_SELECT | 
 | 1496 |    patch_abs_32 (hostdata->script, 0, int_EVENT_BEFORE_SELECT, | 
 | 1497 | 	(u32) EVENT_BEFORE_SELECT); | 
 | 1498 | #endif | 
 | 1499 | #ifdef A_int_EVENT_RESELECT_FAILED | 
 | 1500 |    patch_abs_32 (hostdata->script, 0, int_EVENT_RESELECT_FAILED,  | 
 | 1501 | 	(u32) EVENT_RESELECT_FAILED); | 
 | 1502 | #endif | 
 | 1503 |  | 
 | 1504 |     /* | 
 | 1505 |      * Make sure the NCR and Linux code agree on the location of  | 
 | 1506 |      * certain fields. | 
 | 1507 |      */ | 
 | 1508 |  | 
 | 1509 |     hostdata->E_accept_message = Ent_accept_message; | 
 | 1510 |     hostdata->E_command_complete = Ent_command_complete;		 | 
 | 1511 |     hostdata->E_cmdout_cmdout = Ent_cmdout_cmdout; | 
 | 1512 |     hostdata->E_data_transfer = Ent_data_transfer; | 
 | 1513 |     hostdata->E_debug_break = Ent_debug_break;	 | 
 | 1514 |     hostdata->E_dsa_code_template = Ent_dsa_code_template; | 
 | 1515 |     hostdata->E_dsa_code_template_end = Ent_dsa_code_template_end; | 
 | 1516 |     hostdata->E_end_data_transfer = Ent_end_data_transfer; | 
 | 1517 |     hostdata->E_initiator_abort = Ent_initiator_abort; | 
 | 1518 |     hostdata->E_msg_in = Ent_msg_in; | 
 | 1519 |     hostdata->E_other_transfer = Ent_other_transfer; | 
 | 1520 |     hostdata->E_other_in = Ent_other_in; | 
 | 1521 |     hostdata->E_other_out = Ent_other_out; | 
 | 1522 |     hostdata->E_reject_message = Ent_reject_message; | 
 | 1523 |     hostdata->E_respond_message = Ent_respond_message; | 
 | 1524 |     hostdata->E_select = Ent_select; | 
 | 1525 |     hostdata->E_select_msgout = Ent_select_msgout; | 
 | 1526 |     hostdata->E_target_abort = Ent_target_abort; | 
 | 1527 | #ifdef Ent_test_0 | 
 | 1528 |     hostdata->E_test_0 = Ent_test_0; | 
 | 1529 | #endif | 
 | 1530 |     hostdata->E_test_1 = Ent_test_1; | 
 | 1531 |     hostdata->E_test_2 = Ent_test_2; | 
 | 1532 | #ifdef Ent_test_3 | 
 | 1533 |     hostdata->E_test_3 = Ent_test_3; | 
 | 1534 | #endif | 
 | 1535 |     hostdata->E_wait_reselect = Ent_wait_reselect; | 
 | 1536 |     hostdata->E_dsa_code_begin = Ent_dsa_code_begin; | 
 | 1537 |  | 
 | 1538 |     hostdata->dsa_cmdout = A_dsa_cmdout; | 
 | 1539 |     hostdata->dsa_cmnd = A_dsa_cmnd; | 
 | 1540 |     hostdata->dsa_datain = A_dsa_datain; | 
 | 1541 |     hostdata->dsa_dataout = A_dsa_dataout; | 
 | 1542 |     hostdata->dsa_end = A_dsa_end;			 | 
 | 1543 |     hostdata->dsa_msgin = A_dsa_msgin; | 
 | 1544 |     hostdata->dsa_msgout = A_dsa_msgout; | 
 | 1545 |     hostdata->dsa_msgout_other = A_dsa_msgout_other; | 
 | 1546 |     hostdata->dsa_next = A_dsa_next; | 
 | 1547 |     hostdata->dsa_select = A_dsa_select; | 
 | 1548 |     hostdata->dsa_start = Ent_dsa_code_template - Ent_dsa_zero; | 
 | 1549 |     hostdata->dsa_status = A_dsa_status; | 
 | 1550 |     hostdata->dsa_jump_dest = Ent_dsa_code_fix_jump - Ent_dsa_zero +  | 
 | 1551 | 	8 /* destination operand */; | 
 | 1552 |  | 
 | 1553 |     /* sanity check */ | 
 | 1554 |     if (A_dsa_fields_start != Ent_dsa_code_template_end -  | 
 | 1555 |     	Ent_dsa_zero)  | 
 | 1556 |     	printk("scsi%d : NCR dsa_fields start is %d not %d\n", | 
 | 1557 |     	    host->host_no, A_dsa_fields_start, Ent_dsa_code_template_end -  | 
 | 1558 |     	    Ent_dsa_zero); | 
 | 1559 |  | 
 | 1560 |     printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no, | 
 | 1561 | 	virt_to_bus(hostdata->script), hostdata->script); | 
 | 1562 | } | 
 | 1563 |  | 
 | 1564 | /* | 
 | 1565 |  * Function : static int NCR53c7xx_run_tests (struct Scsi_Host *host) | 
 | 1566 |  * | 
 | 1567 |  * Purpose : run various verification tests on the NCR chip,  | 
 | 1568 |  *	including interrupt generation, and proper bus mastering | 
 | 1569 |  * 	operation. | 
 | 1570 |  *  | 
 | 1571 |  * Inputs : host - a properly initialized Scsi_Host structure | 
 | 1572 |  * | 
 | 1573 |  * Preconditions : the NCR chip must be in a halted state. | 
 | 1574 |  * | 
 | 1575 |  * Returns : 0 if all tests were successful, -1 on error. | 
 | 1576 |  *  | 
 | 1577 |  */ | 
 | 1578 |  | 
 | 1579 | static int  | 
 | 1580 | NCR53c7xx_run_tests (struct Scsi_Host *host) { | 
 | 1581 |     NCR53c7x0_local_declare(); | 
 | 1582 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 1583 | 	host->hostdata[0]; | 
 | 1584 |     unsigned long timeout; | 
 | 1585 |     u32 start; | 
 | 1586 |     int failed, i; | 
 | 1587 |     unsigned long flags; | 
 | 1588 |     NCR53c7x0_local_setup(host); | 
 | 1589 |  | 
 | 1590 |     /* The NCR chip _must_ be idle to run the test scripts */ | 
 | 1591 |  | 
 | 1592 |     local_irq_save(flags); | 
 | 1593 |     if (!hostdata->idle) { | 
 | 1594 | 	printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); | 
 | 1595 | 	local_irq_restore(flags); | 
 | 1596 | 	return -1; | 
 | 1597 |     } | 
 | 1598 |  | 
 | 1599 |     /*  | 
 | 1600 |      * Check for functional interrupts, this could work as an | 
 | 1601 |      * autoprobe routine. | 
 | 1602 |      */ | 
 | 1603 |  | 
 | 1604 |     if ((hostdata->options & OPTION_DEBUG_TEST1) &&  | 
 | 1605 | 	    hostdata->state != STATE_DISABLED) { | 
 | 1606 | 	hostdata->idle = 0; | 
 | 1607 | 	hostdata->test_running = 1; | 
 | 1608 | 	hostdata->test_completed = -1; | 
 | 1609 | 	hostdata->test_dest = 0; | 
 | 1610 | 	hostdata->test_source = 0xdeadbeef; | 
 | 1611 | 	start = virt_to_bus (hostdata->script) + hostdata->E_test_1; | 
 | 1612 |     	hostdata->state = STATE_RUNNING; | 
 | 1613 | 	printk ("scsi%d : test 1", host->host_no); | 
 | 1614 | 	NCR53c7x0_write32 (DSP_REG, start); | 
 | 1615 | 	if (hostdata->options & OPTION_DEBUG_TRACE) | 
 | 1616 | 	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM | | 
 | 1617 | 						DCNTL_STD); | 
 | 1618 | 	printk (" started\n"); | 
 | 1619 | 	local_irq_restore(flags); | 
 | 1620 |  | 
 | 1621 | 	/*  | 
 | 1622 | 	 * This is currently a .5 second timeout, since (in theory) no slow  | 
 | 1623 | 	 * board will take that long.  In practice, we've seen one  | 
 | 1624 | 	 * pentium which occassionally fails with this, but works with  | 
 | 1625 | 	 * 10 times as much? | 
 | 1626 | 	 */ | 
 | 1627 |  | 
 | 1628 | 	timeout = jiffies + 5 * HZ / 10; | 
 | 1629 | 	while ((hostdata->test_completed == -1) && time_before(jiffies, timeout)) | 
 | 1630 | 		barrier(); | 
 | 1631 |  | 
 | 1632 | 	failed = 1; | 
 | 1633 | 	if (hostdata->test_completed == -1) | 
 | 1634 | 	    printk ("scsi%d : driver test 1 timed out%s\n",host->host_no , | 
 | 1635 | 		(hostdata->test_dest == 0xdeadbeef) ?  | 
 | 1636 | 		    " due to lost interrupt.\n" | 
 | 1637 | 		    "         Please verify that the correct IRQ is being used for your board,\n" | 
 | 1638 | 		    : ""); | 
 | 1639 | 	else if (hostdata->test_completed != 1)  | 
 | 1640 | 	    printk ("scsi%d : test 1 bad interrupt value (%d)\n",  | 
 | 1641 | 		host->host_no, hostdata->test_completed); | 
 | 1642 | 	else  | 
 | 1643 | 	    failed = (hostdata->test_dest != 0xdeadbeef); | 
 | 1644 |  | 
 | 1645 | 	if (hostdata->test_dest != 0xdeadbeef) { | 
 | 1646 | 	    printk ("scsi%d : driver test 1 read 0x%x instead of 0xdeadbeef indicating a\n" | 
 | 1647 |                     "         probable cache invalidation problem.  Please configure caching\n" | 
 | 1648 | 		    "         as write-through or disabled\n", | 
 | 1649 | 		host->host_no, hostdata->test_dest); | 
 | 1650 | 	} | 
 | 1651 |  | 
 | 1652 | 	if (failed) { | 
 | 1653 | 	    printk ("scsi%d : DSP = 0x%p (script at 0x%p, start at 0x%x)\n", | 
 | 1654 | 		host->host_no, bus_to_virt(NCR53c7x0_read32(DSP_REG)), | 
 | 1655 | 		hostdata->script, start); | 
 | 1656 | 	    printk ("scsi%d : DSPS = 0x%x\n", host->host_no, | 
 | 1657 | 		NCR53c7x0_read32(DSPS_REG)); | 
 | 1658 | 	    local_irq_restore(flags); | 
 | 1659 | 	    return -1; | 
 | 1660 | 	} | 
 | 1661 |     	hostdata->test_running = 0; | 
 | 1662 |     } | 
 | 1663 |  | 
 | 1664 |     if ((hostdata->options & OPTION_DEBUG_TEST2) &&  | 
 | 1665 | 	hostdata->state != STATE_DISABLED) { | 
 | 1666 | 	u32 dsa[48]; | 
 | 1667 |     	unsigned char identify = IDENTIFY(0, 0); | 
 | 1668 | 	unsigned char cmd[6]; | 
 | 1669 | 	unsigned char data[36]; | 
 | 1670 |     	unsigned char status = 0xff; | 
 | 1671 |     	unsigned char msg = 0xff; | 
 | 1672 |  | 
 | 1673 |     	cmd[0] = INQUIRY; | 
 | 1674 |     	cmd[1] = cmd[2] = cmd[3] = cmd[5] = 0; | 
 | 1675 |     	cmd[4] = sizeof(data);  | 
 | 1676 |  | 
 | 1677 |     	dsa[2] = 1; | 
 | 1678 |     	dsa[3] = virt_to_bus(&identify); | 
 | 1679 |     	dsa[4] = 6; | 
 | 1680 |     	dsa[5] = virt_to_bus(&cmd); | 
 | 1681 |     	dsa[6] = sizeof(data); | 
 | 1682 |     	dsa[7] = virt_to_bus(&data); | 
 | 1683 |     	dsa[8] = 1; | 
 | 1684 |     	dsa[9] = virt_to_bus(&status); | 
 | 1685 |     	dsa[10] = 1; | 
 | 1686 |     	dsa[11] = virt_to_bus(&msg); | 
 | 1687 |  | 
 | 1688 | 	for (i = 0; i < 6; ++i) { | 
 | 1689 | #ifdef VALID_IDS | 
 | 1690 | 	    if (!hostdata->valid_ids[i]) | 
 | 1691 | 		continue; | 
 | 1692 | #endif | 
 | 1693 | 	    local_irq_disable(); | 
 | 1694 | 	    if (!hostdata->idle) { | 
 | 1695 | 		printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); | 
 | 1696 | 		local_irq_restore(flags); | 
 | 1697 | 		return -1; | 
 | 1698 | 	    } | 
 | 1699 |  | 
 | 1700 | 	    /* 710: bit mapped scsi ID, async   */ | 
 | 1701 |             dsa[0] = (1 << i) << 16; | 
 | 1702 | 	    hostdata->idle = 0; | 
 | 1703 | 	    hostdata->test_running = 2; | 
 | 1704 | 	    hostdata->test_completed = -1; | 
 | 1705 | 	    start = virt_to_bus(hostdata->script) + hostdata->E_test_2; | 
 | 1706 | 	    hostdata->state = STATE_RUNNING; | 
 | 1707 | 	    NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa)); | 
 | 1708 | 	    NCR53c7x0_write32 (DSP_REG, start); | 
 | 1709 | 	    if (hostdata->options & OPTION_DEBUG_TRACE) | 
 | 1710 | 	        NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | | 
 | 1711 | 				DCNTL_SSM | DCNTL_STD); | 
 | 1712 | 	    local_irq_restore(flags); | 
 | 1713 |  | 
 | 1714 | 	    timeout = jiffies + 5 * HZ;	/* arbitrary */ | 
 | 1715 | 	    while ((hostdata->test_completed == -1) && time_before(jiffies, timeout)) | 
 | 1716 | 	    	barrier(); | 
 | 1717 |  | 
 | 1718 | 	    NCR53c7x0_write32 (DSA_REG, 0); | 
 | 1719 |  | 
 | 1720 | 	    if (hostdata->test_completed == 2) { | 
 | 1721 | 		data[35] = 0; | 
 | 1722 | 		printk ("scsi%d : test 2 INQUIRY to target %d, lun 0 : %s\n", | 
 | 1723 | 		    host->host_no, i, data + 8); | 
 | 1724 | 		printk ("scsi%d : status ", host->host_no); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 1725 | 		scsi_print_status (status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1726 | 		printk ("\nscsi%d : message ", host->host_no); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 1727 | 		scsi_print_msg (&msg); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1728 | 		printk ("\n"); | 
 | 1729 | 	    } else if (hostdata->test_completed == 3) { | 
 | 1730 | 		printk("scsi%d : test 2 no connection with target %d\n", | 
 | 1731 | 		    host->host_no, i); | 
 | 1732 | 		if (!hostdata->idle) { | 
 | 1733 | 		    printk("scsi%d : not idle\n", host->host_no); | 
 | 1734 | 		    local_irq_restore(flags); | 
 | 1735 | 		    return -1; | 
 | 1736 | 		} | 
 | 1737 | 	    } else if (hostdata->test_completed == -1) { | 
 | 1738 | 		printk ("scsi%d : test 2 timed out\n", host->host_no); | 
 | 1739 | 		local_irq_restore(flags); | 
 | 1740 | 		return -1; | 
 | 1741 | 	    }  | 
 | 1742 | 	    hostdata->test_running = 0; | 
 | 1743 | 	} | 
 | 1744 |     } | 
 | 1745 |  | 
 | 1746 |     local_irq_restore(flags); | 
 | 1747 |     return 0; | 
 | 1748 | } | 
 | 1749 |  | 
 | 1750 | /* | 
 | 1751 |  * Function : static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) | 
 | 1752 |  * | 
 | 1753 |  * Purpose : copy the NCR53c8xx dsa structure into cmd's dsa buffer, | 
 | 1754 |  * 	performing all necessary relocation. | 
 | 1755 |  * | 
 | 1756 |  * Inputs : cmd, a NCR53c7x0_cmd structure with a dsa area large | 
 | 1757 |  *	enough to hold the NCR53c8xx dsa. | 
 | 1758 |  */ | 
 | 1759 |  | 
 | 1760 | static void  | 
 | 1761 | NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) { | 
 | 1762 |     Scsi_Cmnd *c = cmd->cmd; | 
 | 1763 |     struct Scsi_Host *host = c->device->host; | 
 | 1764 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 1765 |     	host->hostdata[0]; | 
 | 1766 |     int i; | 
 | 1767 |  | 
 | 1768 |     memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4), | 
 | 1769 |     	hostdata->E_dsa_code_template_end - hostdata->E_dsa_code_template); | 
 | 1770 |  | 
 | 1771 |     /*  | 
 | 1772 |      * Note : within the NCR 'C' code, dsa points to the _start_ | 
 | 1773 |      * of the DSA structure, and _not_ the offset of dsa_zero within | 
 | 1774 |      * that structure used to facilitate shorter signed offsets | 
 | 1775 |      * for the 8 bit ALU. | 
 | 1776 |      *  | 
 | 1777 |      * The implications of this are that  | 
 | 1778 |      *  | 
 | 1779 |      * - 32 bit A_dsa_* absolute values require an additional  | 
 | 1780 |      * 	 dsa_zero added to their value to be correct, since they are  | 
 | 1781 |      *   relative to dsa_zero which is in essentially a separate | 
 | 1782 |      *   space from the code symbols. | 
 | 1783 |      * | 
 | 1784 |      * - All other symbols require no special treatment. | 
 | 1785 |      */ | 
 | 1786 |  | 
 | 1787 |     patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1788 |     	dsa_temp_lun, c->device->lun); | 
 | 1789 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1790 | 	dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr)); | 
 | 1791 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1792 |     	dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero - | 
 | 1793 | 	Ent_dsa_code_template + A_dsa_next); | 
 | 1794 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),  | 
 | 1795 |     	dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->device->id].script)); | 
 | 1796 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),  | 
 | 1797 |     	dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->device->id].sscf_710)); | 
 | 1798 |     patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1799 |     	    dsa_temp_target, 1 << c->device->id); | 
 | 1800 |     /* XXX - new pointer stuff */ | 
 | 1801 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1802 |     	dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer)); | 
 | 1803 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1804 |     	dsa_temp_addr_saved_residual, virt_to_bus(&cmd->saved_residual)); | 
 | 1805 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1806 |     	dsa_temp_addr_residual, virt_to_bus(&cmd->residual)); | 
 | 1807 |  | 
 | 1808 |     /*  XXX - new start stuff */ | 
 | 1809 |  | 
 | 1810 |     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), | 
 | 1811 | 	dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr)); | 
 | 1812 | } | 
 | 1813 |  | 
 | 1814 | /*  | 
 | 1815 |  * Function : run_process_issue_queue (void) | 
 | 1816 |  *  | 
 | 1817 |  * Purpose : insure that the coroutine is running and will process our  | 
 | 1818 |  * 	request.  process_issue_queue_running is checked/set here (in an  | 
 | 1819 |  *	inline function) rather than in process_issue_queue itself to reduce  | 
 | 1820 |  * 	the chances of stack overflow. | 
 | 1821 |  * | 
 | 1822 |  */ | 
 | 1823 |  | 
 | 1824 | static volatile int process_issue_queue_running = 0; | 
 | 1825 |  | 
 | 1826 | static __inline__ void  | 
 | 1827 | run_process_issue_queue(void) { | 
 | 1828 |     unsigned long flags; | 
 | 1829 |     local_irq_save(flags); | 
 | 1830 |     if (!process_issue_queue_running) { | 
 | 1831 | 	process_issue_queue_running = 1; | 
 | 1832 |         process_issue_queue(flags); | 
 | 1833 | 	/*  | 
 | 1834 |          * process_issue_queue_running is cleared in process_issue_queue  | 
 | 1835 | 	 * once it can't do more work, and process_issue_queue exits with  | 
 | 1836 | 	 * interrupts disabled. | 
 | 1837 | 	 */ | 
 | 1838 |     } | 
 | 1839 |     local_irq_restore(flags); | 
 | 1840 | } | 
 | 1841 |  | 
 | 1842 | /* | 
 | 1843 |  * Function : static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int | 
 | 1844 |  *	result) | 
 | 1845 |  * | 
 | 1846 |  * Purpose : mark SCSI command as finished, OR'ing the host portion  | 
 | 1847 |  *	of the result word into the result field of the corresponding | 
 | 1848 |  *	Scsi_Cmnd structure, and removing it from the internal queues. | 
 | 1849 |  * | 
 | 1850 |  * Inputs : cmd - command, result - entire result field | 
 | 1851 |  * | 
 | 1852 |  * Preconditions : the 	NCR chip should be in a halted state when  | 
 | 1853 |  *	abnormal_finished is run, since it modifies structures which | 
 | 1854 |  *	the NCR expects to have exclusive access to. | 
 | 1855 |  */ | 
 | 1856 |  | 
 | 1857 | static void  | 
 | 1858 | abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) { | 
 | 1859 |     Scsi_Cmnd *c = cmd->cmd; | 
 | 1860 |     struct Scsi_Host *host = c->device->host; | 
 | 1861 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 1862 |     	host->hostdata[0]; | 
 | 1863 |     unsigned long flags; | 
 | 1864 |     int left, found; | 
 | 1865 |     volatile struct NCR53c7x0_cmd * linux_search; | 
 | 1866 |     volatile struct NCR53c7x0_cmd * volatile *linux_prev; | 
 | 1867 |     volatile u32 *ncr_prev, *ncrcurrent, ncr_search; | 
 | 1868 |  | 
 | 1869 | #if 0 | 
 | 1870 |     printk ("scsi%d: abnormal finished\n", host->host_no); | 
 | 1871 | #endif | 
 | 1872 |  | 
 | 1873 |     local_irq_save(flags); | 
 | 1874 |     found = 0; | 
 | 1875 |     /*  | 
 | 1876 |      * Traverse the NCR issue array until we find a match or run out  | 
 | 1877 |      * of instructions.  Instructions in the NCR issue array are  | 
 | 1878 |      * either JUMP or NOP instructions, which are 2 words in length. | 
 | 1879 |      */ | 
 | 1880 |  | 
 | 1881 |  | 
 | 1882 |     for (found = 0, left = host->can_queue, ncrcurrent = hostdata->schedule;  | 
 | 1883 | 	left > 0; --left, ncrcurrent += 2) | 
 | 1884 |     { | 
 | 1885 | 	if (issue_to_cmd (host, hostdata, (u32 *) ncrcurrent) == cmd)  | 
 | 1886 | 	{ | 
 | 1887 | 	    ncrcurrent[0] = hostdata->NOP_insn; | 
 | 1888 | 	    ncrcurrent[1] = 0xdeadbeef; | 
 | 1889 | 	    ++found; | 
 | 1890 | 	    break; | 
 | 1891 | 	} | 
 | 1892 |     } | 
 | 1893 | 	 | 
 | 1894 |     /*  | 
 | 1895 |      * Traverse the NCR reconnect list of DSA structures until we find  | 
 | 1896 |      * a pointer to this dsa or have found too many command structures.   | 
 | 1897 |      * We let prev point at the next field of the previous element or  | 
 | 1898 |      * head of the list, so we don't do anything different for removing  | 
 | 1899 |      * the head element.   | 
 | 1900 |      */ | 
 | 1901 |  | 
 | 1902 |     for (left = host->can_queue, | 
 | 1903 | 	    ncr_search = hostdata->reconnect_dsa_head,  | 
 | 1904 | 	    ncr_prev = &hostdata->reconnect_dsa_head; | 
 | 1905 | 	left >= 0 && ncr_search &&  | 
 | 1906 | 	    ((char*)bus_to_virt(ncr_search) + hostdata->dsa_start)  | 
 | 1907 | 		!= (char *) cmd->dsa; | 
 | 1908 | 	ncr_prev = (u32*) ((char*)bus_to_virt(ncr_search) +  | 
 | 1909 | 	    hostdata->dsa_next), ncr_search = *ncr_prev, --left); | 
 | 1910 |  | 
 | 1911 |     if (left < 0)  | 
 | 1912 | 	printk("scsi%d: loop detected in ncr reconncect list\n", | 
 | 1913 | 	    host->host_no); | 
 | 1914 |     else if (ncr_search) { | 
 | 1915 | 	if (found) | 
 | 1916 | 	    printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n", | 
 | 1917 | 		host->host_no, c->pid); | 
 | 1918 | 	else { | 
 | 1919 | 	    volatile u32 * next = (u32 *)  | 
 | 1920 | 	    	((char *)bus_to_virt(ncr_search) + hostdata->dsa_next); | 
 | 1921 | 	    *ncr_prev = *next; | 
 | 1922 | /* If we're at the tail end of the issue queue, update that pointer too. */ | 
 | 1923 | 	    found = 1; | 
 | 1924 | 	} | 
 | 1925 |     } | 
 | 1926 |  | 
 | 1927 |     /* | 
 | 1928 |      * Traverse the host running list until we find this command or discover | 
 | 1929 |      * we have too many elements, pointing linux_prev at the next field of the  | 
 | 1930 |      * linux_previous element or head of the list, search at this element. | 
 | 1931 |      */ | 
 | 1932 |  | 
 | 1933 |     for (left = host->can_queue, linux_search = hostdata->running_list,  | 
 | 1934 | 	    linux_prev = &hostdata->running_list; | 
 | 1935 | 	left >= 0 && linux_search && linux_search != cmd; | 
 | 1936 | 	linux_prev = &(linux_search->next),  | 
 | 1937 | 	    linux_search = linux_search->next, --left); | 
 | 1938 |      | 
 | 1939 |     if (left < 0)  | 
 | 1940 | 	printk ("scsi%d: loop detected in host running list for scsi pid %ld\n", | 
 | 1941 | 	    host->host_no, c->pid); | 
 | 1942 |     else if (linux_search) { | 
 | 1943 | 	*linux_prev = linux_search->next; | 
 | 1944 | 	--hostdata->busy[c->device->id][c->device->lun]; | 
 | 1945 |     } | 
 | 1946 |  | 
 | 1947 |     /* Return the NCR command structure to the free list */ | 
 | 1948 |     cmd->next = hostdata->free; | 
 | 1949 |     hostdata->free = cmd; | 
 | 1950 |     c->host_scribble = NULL; | 
 | 1951 |  | 
 | 1952 |     /* And return */ | 
 | 1953 |     c->result = result; | 
 | 1954 |     c->scsi_done(c); | 
 | 1955 |  | 
 | 1956 |     local_irq_restore(flags); | 
 | 1957 |     run_process_issue_queue(); | 
 | 1958 | } | 
 | 1959 |  | 
 | 1960 | /*  | 
 | 1961 |  * Function : static void intr_break (struct Scsi_Host *host, | 
 | 1962 |  * 	struct NCR53c7x0_cmd *cmd) | 
 | 1963 |  * | 
 | 1964 |  * Purpose :  Handler for breakpoint interrupts from a SCSI script | 
 | 1965 |  * | 
 | 1966 |  * Inputs : host - pointer to this host adapter's structure, | 
 | 1967 |  * 	cmd - pointer to the command (if any) dsa was pointing  | 
 | 1968 |  * 	to. | 
 | 1969 |  * | 
 | 1970 |  */ | 
 | 1971 |  | 
 | 1972 | static void  | 
 | 1973 | intr_break (struct Scsi_Host *host, struct  | 
 | 1974 |     NCR53c7x0_cmd *cmd) { | 
 | 1975 |     NCR53c7x0_local_declare(); | 
 | 1976 |     struct NCR53c7x0_break *bp; | 
 | 1977 | #if 0 | 
 | 1978 |     Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; | 
 | 1979 | #endif | 
 | 1980 |     u32 *dsp; | 
 | 1981 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 1982 | 	host->hostdata[0];		 | 
 | 1983 |     unsigned long flags; | 
 | 1984 |     NCR53c7x0_local_setup(host); | 
 | 1985 |  | 
 | 1986 |     /* | 
 | 1987 |      * Find the break point corresponding to this address, and  | 
 | 1988 |      * dump the appropriate debugging information to standard  | 
 | 1989 |      * output.   | 
 | 1990 |      */ | 
 | 1991 |     local_irq_save(flags); | 
 | 1992 |     dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG)); | 
 | 1993 |     for (bp = hostdata->breakpoints; bp && bp->address != dsp;  | 
 | 1994 |     	bp = bp->next); | 
 | 1995 |     if (!bp)  | 
 | 1996 |     	panic("scsi%d : break point interrupt from %p with no breakpoint!", | 
 | 1997 |     	    host->host_no, dsp); | 
 | 1998 |  | 
 | 1999 |     /* | 
 | 2000 |      * Configure the NCR chip for manual start mode, so that we can  | 
 | 2001 |      * point the DSP register at the instruction that follows the  | 
 | 2002 |      * INT int_debug_break instruction. | 
 | 2003 |      */ | 
 | 2004 |  | 
 | 2005 |     NCR53c7x0_write8 (hostdata->dmode,  | 
 | 2006 | 	NCR53c7x0_read8(hostdata->dmode)|DMODE_MAN); | 
 | 2007 |  | 
 | 2008 |     /* | 
 | 2009 |      * And update the DSP register, using the size of the old  | 
 | 2010 |      * instruction in bytes. | 
 | 2011 |      */ | 
 | 2012 |  | 
 | 2013 |     local_irq_restore(flags); | 
 | 2014 | } | 
 | 2015 | /* | 
 | 2016 |  * Function : static void print_synchronous (const char *prefix,  | 
 | 2017 |  *	const unsigned char *msg) | 
 | 2018 |  *  | 
 | 2019 |  * Purpose : print a pretty, user and machine parsable representation | 
 | 2020 |  *	of a SDTR message, including the "real" parameters, data | 
 | 2021 |  *	clock so we can tell transfer rate at a glance. | 
 | 2022 |  * | 
 | 2023 |  * Inputs ; prefix - text to prepend, msg - SDTR message (5 bytes) | 
 | 2024 |  */ | 
 | 2025 |  | 
 | 2026 | static void | 
 | 2027 | print_synchronous (const char *prefix, const unsigned char *msg) { | 
 | 2028 |     if (msg[4]) { | 
 | 2029 | 	int Hz = 1000000000 / (msg[3] * 4); | 
 | 2030 | 	int integer = Hz / 1000000; | 
 | 2031 | 	int fraction = (Hz - (integer * 1000000)) / 10000; | 
 | 2032 | 	printk ("%speriod %dns offset %d %d.%02dMHz %s SCSI%s\n", | 
 | 2033 | 	    prefix, (int) msg[3] * 4, (int) msg[4], integer, fraction, | 
 | 2034 | 	    (((msg[3] * 4) < 200) ? "FAST" : "synchronous"), | 
 | 2035 | 	    (((msg[3] * 4) < 200) ? "-II" : "")); | 
 | 2036 |     } else  | 
 | 2037 | 	printk ("%sasynchronous SCSI\n", prefix); | 
 | 2038 | } | 
 | 2039 |  | 
 | 2040 | /* | 
 | 2041 |  * Function : static void set_synchronous (struct Scsi_Host *host,  | 
 | 2042 |  *	 	int target, int sxfer, int scntl3, int now_connected) | 
 | 2043 |  * | 
 | 2044 |  * Purpose : reprogram transfers between the selected SCSI initiator and  | 
 | 2045 |  *	target with the given register values; in the indirect | 
 | 2046 |  *	select operand, reselection script, and chip registers. | 
 | 2047 |  * | 
 | 2048 |  * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id, | 
 | 2049 |  *	sxfer and scntl3 - NCR registers. now_connected - if non-zero,  | 
 | 2050 |  *	we should reprogram the registers now too. | 
 | 2051 |  * | 
 | 2052 |  *      NOTE:  For 53c710, scntl3 is actually used for SCF bits from | 
 | 2053 |  *	SBCL, as we don't have a SCNTL3. | 
 | 2054 |  */ | 
 | 2055 |  | 
 | 2056 | static void | 
 | 2057 | set_synchronous (struct Scsi_Host *host, int target, int sxfer, int scntl3, | 
 | 2058 |     int now_connected) { | 
 | 2059 |     NCR53c7x0_local_declare(); | 
 | 2060 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)  | 
 | 2061 | 	host->hostdata[0]; | 
 | 2062 |     u32 *script; | 
 | 2063 |     NCR53c7x0_local_setup(host); | 
 | 2064 |  | 
 | 2065 |     /* These are eight bit registers */ | 
 | 2066 |     sxfer &= 0xff; | 
 | 2067 |     scntl3 &= 0xff; | 
 | 2068 |  | 
 | 2069 |     hostdata->sync[target].sxfer_sanity = sxfer; | 
 | 2070 |     hostdata->sync[target].scntl3_sanity = scntl3; | 
 | 2071 |  | 
 | 2072 | /*  | 
 | 2073 |  * HARD CODED : synchronous script is EIGHT words long.  This  | 
 | 2074 |  * must agree with 53c7.8xx.h | 
 | 2075 |  */ | 
 | 2076 |  | 
 | 2077 |     if ((hostdata->chip != 700) && (hostdata->chip != 70066)) { | 
 | 2078 | 	hostdata->sync[target].select_indirect = (1 << target) << 16 | | 
 | 2079 | 		(sxfer << 8); | 
 | 2080 | 	hostdata->sync[target].sscf_710 = scntl3; | 
 | 2081 |  | 
 | 2082 | 	script = (u32 *) hostdata->sync[target].script; | 
 | 2083 |  | 
 | 2084 | 	/* XXX - add NCR53c7x0 code to reprogram SCF bits if we want to */ | 
 | 2085 | 	script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY | | 
 | 2086 | 		DCMD_RWRI_OP_MOVE) << 24) | | 
 | 2087 | 		(SBCL_REG << 16) | (scntl3 << 8); | 
 | 2088 | 	script[1] = 0; | 
 | 2089 | 	script += 2; | 
 | 2090 |  | 
 | 2091 | 	script[0] = ((DCMD_TYPE_RWRI | DCMD_RWRI_OPC_MODIFY | | 
 | 2092 | 	    DCMD_RWRI_OP_MOVE) << 24) | | 
 | 2093 | 		(SXFER_REG << 16) | (sxfer << 8); | 
 | 2094 | 	script[1] = 0; | 
 | 2095 | 	script += 2; | 
 | 2096 |  | 
 | 2097 | #ifdef DEBUG_SYNC_INTR | 
 | 2098 | 	if (hostdata->options & OPTION_DEBUG_DISCONNECT) { | 
 | 2099 | 	    script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_INT) << 24) | DBC_TCI_TRUE; | 
 | 2100 | 	    script[1] = DEBUG_SYNC_INTR; | 
 | 2101 | 	    script += 2; | 
 | 2102 | 	} | 
 | 2103 | #endif | 
 | 2104 |  | 
 | 2105 | 	script[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_RETURN) << 24) | DBC_TCI_TRUE; | 
 | 2106 | 	script[1] = 0; | 
 | 2107 | 	script += 2; | 
 | 2108 |     } | 
 | 2109 |  | 
 | 2110 |     if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS)  | 
 | 2111 | 	printk ("scsi%d : target %d sync parameters are sxfer=0x%x, scntl3=0x%x\n", | 
 | 2112 | 	host->host_no, target, sxfer, scntl3); | 
 | 2113 |  | 
 | 2114 |     if (now_connected) { | 
 | 2115 | 	NCR53c7x0_write8(SBCL_REG, scntl3); | 
 | 2116 | 	NCR53c7x0_write8(SXFER_REG, sxfer); | 
 | 2117 |     } | 
 | 2118 | } | 
 | 2119 |  | 
 | 2120 |  | 
 | 2121 | /* | 
 | 2122 |  * Function : static int asynchronous (struct Scsi_Host *host, int target) | 
 | 2123 |  * | 
 | 2124 |  * Purpose : reprogram between the selected SCSI Host adapter and target  | 
 | 2125 |  *      (assumed to be currently connected) for asynchronous transfers. | 
 | 2126 |  * | 
 | 2127 |  * Inputs : host - SCSI host structure, target - numeric target ID. | 
 | 2128 |  * | 
 | 2129 |  * Preconditions : the NCR chip should be in one of the halted states | 
 | 2130 |  */ | 
 | 2131 |      | 
 | 2132 | static void | 
 | 2133 | asynchronous (struct Scsi_Host *host, int target) { | 
 | 2134 |     NCR53c7x0_local_declare(); | 
 | 2135 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 2136 | 	host->hostdata[0]; | 
 | 2137 |     NCR53c7x0_local_setup(host); | 
 | 2138 |     set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3, | 
 | 2139 | 	1); | 
 | 2140 |     printk ("scsi%d : setting target %d to asynchronous SCSI\n", | 
 | 2141 | 	host->host_no, target); | 
 | 2142 | } | 
 | 2143 |  | 
 | 2144 | /*  | 
 | 2145 |  * XXX - do we want to go out of our way (ie, add extra code to selection | 
 | 2146 |  * 	in the NCR53c710/NCR53c720 script) to reprogram the synchronous | 
 | 2147 |  * 	conversion bits, or can we be content in just setting the  | 
 | 2148 |  * 	sxfer bits?  I chose to do so [richard@sleepie.demon.co.uk] | 
 | 2149 |  */ | 
 | 2150 |  | 
 | 2151 | /* Table for NCR53c8xx synchronous values */ | 
 | 2152 |  | 
 | 2153 | /* This table is also correct for 710, allowing that scf=4 is equivalent | 
 | 2154 |  * of SSCF=0 (ie use DCNTL, divide by 3) for a 50.01-66.00MHz clock. | 
 | 2155 |  * For any other clock values, we cannot use entries with SCF values of | 
 | 2156 |  * 4.  I guess that for a 66MHz clock, the slowest it will set is 2MHz, | 
 | 2157 |  * and for a 50MHz clock, the slowest will be 2.27Mhz.  Should check | 
 | 2158 |  * that a device doesn't try and negotiate sync below these limits! | 
 | 2159 |  */ | 
 | 2160 |   | 
 | 2161 | static const struct { | 
 | 2162 |     int div;		/* Total clock divisor * 10 */ | 
 | 2163 |     unsigned char scf;	/* */ | 
 | 2164 |     unsigned char tp;	/* 4 + tp = xferp divisor */ | 
 | 2165 | } syncs[] = { | 
 | 2166 | /*	div	scf	tp	div	scf	tp	div	scf	tp */ | 
 | 2167 |     {	40,	1,	0}, {	50,	1,	1}, {	60,	1,	2},  | 
 | 2168 |     {	70,	1,	3}, {	75,	2,	1}, {	80,	1,	4}, | 
 | 2169 |     {	90,	1,	5}, {	100,	1,	6}, {	105,	2,	3}, | 
 | 2170 |     {	110,	1,	7}, {	120,	2,	4}, {	135,	2,	5}, | 
 | 2171 |     {	140,	3,	3}, {	150,	2,	6}, {	160,	3,	4}, | 
 | 2172 |     {	165,	2,	7}, {	180,	3,	5}, {	200,	3,	6}, | 
 | 2173 |     {	210,	4,	3}, {	220,	3,	7}, {	240,	4,	4}, | 
 | 2174 |     {	270,	4,	5}, {	300,	4,	6}, {	330,	4,	7} | 
 | 2175 | }; | 
 | 2176 |  | 
 | 2177 | /* | 
 | 2178 |  * Function : static void synchronous (struct Scsi_Host *host, int target,  | 
 | 2179 |  *	char *msg) | 
 | 2180 |  * | 
 | 2181 |  * Purpose : reprogram transfers between the selected SCSI initiator and  | 
 | 2182 |  *	target for synchronous SCSI transfers such that the synchronous  | 
 | 2183 |  *	offset is less than that requested and period at least as long  | 
 | 2184 |  *	as that requested.  Also modify *msg such that it contains  | 
 | 2185 |  *	an appropriate response.  | 
 | 2186 |  * | 
 | 2187 |  * Inputs : host - NCR53c7,8xx SCSI host, target - number SCSI target id, | 
 | 2188 |  *	msg - synchronous transfer request. | 
 | 2189 |  */ | 
 | 2190 |  | 
 | 2191 |  | 
 | 2192 | static void  | 
 | 2193 | synchronous (struct Scsi_Host *host, int target, char *msg) { | 
 | 2194 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 2195 | 	host->hostdata[0]; | 
 | 2196 |     int desire, divisor, i, limit; | 
 | 2197 |     unsigned char scntl3, sxfer; | 
 | 2198 | /* The diagnostic message fits on one line, even with max. width integers */ | 
 | 2199 |     char buf[80];	 | 
 | 2200 |     | 
 | 2201 | /* Desired transfer clock in Hz */ | 
 | 2202 |     desire = 1000000000L / (msg[3] * 4); | 
 | 2203 | /* Scale the available SCSI clock by 10 so we get tenths */ | 
 | 2204 |     divisor = (hostdata->scsi_clock * 10) / desire; | 
 | 2205 |  | 
 | 2206 | /* NCR chips can handle at most an offset of 8 */ | 
 | 2207 |     if (msg[4] > 8) | 
 | 2208 | 	msg[4] = 8; | 
 | 2209 |  | 
 | 2210 |     if (hostdata->options & OPTION_DEBUG_SDTR) | 
 | 2211 |     	printk("scsi%d : optimal synchronous divisor of %d.%01d\n",  | 
 | 2212 | 	    host->host_no, divisor / 10, divisor % 10); | 
 | 2213 |  | 
 | 2214 |     limit = (sizeof(syncs) / sizeof(syncs[0]) -1); | 
 | 2215 |     for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i); | 
 | 2216 |  | 
 | 2217 |     if (hostdata->options & OPTION_DEBUG_SDTR) | 
 | 2218 |     	printk("scsi%d : selected synchronous divisor of %d.%01d\n",  | 
 | 2219 | 	    host->host_no, syncs[i].div / 10, syncs[i].div % 10); | 
 | 2220 |  | 
 | 2221 |     msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4); | 
 | 2222 |  | 
 | 2223 |     if (hostdata->options & OPTION_DEBUG_SDTR) | 
 | 2224 |     	printk("scsi%d : selected synchronous period of %dns\n", host->host_no, | 
 | 2225 | 	    msg[3] * 4); | 
 | 2226 |  | 
 | 2227 |     scntl3 = syncs[i].scf; | 
 | 2228 |     sxfer = (msg[4] << SXFER_MO_SHIFT) | (syncs[i].tp << 4); | 
 | 2229 |     if (hostdata->options & OPTION_DEBUG_SDTR) | 
 | 2230 |     	printk ("scsi%d : sxfer=0x%x scntl3=0x%x\n",  | 
 | 2231 | 	    host->host_no, (int) sxfer, (int) scntl3); | 
 | 2232 |     set_synchronous (host, target, sxfer, scntl3, 1); | 
 | 2233 |     sprintf (buf, "scsi%d : setting target %d to ", host->host_no, target); | 
 | 2234 |     print_synchronous (buf, msg); | 
 | 2235 | } | 
 | 2236 |  | 
 | 2237 | /*  | 
 | 2238 |  * Function : static int NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, | 
 | 2239 |  * 	struct NCR53c7x0_cmd *cmd) | 
 | 2240 |  * | 
 | 2241 |  * Purpose :  Handler for INT generated instructions for the  | 
 | 2242 |  * 	NCR53c810/820 SCSI SCRIPT | 
 | 2243 |  * | 
 | 2244 |  * Inputs : host - pointer to this host adapter's structure, | 
 | 2245 |  * 	cmd - pointer to the command (if any) dsa was pointing  | 
 | 2246 |  * 	to. | 
 | 2247 |  * | 
 | 2248 |  */ | 
 | 2249 |  | 
 | 2250 | static int  | 
 | 2251 | NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct  | 
 | 2252 |     NCR53c7x0_cmd *cmd) { | 
 | 2253 |     NCR53c7x0_local_declare(); | 
 | 2254 |     int print; | 
 | 2255 |     Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; | 
 | 2256 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 2257 | 	host->hostdata[0];		 | 
 | 2258 |     u32 dsps,*dsp;	/* Argument of the INT instruction */ | 
 | 2259 |  | 
 | 2260 |     NCR53c7x0_local_setup(host); | 
 | 2261 |     dsps = NCR53c7x0_read32(DSPS_REG); | 
 | 2262 |     dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG)); | 
 | 2263 |  | 
 | 2264 |     /* RGH 150597:  Frig.  Commands which fail with Check Condition are | 
 | 2265 |      * Flagged as successful - hack dsps to indicate check condition */ | 
 | 2266 | #if 0 | 
 | 2267 |     /* RGH 200597:  Need to disable for BVME6000, as it gets Check Conditions | 
 | 2268 |      * and then dies.  Seems to handle Check Condition at startup, but | 
 | 2269 |      * not mid kernel build. */ | 
 | 2270 |     if (dsps == A_int_norm_emulateintfly && cmd && cmd->result == 2) | 
 | 2271 |         dsps = A_int_err_check_condition; | 
 | 2272 | #endif | 
 | 2273 |  | 
 | 2274 |     if (hostdata->options & OPTION_DEBUG_INTR)  | 
 | 2275 | 	printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps); | 
 | 2276 |  | 
 | 2277 |     switch (dsps) { | 
 | 2278 |     case A_int_msg_1: | 
 | 2279 | 	print = 1; | 
 | 2280 | 	switch (hostdata->msg_buf[0]) { | 
 | 2281 | 	/*  | 
 | 2282 | 	 * Unless we've initiated synchronous negotiation, I don't | 
 | 2283 | 	 * think that this should happen. | 
 | 2284 | 	 */ | 
 | 2285 | 	case MESSAGE_REJECT: | 
 | 2286 | 	    hostdata->dsp = hostdata->script + hostdata->E_accept_message / | 
 | 2287 | 		sizeof(u32); | 
 | 2288 | 	    hostdata->dsp_changed = 1; | 
 | 2289 | 	    if (cmd && (cmd->flags & CMD_FLAG_SDTR)) { | 
 | 2290 | 		printk ("scsi%d : target %d rejected SDTR\n", host->host_no,  | 
 | 2291 | 		    c->device->id); | 
 | 2292 | 		cmd->flags &= ~CMD_FLAG_SDTR; | 
 | 2293 | 		asynchronous (host, c->device->id); | 
 | 2294 | 		print = 0; | 
 | 2295 | 	    }  | 
 | 2296 | 	    break; | 
 | 2297 | 	case INITIATE_RECOVERY: | 
 | 2298 | 	    printk ("scsi%d : extended contingent allegiance not supported yet, rejecting\n", | 
 | 2299 | 		host->host_no); | 
 | 2300 | 	    /* Fall through to default */ | 
 | 2301 | 	    hostdata->dsp = hostdata->script + hostdata->E_reject_message / | 
 | 2302 | 		sizeof(u32); | 
 | 2303 | 	    hostdata->dsp_changed = 1; | 
 | 2304 | 	    break; | 
 | 2305 | 	default: | 
 | 2306 | 	    printk ("scsi%d : unsupported message, rejecting\n", | 
 | 2307 | 		host->host_no); | 
 | 2308 | 	    hostdata->dsp = hostdata->script + hostdata->E_reject_message / | 
 | 2309 | 		sizeof(u32); | 
 | 2310 | 	    hostdata->dsp_changed = 1; | 
 | 2311 | 	} | 
 | 2312 | 	if (print) { | 
 | 2313 | 	    printk ("scsi%d : received message", host->host_no); | 
 | 2314 | 	    if (c)  | 
 | 2315 | 	    	printk (" from target %d lun %d ", c->device->id, c->device->lun); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 2316 | 	    scsi_print_msg ((unsigned char *) hostdata->msg_buf); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2317 | 	    printk("\n"); | 
 | 2318 | 	} | 
 | 2319 | 	 | 
 | 2320 | 	return SPECIFIC_INT_NOTHING; | 
 | 2321 |  | 
 | 2322 |  | 
 | 2323 |     case A_int_msg_sdtr: | 
 | 2324 | /* | 
 | 2325 |  * At this point, hostdata->msg_buf contains | 
 | 2326 |  * 0 EXTENDED MESSAGE | 
 | 2327 |  * 1 length  | 
 | 2328 |  * 2 SDTR | 
 | 2329 |  * 3 period * 4ns | 
 | 2330 |  * 4 offset | 
 | 2331 |  */ | 
 | 2332 |  | 
 | 2333 | 	if (cmd) { | 
 | 2334 | 	    char buf[80]; | 
 | 2335 | 	    sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->device->id, | 
 | 2336 | 		(cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting"); | 
 | 2337 | 	    print_synchronous (buf, (unsigned char *) hostdata->msg_buf); | 
 | 2338 |  | 
 | 2339 | 	/*  | 
 | 2340 | 	 * Initiator initiated, won't happen unless synchronous  | 
 | 2341 | 	 * 	transfers are enabled.  If we get a SDTR message in | 
 | 2342 | 	 * 	response to our SDTR, we should program our parameters | 
 | 2343 | 	 * 	such that  | 
 | 2344 | 	 *		offset <= requested offset | 
 | 2345 | 	 *		period >= requested period		 	 | 
 | 2346 |    	 */ | 
 | 2347 | 	    if (cmd->flags & CMD_FLAG_SDTR) { | 
 | 2348 | 		cmd->flags &= ~CMD_FLAG_SDTR;  | 
 | 2349 | 		if (hostdata->msg_buf[4])  | 
 | 2350 | 		    synchronous (host, c->device->id, (unsigned char *)  | 
 | 2351 | 		    	hostdata->msg_buf); | 
 | 2352 | 		else  | 
 | 2353 | 		    asynchronous (host, c->device->id); | 
 | 2354 | 		hostdata->dsp = hostdata->script + hostdata->E_accept_message / | 
 | 2355 | 		    sizeof(u32); | 
 | 2356 | 		hostdata->dsp_changed = 1; | 
 | 2357 | 		return SPECIFIC_INT_NOTHING; | 
 | 2358 | 	    } else { | 
 | 2359 | 		if (hostdata->options & OPTION_SYNCHRONOUS)  { | 
 | 2360 | 		    cmd->flags |= CMD_FLAG_DID_SDTR; | 
 | 2361 | 		    synchronous (host, c->device->id, (unsigned char *)  | 
 | 2362 | 			hostdata->msg_buf); | 
 | 2363 | 		} else { | 
 | 2364 | 		    hostdata->msg_buf[4] = 0;		/* 0 offset = async */ | 
 | 2365 | 		    asynchronous (host, c->device->id); | 
 | 2366 | 		} | 
 | 2367 | 		patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5); | 
 | 2368 | 		patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32)  | 
 | 2369 | 		    virt_to_bus ((void *)&hostdata->msg_buf)); | 
 | 2370 | 		hostdata->dsp = hostdata->script +  | 
 | 2371 | 		    hostdata->E_respond_message / sizeof(u32); | 
 | 2372 | 		hostdata->dsp_changed = 1; | 
 | 2373 | 	    } | 
 | 2374 | 	    return SPECIFIC_INT_NOTHING; | 
 | 2375 | 	} | 
 | 2376 | 	/* Fall through to abort if we couldn't find a cmd, and  | 
 | 2377 | 	   therefore a dsa structure to twiddle */ | 
 | 2378 |     case A_int_msg_wdtr: | 
 | 2379 | 	hostdata->dsp = hostdata->script + hostdata->E_reject_message / | 
 | 2380 | 	    sizeof(u32); | 
 | 2381 | 	hostdata->dsp_changed = 1; | 
 | 2382 | 	return SPECIFIC_INT_NOTHING; | 
 | 2383 |     case A_int_err_unexpected_phase: | 
 | 2384 | 	if (hostdata->options & OPTION_DEBUG_INTR)  | 
 | 2385 | 	    printk ("scsi%d : unexpected phase\n", host->host_no); | 
 | 2386 | 	return SPECIFIC_INT_ABORT; | 
 | 2387 |     case A_int_err_selected: | 
 | 2388 | 	if ((hostdata->chip / 100) == 8) | 
 | 2389 | 	    printk ("scsi%d : selected by target %d\n", host->host_no, | 
 | 2390 | 	        (int) NCR53c7x0_read8(SDID_REG_800) &7); | 
 | 2391 | 	else | 
 | 2392 |             printk ("scsi%d : selected by target LCRC=0x%02x\n", host->host_no, | 
 | 2393 |                 (int) NCR53c7x0_read8(LCRC_REG_10)); | 
 | 2394 | 	hostdata->dsp = hostdata->script + hostdata->E_target_abort /  | 
 | 2395 |     	    sizeof(u32); | 
 | 2396 | 	hostdata->dsp_changed = 1; | 
 | 2397 | 	return SPECIFIC_INT_NOTHING; | 
 | 2398 |     case A_int_err_unexpected_reselect: | 
 | 2399 | 	if ((hostdata->chip / 100) == 8) | 
 | 2400 | 	    printk ("scsi%d : unexpected reselect by target %d lun %d\n",  | 
 | 2401 | 	        host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & 7, | 
 | 2402 | 	        hostdata->reselected_identify & 7); | 
 | 2403 | 	else | 
 | 2404 |             printk ("scsi%d : unexpected reselect LCRC=0x%02x\n", host->host_no, | 
 | 2405 |                 (int) NCR53c7x0_read8(LCRC_REG_10)); | 
 | 2406 | 	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / | 
 | 2407 |     	    sizeof(u32); | 
 | 2408 | 	hostdata->dsp_changed = 1; | 
 | 2409 | 	return SPECIFIC_INT_NOTHING; | 
 | 2410 | /* | 
 | 2411 |  * Since contingent allegiance conditions are cleared by the next  | 
 | 2412 |  * command issued to a target, we must issue a REQUEST SENSE  | 
 | 2413 |  * command after receiving a CHECK CONDITION status, before | 
 | 2414 |  * another command is issued. | 
 | 2415 |  *  | 
 | 2416 |  * Since this NCR53c7x0_cmd will be freed after use, we don't  | 
 | 2417 |  * care if we step on the various fields, so modify a few things. | 
 | 2418 |  */ | 
 | 2419 |     case A_int_err_check_condition:  | 
 | 2420 | #if 0 | 
 | 2421 | 	if (hostdata->options & OPTION_DEBUG_INTR)  | 
 | 2422 | #endif | 
 | 2423 | 	    printk ("scsi%d : CHECK CONDITION\n", host->host_no); | 
 | 2424 | 	if (!c) { | 
 | 2425 | 	    printk("scsi%d : CHECK CONDITION with no SCSI command\n", | 
 | 2426 | 		host->host_no); | 
 | 2427 | 	    return SPECIFIC_INT_PANIC; | 
 | 2428 | 	} | 
 | 2429 |  | 
 | 2430 | 	/*  | 
 | 2431 | 	 * FIXME : this uses the normal one-byte selection message. | 
 | 2432 | 	 * 	We may want to renegotiate for synchronous & WIDE transfers | 
 | 2433 | 	 * 	since these could be the crux of our problem. | 
 | 2434 | 	 * | 
 | 2435 | 	 hostdata->NOP_insn* FIXME : once SCSI-II tagged queuing is implemented, we'll | 
 | 2436 | 	 * 	have to set this up so that the rest of the DSA | 
 | 2437 | 	 *	agrees with this being an untagged queue'd command. | 
 | 2438 | 	 */ | 
 | 2439 |  | 
 | 2440 |     	patch_dsa_32 (cmd->dsa, dsa_msgout, 0, 1); | 
 | 2441 |  | 
 | 2442 |     	/*  | 
 | 2443 |     	 * Modify the table indirect for COMMAND OUT phase, since  | 
 | 2444 |     	 * Request Sense is a six byte command. | 
 | 2445 |     	 */ | 
 | 2446 |  | 
 | 2447 |     	patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6); | 
 | 2448 |  | 
 | 2449 |         /* | 
 | 2450 |          * The CDB is now mirrored in our local non-cached | 
 | 2451 |          * structure, but keep the old structure up to date as well, | 
 | 2452 |          * just in case anyone looks at it. | 
 | 2453 |          */ | 
 | 2454 |  | 
 | 2455 | 	/* | 
 | 2456 | 	 * XXX Need to worry about data buffer alignment/cache state | 
 | 2457 | 	 * XXX here, but currently never get A_int_err_check_condition, | 
 | 2458 | 	 * XXX so ignore problem for now. | 
 | 2459 |          */ | 
 | 2460 | 	cmd->cmnd[0] = c->cmnd[0] = REQUEST_SENSE; | 
 | 2461 | 	cmd->cmnd[0] = c->cmnd[1] &= 0xe0;	/* Zero all but LUN */ | 
 | 2462 | 	cmd->cmnd[0] = c->cmnd[2] = 0; | 
 | 2463 | 	cmd->cmnd[0] = c->cmnd[3] = 0; | 
 | 2464 | 	cmd->cmnd[0] = c->cmnd[4] = sizeof(c->sense_buffer); | 
 | 2465 | 	cmd->cmnd[0] = c->cmnd[5] = 0;  | 
 | 2466 |  | 
 | 2467 | 	/* | 
 | 2468 | 	 * Disable dataout phase, and program datain to transfer to the  | 
 | 2469 | 	 * sense buffer, and add a jump to other_transfer after the  | 
 | 2470 |     	 * command so overflow/underrun conditions are detected. | 
 | 2471 | 	 */ | 
 | 2472 |  | 
 | 2473 |     	patch_dsa_32 (cmd->dsa, dsa_dataout, 0,  | 
 | 2474 | 	    virt_to_bus(hostdata->script) + hostdata->E_other_transfer); | 
 | 2475 |     	patch_dsa_32 (cmd->dsa, dsa_datain, 0,  | 
 | 2476 | 	    virt_to_bus(cmd->data_transfer_start)); | 
 | 2477 |     	cmd->data_transfer_start[0] = (((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I |  | 
 | 2478 |     	    DCMD_BMI_IO)) << 24) | sizeof(c->sense_buffer); | 
 | 2479 |     	cmd->data_transfer_start[1] = (u32) virt_to_bus(c->sense_buffer); | 
 | 2480 |  | 
 | 2481 | 	cmd->data_transfer_start[2] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP)  | 
 | 2482 |     	    << 24) | DBC_TCI_TRUE; | 
 | 2483 | 	cmd->data_transfer_start[3] = (u32) virt_to_bus(hostdata->script) +  | 
 | 2484 | 	    hostdata->E_other_transfer; | 
 | 2485 |  | 
 | 2486 |     	/* | 
 | 2487 |     	 * Currently, this command is flagged as completed, ie  | 
 | 2488 |     	 * it has valid status and message data.  Reflag it as | 
 | 2489 |     	 * incomplete.  Q - need to do something so that original | 
 | 2490 | 	 * status, etc are used. | 
 | 2491 |     	 */ | 
 | 2492 |  | 
 | 2493 | 	cmd->result = cmd->cmd->result = 0xffff;		 | 
 | 2494 |  | 
 | 2495 | 	/*  | 
 | 2496 | 	 * Restart command as a REQUEST SENSE. | 
 | 2497 | 	 */ | 
 | 2498 | 	hostdata->dsp = (u32 *) hostdata->script + hostdata->E_select / | 
 | 2499 | 	    sizeof(u32); | 
 | 2500 | 	hostdata->dsp_changed = 1; | 
 | 2501 | 	return SPECIFIC_INT_NOTHING; | 
 | 2502 |     case A_int_debug_break: | 
 | 2503 | 	return SPECIFIC_INT_BREAK; | 
 | 2504 |     case A_int_norm_aborted: | 
 | 2505 | 	hostdata->dsp = (u32 *) hostdata->schedule; | 
 | 2506 | 	hostdata->dsp_changed = 1; | 
 | 2507 | 	if (cmd) | 
 | 2508 | 	    abnormal_finished (cmd, DID_ERROR << 16); | 
 | 2509 | 	return SPECIFIC_INT_NOTHING; | 
 | 2510 |     case A_int_norm_emulateintfly: | 
 | 2511 | 	NCR53c7x0_intfly(host); | 
 | 2512 | 	return SPECIFIC_INT_NOTHING; | 
 | 2513 |     case A_int_test_1: | 
 | 2514 |     case A_int_test_2: | 
 | 2515 | 	hostdata->idle = 1; | 
 | 2516 | 	hostdata->test_completed = (dsps - A_int_test_1) / 0x00010000 + 1; | 
 | 2517 | 	if (hostdata->options & OPTION_DEBUG_INTR) | 
 | 2518 | 	    printk("scsi%d : test%d complete\n", host->host_no, | 
 | 2519 | 		hostdata->test_completed); | 
 | 2520 | 	return SPECIFIC_INT_NOTHING; | 
 | 2521 | #ifdef A_int_debug_reselected_ok | 
 | 2522 |     case A_int_debug_reselected_ok: | 
 | 2523 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| | 
 | 2524 |     	    	OPTION_DEBUG_DISCONNECT)) { | 
 | 2525 | 	    /*  | 
 | 2526 | 	     * Note - this dsa is not based on location relative to  | 
 | 2527 | 	     * the command structure, but to location relative to the  | 
 | 2528 | 	     * DSA register  | 
 | 2529 | 	     */	 | 
 | 2530 | 	    u32 *dsa; | 
 | 2531 | 	    dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG)); | 
 | 2532 |  | 
 | 2533 | 	    printk("scsi%d : reselected_ok (DSA = 0x%x (virt 0x%p)\n",  | 
 | 2534 | 		host->host_no, NCR53c7x0_read32(DSA_REG), dsa); | 
 | 2535 | 	    printk("scsi%d : resume address is 0x%x (virt 0x%p)\n", | 
 | 2536 | 		    host->host_no, cmd->saved_data_pointer, | 
 | 2537 | 		    bus_to_virt(cmd->saved_data_pointer)); | 
 | 2538 | 	    print_insn (host, hostdata->script + Ent_reselected_ok /  | 
 | 2539 |     	    	    sizeof(u32), "", 1); | 
 | 2540 | 	    if ((hostdata->chip / 100) == 8) | 
 | 2541 |     	        printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n", | 
 | 2542 | 		    host->host_no, NCR53c7x0_read8(SXFER_REG), | 
 | 2543 | 		    NCR53c7x0_read8(SCNTL3_REG_800)); | 
 | 2544 | 	    else | 
 | 2545 |     	        printk ("scsi%d : sxfer=0x%x, cannot read SBCL\n", | 
 | 2546 | 		    host->host_no, NCR53c7x0_read8(SXFER_REG)); | 
 | 2547 | 	    if (c) { | 
 | 2548 | 		print_insn (host, (u32 *)  | 
 | 2549 | 		    hostdata->sync[c->device->id].script, "", 1); | 
 | 2550 | 		print_insn (host, (u32 *)  | 
 | 2551 | 		    hostdata->sync[c->device->id].script + 2, "", 1); | 
 | 2552 | 	    } | 
 | 2553 | 	} | 
 | 2554 |     	return SPECIFIC_INT_RESTART; | 
 | 2555 | #endif | 
 | 2556 | #ifdef A_int_debug_reselect_check | 
 | 2557 |     case A_int_debug_reselect_check: | 
 | 2558 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { | 
 | 2559 | 	    u32 *dsa; | 
 | 2560 | #if 0 | 
 | 2561 | 	    u32 *code; | 
 | 2562 | #endif | 
 | 2563 | 	    /*  | 
 | 2564 | 	     * Note - this dsa is not based on location relative to  | 
 | 2565 | 	     * the command structure, but to location relative to the  | 
 | 2566 | 	     * DSA register  | 
 | 2567 | 	     */	 | 
 | 2568 | 	    dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG)); | 
 | 2569 | 	    printk("scsi%d : reselected_check_next (DSA = 0x%lx (virt 0x%p))\n", | 
 | 2570 | 		host->host_no, virt_to_bus(dsa), dsa); | 
 | 2571 | 	    if (dsa) { | 
 | 2572 | 		printk("scsi%d : resume address is 0x%x (virt 0x%p)\n", | 
 | 2573 | 		    host->host_no, cmd->saved_data_pointer, | 
 | 2574 | 		    bus_to_virt (cmd->saved_data_pointer)); | 
 | 2575 | #if 0 | 
 | 2576 | 		printk("scsi%d : template code :\n", host->host_no); | 
 | 2577 | 		for (code = dsa + (Ent_dsa_code_check_reselect - Ent_dsa_zero)  | 
 | 2578 | 		    / sizeof(u32); code < (dsa + Ent_dsa_zero / sizeof(u32));  | 
 | 2579 | 		    code += print_insn (host, code, "", 1)); | 
 | 2580 | #endif | 
 | 2581 | 	    } | 
 | 2582 | 	    print_insn (host, hostdata->script + Ent_reselected_ok /  | 
 | 2583 |     	    	    sizeof(u32), "", 1); | 
 | 2584 | 	} | 
 | 2585 |     	return SPECIFIC_INT_RESTART; | 
 | 2586 | #endif | 
 | 2587 | #ifdef A_int_debug_dsa_schedule | 
 | 2588 |     case A_int_debug_dsa_schedule: | 
 | 2589 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { | 
 | 2590 | 	    u32 *dsa; | 
 | 2591 | 	    /*  | 
 | 2592 | 	     * Note - this dsa is not based on location relative to  | 
 | 2593 | 	     * the command structure, but to location relative to the  | 
 | 2594 | 	     * DSA register  | 
 | 2595 | 	     */	 | 
 | 2596 | 	    dsa = (u32 *) bus_to_virt (NCR53c7x0_read32(DSA_REG)); | 
 | 2597 | 	    printk("scsi%d : dsa_schedule (old DSA = 0x%lx (virt 0x%p))\n",  | 
 | 2598 | 		host->host_no, virt_to_bus(dsa), dsa); | 
 | 2599 | 	    if (dsa)  | 
 | 2600 | 		printk("scsi%d : resume address is 0x%x (virt 0x%p)\n" | 
 | 2601 | 		       "         (temp was 0x%x (virt 0x%p))\n", | 
 | 2602 | 		    host->host_no, cmd->saved_data_pointer, | 
 | 2603 | 		    bus_to_virt (cmd->saved_data_pointer), | 
 | 2604 | 		    NCR53c7x0_read32 (TEMP_REG), | 
 | 2605 | 		    bus_to_virt (NCR53c7x0_read32(TEMP_REG))); | 
 | 2606 | 	} | 
 | 2607 |     	return SPECIFIC_INT_RESTART; | 
 | 2608 | #endif | 
 | 2609 | #ifdef A_int_debug_scheduled | 
 | 2610 |     case A_int_debug_scheduled: | 
 | 2611 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { | 
 | 2612 | 	    printk("scsi%d : new I/O 0x%x (virt 0x%p) scheduled\n",  | 
 | 2613 | 		host->host_no, NCR53c7x0_read32(DSA_REG), | 
 | 2614 | 	    	bus_to_virt(NCR53c7x0_read32(DSA_REG))); | 
 | 2615 | 	} | 
 | 2616 | 	return SPECIFIC_INT_RESTART; | 
 | 2617 | #endif | 
 | 2618 | #ifdef A_int_debug_idle | 
 | 2619 |     case A_int_debug_idle: | 
 | 2620 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { | 
 | 2621 | 	    printk("scsi%d : idle\n", host->host_no); | 
 | 2622 | 	} | 
 | 2623 | 	return SPECIFIC_INT_RESTART; | 
 | 2624 | #endif | 
 | 2625 | #ifdef A_int_debug_cmd | 
 | 2626 |     case A_int_debug_cmd: | 
 | 2627 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { | 
 | 2628 | 	    printk("scsi%d : command sent\n"); | 
 | 2629 | 	} | 
 | 2630 |     	return SPECIFIC_INT_RESTART; | 
 | 2631 | #endif | 
 | 2632 | #ifdef A_int_debug_dsa_loaded | 
 | 2633 |     case A_int_debug_dsa_loaded: | 
 | 2634 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { | 
 | 2635 | 	    printk("scsi%d : DSA loaded with 0x%x (virt 0x%p)\n", host->host_no, | 
 | 2636 | 		NCR53c7x0_read32(DSA_REG),  | 
 | 2637 | 		bus_to_virt(NCR53c7x0_read32(DSA_REG))); | 
 | 2638 | 	} | 
 | 2639 | 	return SPECIFIC_INT_RESTART;  | 
 | 2640 | #endif | 
 | 2641 | #ifdef A_int_debug_reselected | 
 | 2642 |     case A_int_debug_reselected: | 
 | 2643 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| | 
 | 2644 | 	    OPTION_DEBUG_DISCONNECT)) { | 
 | 2645 | 	    if ((hostdata->chip / 100) == 8) | 
 | 2646 | 		printk("scsi%d : reselected by target %d lun %d\n", | 
 | 2647 | 		    host->host_no, (int) NCR53c7x0_read8(SDID_REG_800) & ~0x80,  | 
 | 2648 | 		    (int) hostdata->reselected_identify & 7); | 
 | 2649 | 	    else | 
 | 2650 | 		printk("scsi%d : reselected by LCRC=0x%02x lun %d\n", | 
 | 2651 |                     host->host_no, (int) NCR53c7x0_read8(LCRC_REG_10), | 
 | 2652 |                     (int) hostdata->reselected_identify & 7); | 
 | 2653 | 	    print_queues(host); | 
 | 2654 | 	} | 
 | 2655 |     	return SPECIFIC_INT_RESTART; | 
 | 2656 | #endif | 
 | 2657 | #ifdef A_int_debug_disconnect_msg | 
 | 2658 |     case A_int_debug_disconnect_msg: | 
 | 2659 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { | 
 | 2660 | 	    if (c) | 
 | 2661 | 		printk("scsi%d : target %d lun %d disconnecting\n",  | 
 | 2662 | 		    host->host_no, c->device->id, c->device->lun); | 
 | 2663 | 	    else | 
 | 2664 | 		printk("scsi%d : unknown target disconnecting\n", | 
 | 2665 | 		    host->host_no); | 
 | 2666 | 	} | 
 | 2667 | 	return SPECIFIC_INT_RESTART; | 
 | 2668 | #endif | 
 | 2669 | #ifdef A_int_debug_disconnected | 
 | 2670 |     case A_int_debug_disconnected: | 
 | 2671 | 	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| | 
 | 2672 | 		OPTION_DEBUG_DISCONNECT)) { | 
 | 2673 | 	    printk ("scsi%d : disconnected, new queues are\n",  | 
 | 2674 | 		host->host_no); | 
 | 2675 | 	    print_queues(host); | 
 | 2676 | #if 0 | 
 | 2677 | 	    /* Not valid on ncr53c710! */ | 
 | 2678 |     	    printk ("scsi%d : sxfer=0x%x, scntl3=0x%x\n", | 
 | 2679 | 		host->host_no, NCR53c7x0_read8(SXFER_REG), | 
 | 2680 | 		NCR53c7x0_read8(SCNTL3_REG_800)); | 
 | 2681 | #endif | 
 | 2682 | 	    if (c) { | 
 | 2683 | 		print_insn (host, (u32 *)  | 
 | 2684 | 		    hostdata->sync[c->device->id].script, "", 1); | 
 | 2685 | 		print_insn (host, (u32 *)  | 
 | 2686 | 		    hostdata->sync[c->device->id].script + 2, "", 1); | 
 | 2687 | 	    } | 
 | 2688 | 	} | 
 | 2689 | 	return SPECIFIC_INT_RESTART; | 
 | 2690 | #endif | 
 | 2691 | #ifdef A_int_debug_panic | 
 | 2692 |     case A_int_debug_panic: | 
 | 2693 | 	printk("scsi%d : int_debug_panic received\n", host->host_no); | 
 | 2694 | 	print_lots (host); | 
 | 2695 | 	return SPECIFIC_INT_PANIC; | 
 | 2696 | #endif | 
 | 2697 | #ifdef A_int_debug_saved | 
 | 2698 |     case A_int_debug_saved: | 
 | 2699 |     	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| | 
 | 2700 |     	    OPTION_DEBUG_DISCONNECT)) { | 
 | 2701 |     	    printk ("scsi%d : saved data pointer 0x%x (virt 0x%p)\n", | 
 | 2702 |     	    	host->host_no, cmd->saved_data_pointer, | 
 | 2703 | 		bus_to_virt (cmd->saved_data_pointer)); | 
 | 2704 |     	    print_progress (c); | 
 | 2705 |     	} | 
 | 2706 |     	return SPECIFIC_INT_RESTART; | 
 | 2707 | #endif | 
 | 2708 | #ifdef A_int_debug_restored | 
 | 2709 |     case A_int_debug_restored: | 
 | 2710 |     	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| | 
 | 2711 |     	    OPTION_DEBUG_DISCONNECT)) { | 
 | 2712 |     	    if (cmd) { | 
 | 2713 | 		int size; | 
 | 2714 |     	    	printk ("scsi%d : restored data pointer 0x%x (virt 0x%p)\n", | 
 | 2715 |     	    	    host->host_no, cmd->saved_data_pointer, bus_to_virt ( | 
 | 2716 | 		    cmd->saved_data_pointer)); | 
 | 2717 | 		size = print_insn (host, (u32 *)  | 
 | 2718 | 		    bus_to_virt(cmd->saved_data_pointer), "", 1); | 
 | 2719 | 		size = print_insn (host, (u32 *)  | 
 | 2720 | 		    bus_to_virt(cmd->saved_data_pointer) + size, "", 1); | 
 | 2721 |     	    	print_progress (c); | 
 | 2722 | 	    } | 
 | 2723 | #if 0 | 
 | 2724 | 	    printk ("scsi%d : datapath residual %d\n", | 
 | 2725 | 		host->host_no, datapath_residual (host)) ; | 
 | 2726 | #endif | 
 | 2727 |     	} | 
 | 2728 |     	return SPECIFIC_INT_RESTART; | 
 | 2729 | #endif | 
 | 2730 | #ifdef A_int_debug_sync | 
 | 2731 |     case A_int_debug_sync: | 
 | 2732 |     	if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| | 
 | 2733 |     	    OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) { | 
 | 2734 | 	    unsigned char sxfer = NCR53c7x0_read8 (SXFER_REG), scntl3; | 
 | 2735 | 	    if ((hostdata->chip / 100) == 8) { | 
 | 2736 | 		scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800); | 
 | 2737 | 		if (c) { | 
 | 2738 | 		  if (sxfer != hostdata->sync[c->device->id].sxfer_sanity || | 
 | 2739 | 		    scntl3 != hostdata->sync[c->device->id].scntl3_sanity) { | 
 | 2740 | 		   	printk ("scsi%d :  sync sanity check failed sxfer=0x%x, scntl3=0x%x", | 
 | 2741 | 			    host->host_no, sxfer, scntl3); | 
 | 2742 | 			NCR53c7x0_write8 (SXFER_REG, sxfer); | 
 | 2743 | 			NCR53c7x0_write8 (SCNTL3_REG_800, scntl3); | 
 | 2744 | 		    } | 
 | 2745 | 		} else  | 
 | 2746 |     	    	  printk ("scsi%d : unknown command sxfer=0x%x, scntl3=0x%x\n", | 
 | 2747 | 		    host->host_no, (int) sxfer, (int) scntl3); | 
 | 2748 | 	    } else { | 
 | 2749 | 		if (c) { | 
 | 2750 | 		  if (sxfer != hostdata->sync[c->device->id].sxfer_sanity) { | 
 | 2751 | 		   	printk ("scsi%d :  sync sanity check failed sxfer=0x%x", | 
 | 2752 | 			    host->host_no, sxfer); | 
 | 2753 | 			NCR53c7x0_write8 (SXFER_REG, sxfer); | 
 | 2754 | 			NCR53c7x0_write8 (SBCL_REG, | 
 | 2755 | 				hostdata->sync[c->device->id].sscf_710); | 
 | 2756 | 		    } | 
 | 2757 | 		} else  | 
 | 2758 |     	    	  printk ("scsi%d : unknown command sxfer=0x%x\n", | 
 | 2759 | 		    host->host_no, (int) sxfer); | 
 | 2760 | 	    } | 
 | 2761 | 	} | 
 | 2762 |     	return SPECIFIC_INT_RESTART; | 
 | 2763 | #endif | 
 | 2764 | #ifdef A_int_debug_datain | 
 | 2765 | 	case A_int_debug_datain: | 
 | 2766 | 	    if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR| | 
 | 2767 | 		OPTION_DEBUG_DISCONNECT|OPTION_DEBUG_SDTR)) { | 
 | 2768 | 		int size; | 
 | 2769 | 		if ((hostdata->chip / 100) == 8) | 
 | 2770 | 		  printk ("scsi%d : In do_datain (%s) sxfer=0x%x, scntl3=0x%x\n" | 
 | 2771 | 			"         datapath residual=%d\n", | 
 | 2772 | 		    host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)), | 
 | 2773 | 		    (int) NCR53c7x0_read8(SXFER_REG),  | 
 | 2774 | 		    (int) NCR53c7x0_read8(SCNTL3_REG_800), | 
 | 2775 | 		    datapath_residual (host)) ; | 
 | 2776 | 		else | 
 | 2777 | 		  printk ("scsi%d : In do_datain (%s) sxfer=0x%x\n" | 
 | 2778 | 			"         datapath residual=%d\n", | 
 | 2779 | 		    host->host_no, sbcl_to_phase (NCR53c7x0_read8 (SBCL_REG)), | 
 | 2780 | 		    (int) NCR53c7x0_read8(SXFER_REG),  | 
 | 2781 | 		    datapath_residual (host)) ; | 
 | 2782 | 		print_insn (host, dsp, "", 1); | 
 | 2783 | 		size = print_insn (host, (u32 *) bus_to_virt(dsp[1]), "", 1); | 
 | 2784 | 		print_insn (host, (u32 *) bus_to_virt(dsp[1]) + size, "", 1); | 
 | 2785 | 	   }  | 
 | 2786 | 	return SPECIFIC_INT_RESTART; | 
 | 2787 | #endif | 
 | 2788 | #ifdef A_int_debug_check_dsa | 
 | 2789 | 	case A_int_debug_check_dsa: | 
 | 2790 | 	    if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) { | 
 | 2791 | 		int sdid; | 
 | 2792 | 		int tmp; | 
 | 2793 | 		char *where; | 
 | 2794 | 		if (hostdata->chip / 100 == 8) | 
 | 2795 | 		    sdid = NCR53c7x0_read8 (SDID_REG_800) & 15; | 
 | 2796 | 		else { | 
 | 2797 | 		    tmp = NCR53c7x0_read8 (SDID_REG_700); | 
 | 2798 | 		    if (!tmp) | 
 | 2799 | 			panic ("SDID_REG_700 = 0"); | 
 | 2800 | 		    tmp >>= 1; | 
 | 2801 | 		    sdid = 0; | 
 | 2802 | 		    while (tmp) { | 
 | 2803 | 			tmp >>= 1; | 
 | 2804 | 			sdid++; | 
 | 2805 | 		    } | 
 | 2806 | 		} | 
 | 2807 | 		where = dsp - NCR53c7x0_insn_size(NCR53c7x0_read8  | 
 | 2808 | 			(DCMD_REG)) == hostdata->script +  | 
 | 2809 | 		    	Ent_select_check_dsa / sizeof(u32) ? | 
 | 2810 | 		    "selection" : "reselection"; | 
 | 2811 | 		if (c && sdid != c->device->id) { | 
 | 2812 | 		    printk ("scsi%d : SDID target %d != DSA target %d at %s\n", | 
 | 2813 | 			host->host_no, sdid, c->device->id, where); | 
 | 2814 | 		    print_lots(host); | 
 | 2815 | 		    dump_events (host, 20); | 
 | 2816 | 		    return SPECIFIC_INT_PANIC; | 
 | 2817 | 		} | 
 | 2818 | 	    } | 
 | 2819 | 	    return SPECIFIC_INT_RESTART; | 
 | 2820 | #endif | 
 | 2821 |     default: | 
 | 2822 | 	if ((dsps & 0xff000000) == 0x03000000) { | 
 | 2823 | 	     printk ("scsi%d : misc debug interrupt 0x%x\n", | 
 | 2824 | 		host->host_no, dsps); | 
 | 2825 | 	    return SPECIFIC_INT_RESTART; | 
 | 2826 | 	} else if ((dsps & 0xff000000) == 0x05000000) { | 
 | 2827 | 	    if (hostdata->events) { | 
 | 2828 | 		struct NCR53c7x0_event *event; | 
 | 2829 | 		++hostdata->event_index; | 
 | 2830 | 		if (hostdata->event_index >= hostdata->event_size) | 
 | 2831 | 		    hostdata->event_index = 0; | 
 | 2832 | 		event = (struct NCR53c7x0_event *) hostdata->events +  | 
 | 2833 | 		    hostdata->event_index; | 
 | 2834 | 		event->event = (enum ncr_event) dsps; | 
 | 2835 | 		event->dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); | 
 | 2836 | 		if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON) { | 
 | 2837 | 		    if (hostdata->chip / 100 == 8) | 
 | 2838 | 			event->target = NCR53c7x0_read8(SSID_REG_800); | 
 | 2839 | 		    else { | 
 | 2840 | 			unsigned char tmp, sdid; | 
 | 2841 | 		        tmp = NCR53c7x0_read8 (SDID_REG_700); | 
 | 2842 | 		        if (!tmp) | 
 | 2843 | 			    panic ("SDID_REG_700 = 0"); | 
 | 2844 | 		        tmp >>= 1; | 
 | 2845 | 		        sdid = 0; | 
 | 2846 | 		        while (tmp) { | 
 | 2847 | 			    tmp >>= 1; | 
 | 2848 | 			    sdid++; | 
 | 2849 | 		        } | 
 | 2850 | 			event->target = sdid; | 
 | 2851 | 		    } | 
 | 2852 | 		} | 
 | 2853 | 		else  | 
 | 2854 | 			event->target = 255; | 
 | 2855 |  | 
 | 2856 | 		if (event->event == EVENT_RESELECT) | 
 | 2857 | 		    event->lun = hostdata->reselected_identify & 0xf; | 
 | 2858 | 		else if (c) | 
 | 2859 | 		    event->lun = c->device->lun; | 
 | 2860 | 		else | 
 | 2861 | 		    event->lun = 255; | 
 | 2862 | 		do_gettimeofday(&(event->time)); | 
 | 2863 | 		if (c) { | 
 | 2864 | 		    event->pid = c->pid; | 
 | 2865 | 		    memcpy ((void *) event->cmnd, (void *) c->cmnd,  | 
 | 2866 | 			sizeof (event->cmnd)); | 
 | 2867 | 		} else { | 
 | 2868 | 		    event->pid = -1; | 
 | 2869 | 		} | 
 | 2870 | 	    } | 
 | 2871 | 	    return SPECIFIC_INT_RESTART; | 
 | 2872 | 	} | 
 | 2873 |  | 
 | 2874 | 	printk ("scsi%d : unknown user interrupt 0x%x\n",  | 
 | 2875 | 	    host->host_no, (unsigned) dsps); | 
 | 2876 | 	return SPECIFIC_INT_PANIC; | 
 | 2877 |     } | 
 | 2878 | } | 
 | 2879 |  | 
 | 2880 | /*  | 
 | 2881 |  * XXX - the stock NCR assembler won't output the scriptu.h file, | 
 | 2882 |  * which undefine's all #define'd CPP symbols from the script.h | 
 | 2883 |  * file, which will create problems if you use multiple scripts | 
 | 2884 |  * with the same  symbol names. | 
 | 2885 |  * | 
 | 2886 |  * If you insist on using NCR's assembler, you could generate | 
 | 2887 |  * scriptu.h from script.h using something like  | 
 | 2888 |  * | 
 | 2889 |  * grep #define script.h | \ | 
 | 2890 |  * sed 's/#define[ 	][ 	]*\([_a-zA-Z][_a-zA-Z0-9]*\).*$/#undefine \1/' \ | 
 | 2891 |  * > scriptu.h | 
 | 2892 |  */ | 
 | 2893 |  | 
 | 2894 | #include "53c7xx_u.h" | 
 | 2895 |  | 
 | 2896 | /* XXX - add alternate script handling code here */ | 
 | 2897 |  | 
 | 2898 |  | 
 | 2899 | /*  | 
 | 2900 |  * Function : static void NCR537xx_soft_reset (struct Scsi_Host *host) | 
 | 2901 |  * | 
 | 2902 |  * Purpose :  perform a soft reset of the NCR53c7xx chip | 
 | 2903 |  * | 
 | 2904 |  * Inputs : host - pointer to this host adapter's structure | 
 | 2905 |  * | 
 | 2906 |  * Preconditions : NCR53c7x0_init must have been called for this  | 
 | 2907 |  *      host. | 
 | 2908 |  *  | 
 | 2909 |  */ | 
 | 2910 |  | 
 | 2911 | static void  | 
 | 2912 | NCR53c7x0_soft_reset (struct Scsi_Host *host) { | 
 | 2913 |     NCR53c7x0_local_declare(); | 
 | 2914 |     unsigned long flags; | 
 | 2915 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 2916 | 	host->hostdata[0]; | 
 | 2917 |     NCR53c7x0_local_setup(host); | 
 | 2918 |  | 
 | 2919 |     local_irq_save(flags); | 
 | 2920 |  | 
 | 2921 |     /* Disable scsi chip and s/w level 7 ints */ | 
 | 2922 |  | 
 | 2923 | #ifdef CONFIG_MVME16x | 
 | 2924 |     if (MACH_IS_MVME16x) | 
 | 2925 |     { | 
 | 2926 |         volatile unsigned long v; | 
 | 2927 |  | 
 | 2928 |         v = *(volatile unsigned long *)0xfff4006c; | 
 | 2929 |         v &= ~0x8000; | 
 | 2930 |         *(volatile unsigned long *)0xfff4006c = v; | 
 | 2931 |         v = *(volatile unsigned long *)0xfff4202c; | 
 | 2932 |         v &= ~0x10; | 
 | 2933 |         *(volatile unsigned long *)0xfff4202c = v; | 
 | 2934 |     } | 
 | 2935 | #endif | 
 | 2936 |     /* Anything specific for your hardware? */ | 
 | 2937 |  | 
 | 2938 |     /* | 
 | 2939 |      * Do a soft reset of the chip so that everything is  | 
 | 2940 |      * reinitialized to the power-on state. | 
 | 2941 |      * | 
 | 2942 |      * Basically follow the procedure outlined in the NCR53c700 | 
 | 2943 |      * data manual under Chapter Six, How to Use, Steps Necessary to | 
 | 2944 |      * Start SCRIPTS, with the exception of actually starting the  | 
 | 2945 |      * script and setting up the synchronous transfer gunk. | 
 | 2946 |      */ | 
 | 2947 |  | 
 | 2948 |     /* Should we reset the scsi bus here??????????????????? */ | 
 | 2949 |  | 
 | 2950 |     NCR53c7x0_write8(ISTAT_REG_700, ISTAT_10_SRST); | 
 | 2951 |     NCR53c7x0_write8(ISTAT_REG_700, 0); | 
 | 2952 |  | 
 | 2953 |     /* | 
 | 2954 |      * saved_dcntl is set up in NCR53c7x0_init() before it is overwritten | 
 | 2955 |      * here.  We should have some better way of working out the CF bit | 
 | 2956 |      * setting.. | 
 | 2957 |      */ | 
 | 2958 |  | 
 | 2959 |     hostdata->saved_dcntl = DCNTL_10_EA|DCNTL_10_COM; | 
 | 2960 |     if (hostdata->scsi_clock > 50000000) | 
 | 2961 | 	hostdata->saved_dcntl |= DCNTL_700_CF_3; | 
 | 2962 |     else | 
 | 2963 |     if (hostdata->scsi_clock > 37500000) | 
 | 2964 |         hostdata->saved_dcntl |= DCNTL_700_CF_2; | 
 | 2965 | #if 0 | 
 | 2966 |     else | 
 | 2967 | 	/* Any clocks less than 37.5MHz? */ | 
 | 2968 | #endif | 
 | 2969 |  | 
 | 2970 |     if (hostdata->options & OPTION_DEBUG_TRACE) | 
 | 2971 |     	NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM); | 
 | 2972 |     else | 
 | 2973 |     	NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl); | 
 | 2974 |     /* Following disables snooping - snooping is not required, as non- | 
 | 2975 |      * cached pages are used for shared data, and appropriate use is | 
 | 2976 |      * made of cache_push/cache_clear.  Indeed, for 68060 | 
 | 2977 |      * enabling snooping causes disk corruption of ext2fs free block | 
 | 2978 |      * bitmaps and the like.  If you have a 68060 with snooping hardwared | 
 | 2979 |      * on, then you need to enable CONFIG_060_WRITETHROUGH. | 
 | 2980 |      */ | 
 | 2981 |     NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD); | 
 | 2982 |     /* Actually burst of eight, according to my 53c710 databook */ | 
 | 2983 |     NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2); | 
 | 2984 |     NCR53c7x0_write8(SCID_REG, 1 << host->this_id); | 
 | 2985 |     NCR53c7x0_write8(SBCL_REG, 0); | 
 | 2986 |     NCR53c7x0_write8(SCNTL1_REG, SCNTL1_ESR_700); | 
 | 2987 |     NCR53c7x0_write8(SCNTL0_REG, ((hostdata->options & OPTION_PARITY) ?  | 
 | 2988 |             SCNTL0_EPC : 0) | SCNTL0_EPG_700 | SCNTL0_ARB1 | SCNTL0_ARB2); | 
 | 2989 |  | 
 | 2990 |     /* | 
 | 2991 |      * Enable all interrupts, except parity which we only want when | 
 | 2992 |      * the user requests it. | 
 | 2993 |      */ | 
 | 2994 |  | 
 | 2995 |     NCR53c7x0_write8(DIEN_REG, DIEN_700_BF | | 
 | 2996 | 		DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC); | 
 | 2997 |  | 
 | 2998 |     NCR53c7x0_write8(SIEN_REG_700, ((hostdata->options & OPTION_PARITY) ? | 
 | 2999 | 	    SIEN_PAR : 0) | SIEN_700_STO | SIEN_RST | SIEN_UDC | | 
 | 3000 | 		SIEN_SGE | SIEN_MA); | 
 | 3001 |  | 
 | 3002 | #ifdef CONFIG_MVME16x | 
 | 3003 |     if (MACH_IS_MVME16x) | 
 | 3004 |     { | 
 | 3005 |         volatile unsigned long v; | 
 | 3006 |  | 
 | 3007 |         /* Enable scsi chip and s/w level 7 ints */ | 
 | 3008 |         v = *(volatile unsigned long *)0xfff40080; | 
 | 3009 |         v = (v & ~(0xf << 28)) | (4 << 28); | 
 | 3010 |         *(volatile unsigned long *)0xfff40080 = v; | 
 | 3011 |         v = *(volatile unsigned long *)0xfff4006c; | 
 | 3012 |         v |= 0x8000; | 
 | 3013 |         *(volatile unsigned long *)0xfff4006c = v; | 
 | 3014 |         v = *(volatile unsigned long *)0xfff4202c; | 
 | 3015 |         v = (v & ~0xff) | 0x10 | 4; | 
 | 3016 |         *(volatile unsigned long *)0xfff4202c = v; | 
 | 3017 |     } | 
 | 3018 | #endif | 
 | 3019 |     /* Anything needed for your hardware? */ | 
 | 3020 |     local_irq_restore(flags); | 
 | 3021 | } | 
 | 3022 |  | 
 | 3023 |  | 
 | 3024 | /* | 
 | 3025 |  * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd) | 
 | 3026 |  *  | 
 | 3027 |  * Purpose : Return the first free NCR53c7x0_cmd structure (which are  | 
 | 3028 |  * 	reused in a LIFO manner to minimize cache thrashing). | 
 | 3029 |  * | 
 | 3030 |  * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd | 
 | 3031 |  *	structures for this device, do so.  Attempt to complete all scheduled | 
 | 3032 |  *	allocations using get_zeroed_page(), putting NCR53c7x0_cmd structures on | 
 | 3033 |  *	the free list.  Teach programmers not to drink and hack. | 
 | 3034 |  * | 
 | 3035 |  * Inputs : cmd - SCSI command | 
 | 3036 |  * | 
 | 3037 |  * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd; | 
 | 3038 |  *	NULL on failure. | 
 | 3039 |  */ | 
 | 3040 |  | 
 | 3041 | static void | 
 | 3042 | my_free_page (void *addr, int dummy) | 
 | 3043 | { | 
 | 3044 |     /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which | 
 | 3045 |      * XXX may be invalid (CONFIG_060_WRITETHROUGH) | 
 | 3046 |      */ | 
 | 3047 |     kernel_set_cachemode((void *)addr, 4096, IOMAP_FULL_CACHING); | 
 | 3048 |     free_page ((u32)addr); | 
 | 3049 | } | 
 | 3050 |  | 
 | 3051 | static struct NCR53c7x0_cmd * | 
 | 3052 | allocate_cmd (Scsi_Cmnd *cmd) { | 
 | 3053 |     struct Scsi_Host *host = cmd->device->host; | 
 | 3054 |     struct NCR53c7x0_hostdata *hostdata =  | 
 | 3055 | 	(struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 3056 |     u32 real;			/* Real address */ | 
 | 3057 |     int size;			/* Size of *tmp */ | 
 | 3058 |     struct NCR53c7x0_cmd *tmp; | 
 | 3059 |     unsigned long flags; | 
 | 3060 |  | 
 | 3061 |     if (hostdata->options & OPTION_DEBUG_ALLOCATION) | 
 | 3062 | 	printk ("scsi%d : num_cmds = %d, can_queue = %d\n" | 
 | 3063 | 		"         target = %d, lun = %d, %s\n", | 
 | 3064 | 	    host->host_no, hostdata->num_cmds, host->can_queue, | 
 | 3065 | 	    cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] & | 
 | 3066 | 		(1 << cmd->device->lun)) ? "already allocated" : "not allocated"); | 
 | 3067 |  | 
 | 3068 | /* | 
 | 3069 |  * If we have not yet reserved commands for this I_T_L nexus, and | 
 | 3070 |  * the device exists (as indicated by permanent Scsi_Cmnd structures | 
 | 3071 |  * being allocated under 1.3.x, or being outside of scan_scsis in | 
 | 3072 |  * 1.2.x), do so now. | 
 | 3073 |  */ | 
 | 3074 |     if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) && | 
 | 3075 | 				cmd->device && cmd->device->has_cmdblocks) { | 
 | 3076 |       if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue) | 
 | 3077 |           hostdata->extra_allocate += host->cmd_per_lun; | 
 | 3078 |       hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun); | 
 | 3079 |     } | 
 | 3080 |  | 
 | 3081 |     for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate,  | 
 | 3082 |     	++hostdata->num_cmds) { | 
 | 3083 |     /* historically, kmalloc has returned unaligned addresses; pad so we | 
 | 3084 |        have enough room to ROUNDUP */ | 
 | 3085 | 	size = hostdata->max_cmd_size + sizeof (void *); | 
 | 3086 | #ifdef FORCE_DSA_ALIGNMENT | 
 | 3087 | 	/* | 
 | 3088 | 	 * 53c710 rev.0 doesn't have an add-with-carry instruction. | 
 | 3089 | 	 * Ensure we allocate enough memory to force alignment. | 
 | 3090 | 	 */ | 
 | 3091 | 	size += 256; | 
 | 3092 | #endif | 
 | 3093 | /* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */ | 
 | 3094 |  | 
 | 3095 |         if (size > 4096) { | 
 | 3096 |             printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n"); | 
 | 3097 | 	    return NULL; | 
 | 3098 | 	} | 
 | 3099 |         real = get_zeroed_page(GFP_ATOMIC); | 
 | 3100 |         if (real == 0) | 
 | 3101 |         	return NULL; | 
 | 3102 |         memset((void *)real, 0, 4096); | 
 | 3103 |         cache_push(virt_to_phys((void *)real), 4096); | 
 | 3104 |         cache_clear(virt_to_phys((void *)real), 4096); | 
 | 3105 |         kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER); | 
 | 3106 | 	tmp = ROUNDUP(real, void *); | 
 | 3107 | #ifdef FORCE_DSA_ALIGNMENT | 
 | 3108 | 	{ | 
 | 3109 | 	    if (((u32)tmp & 0xff) > CmdPageStart) | 
 | 3110 | 		tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255); | 
 | 3111 | 	    tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart); | 
 | 3112 | #if 0 | 
 | 3113 | 	    printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n", | 
 | 3114 | 			size, real, (u32)tmp); | 
 | 3115 | #endif | 
 | 3116 | 	} | 
 | 3117 | #endif | 
 | 3118 | 	tmp->real = (void *)real; | 
 | 3119 | 	tmp->size = size;			 | 
 | 3120 | 	tmp->free = ((void (*)(void *, int)) my_free_page); | 
 | 3121 | 	local_irq_save(flags); | 
 | 3122 | 	tmp->next = hostdata->free; | 
 | 3123 | 	hostdata->free = tmp; | 
 | 3124 | 	local_irq_restore(flags); | 
 | 3125 |     } | 
 | 3126 |     local_irq_save(flags); | 
 | 3127 |     tmp = (struct NCR53c7x0_cmd *) hostdata->free; | 
 | 3128 |     if (tmp) { | 
 | 3129 | 	hostdata->free = tmp->next; | 
 | 3130 |     } | 
 | 3131 |     local_irq_restore(flags); | 
 | 3132 |     if (!tmp) | 
 | 3133 | 	printk ("scsi%d : can't allocate command for target %d lun %d\n", | 
 | 3134 | 	    host->host_no, cmd->device->id, cmd->device->lun); | 
 | 3135 |     return tmp; | 
 | 3136 | } | 
 | 3137 |  | 
 | 3138 | /* | 
 | 3139 |  * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd)  | 
 | 3140 |  * | 
 | 3141 |  * | 
 | 3142 |  * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the  | 
 | 3143 |  * 	Scsi_Cmnd structure passed in cmd, including dsa and Linux field  | 
 | 3144 |  * 	initialization, and dsa code relocation. | 
 | 3145 |  * | 
 | 3146 |  * Inputs : cmd - SCSI command | 
 | 3147 |  * | 
 | 3148 |  * Returns : NCR53c7x0_cmd structure corresponding to cmd, | 
 | 3149 |  *	NULL on failure. | 
 | 3150 |  */ | 
 | 3151 | static struct NCR53c7x0_cmd * | 
 | 3152 | create_cmd (Scsi_Cmnd *cmd) { | 
 | 3153 |     NCR53c7x0_local_declare(); | 
 | 3154 |     struct Scsi_Host *host = cmd->device->host; | 
 | 3155 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 3156 |         host->hostdata[0];	 | 
 | 3157 |     struct NCR53c7x0_cmd *tmp; 	/* NCR53c7x0_cmd structure for this command */ | 
 | 3158 |     int datain,  		/* Number of instructions per phase */ | 
 | 3159 | 	dataout; | 
 | 3160 |     int data_transfer_instructions, /* Count of dynamic instructions */ | 
 | 3161 |     	i;			/* Counter */ | 
 | 3162 |     u32 *cmd_datain,		/* Address of datain/dataout code */ | 
 | 3163 | 	*cmd_dataout;		/* Incremented as we assemble */ | 
 | 3164 | #ifdef notyet | 
 | 3165 |     unsigned char *msgptr;	/* Current byte in select message */ | 
 | 3166 |     int msglen;			/* Length of whole select message */ | 
 | 3167 | #endif | 
 | 3168 |     unsigned long flags; | 
 | 3169 |     u32 exp_select_indirect;	/* Used in sanity check */ | 
 | 3170 |     NCR53c7x0_local_setup(cmd->device->host); | 
 | 3171 |  | 
 | 3172 |     if (!(tmp = allocate_cmd (cmd))) | 
 | 3173 | 	return NULL; | 
 | 3174 |  | 
 | 3175 |     /* | 
 | 3176 |      * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd. | 
 | 3177 |      * We do this because NCR53c7x0_cmd may have a special cache mode | 
 | 3178 |      * selected to cope with lack of bus snooping, etc. | 
 | 3179 |      */ | 
 | 3180 |  | 
 | 3181 |     memcpy(tmp->cmnd, cmd->cmnd, 12); | 
 | 3182 |     tmp->result = cmd->result; | 
 | 3183 |  | 
 | 3184 |     /* | 
 | 3185 |      * Decide whether we need to generate commands for DATA IN, | 
 | 3186 |      * DATA OUT, neither, or both based on the SCSI command  | 
 | 3187 |      */ | 
 | 3188 |  | 
 | 3189 |     switch (cmd->cmnd[0]) { | 
 | 3190 |     /* These commands do DATA IN */ | 
 | 3191 |     case INQUIRY: | 
 | 3192 |     case MODE_SENSE: | 
 | 3193 |     case READ_6: | 
 | 3194 |     case READ_10: | 
 | 3195 |     case READ_CAPACITY: | 
 | 3196 |     case REQUEST_SENSE: | 
 | 3197 |     case READ_BLOCK_LIMITS: | 
 | 3198 |     case READ_TOC: | 
 | 3199 | 	datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; | 
 | 3200 |     	dataout = 0; | 
 | 3201 | 	break; | 
 | 3202 |     /* These commands do DATA OUT */ | 
 | 3203 |     case MODE_SELECT:  | 
 | 3204 |     case WRITE_6: | 
 | 3205 |     case WRITE_10: | 
 | 3206 | #if 0 | 
 | 3207 | 	printk("scsi%d : command is ", host->host_no); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 3208 | 	__scsi_print_command(cmd->cmnd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3209 | #endif | 
 | 3210 | #if 0 | 
 | 3211 | 	printk ("scsi%d : %d scatter/gather segments\n", host->host_no, | 
 | 3212 | 	    cmd->use_sg); | 
 | 3213 | #endif | 
 | 3214 |     	datain = 0; | 
 | 3215 | 	dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; | 
 | 3216 | #if 0 | 
 | 3217 | 	hostdata->options |= OPTION_DEBUG_INTR; | 
 | 3218 | #endif | 
 | 3219 | 	break; | 
 | 3220 |     /*  | 
 | 3221 |      * These commands do no data transfer, we should force an | 
 | 3222 |      * interrupt if a data phase is attempted on them. | 
 | 3223 |      */ | 
 | 3224 |     case TEST_UNIT_READY: | 
 | 3225 |     case ALLOW_MEDIUM_REMOVAL: | 
 | 3226 |     case START_STOP: | 
 | 3227 |     	datain = dataout = 0; | 
 | 3228 | 	break; | 
 | 3229 |     /* | 
 | 3230 |      * We don't know about these commands, so generate code to handle | 
 | 3231 |      * both DATA IN and DATA OUT phases.  More efficient to identify them | 
 | 3232 |      * and add them to the above cases. | 
 | 3233 |      */ | 
 | 3234 |     default: | 
 | 3235 | 	printk("scsi%d : datain+dataout for command ", host->host_no); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 3236 | 	__scsi_print_command(cmd->cmnd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3237 | 	datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3; | 
 | 3238 |     } | 
 | 3239 |  | 
 | 3240 |     /* | 
 | 3241 |      * New code : so that active pointers work correctly regardless | 
 | 3242 |      * 	of where the saved data pointer is at, we want to immediately | 
 | 3243 |      * 	enter the dynamic code after selection, and on a non-data | 
 | 3244 |      * 	phase perform a CALL to the non-data phase handler, with | 
 | 3245 |      * 	returns back to this address. | 
 | 3246 |      * | 
 | 3247 |      * 	If a phase mismatch is encountered in the middle of a  | 
 | 3248 |      * 	Block MOVE instruction, we want to _leave_ that instruction | 
 | 3249 |      *	unchanged as the current case is, modify a temporary buffer, | 
 | 3250 |      *	and point the active pointer (TEMP) at that. | 
 | 3251 |      * | 
 | 3252 |      * 	Furthermore, we want to implement a saved data pointer,  | 
 | 3253 |      * 	set by the SAVE_DATA_POINTERs message. | 
 | 3254 |      * | 
 | 3255 |      * 	So, the data transfer segments will change to  | 
 | 3256 |      *		CALL data_transfer, WHEN NOT data phase | 
 | 3257 |      *		MOVE x, x, WHEN data phase | 
 | 3258 |      *		( repeat ) | 
 | 3259 |      *		JUMP other_transfer | 
 | 3260 |      */ | 
 | 3261 |  | 
 | 3262 |     data_transfer_instructions = datain + dataout; | 
 | 3263 |  | 
 | 3264 |     /* | 
 | 3265 |      * When we perform a request sense, we overwrite various things, | 
 | 3266 |      * including the data transfer code.  Make sure we have enough | 
 | 3267 |      * space to do that. | 
 | 3268 |      */ | 
 | 3269 |  | 
 | 3270 |     if (data_transfer_instructions < 2) | 
 | 3271 |     	data_transfer_instructions = 2; | 
 | 3272 |  | 
 | 3273 |  | 
 | 3274 |     /* | 
 | 3275 |      * The saved data pointer is set up so that a RESTORE POINTERS message  | 
 | 3276 |      * will start the data transfer over at the beginning. | 
 | 3277 |      */ | 
 | 3278 |  | 
 | 3279 |     tmp->saved_data_pointer = virt_to_bus (hostdata->script) +  | 
 | 3280 | 	hostdata->E_data_transfer; | 
 | 3281 |  | 
 | 3282 |     /* | 
 | 3283 |      * Initialize Linux specific fields. | 
 | 3284 |      */ | 
 | 3285 |  | 
 | 3286 |     tmp->cmd = cmd; | 
 | 3287 |     tmp->next = NULL; | 
 | 3288 |     tmp->flags = 0; | 
 | 3289 |     tmp->dsa_next_addr = virt_to_bus(tmp->dsa) + hostdata->dsa_next -  | 
 | 3290 | 	hostdata->dsa_start; | 
 | 3291 |     tmp->dsa_addr = virt_to_bus(tmp->dsa) - hostdata->dsa_start; | 
 | 3292 |  | 
 | 3293 |     /*  | 
 | 3294 |      * Calculate addresses of dynamic code to fill in DSA | 
 | 3295 |      */ | 
 | 3296 |  | 
 | 3297 |     tmp->data_transfer_start = tmp->dsa + (hostdata->dsa_end -  | 
 | 3298 |     	hostdata->dsa_start) / sizeof(u32); | 
 | 3299 |     tmp->data_transfer_end = tmp->data_transfer_start +  | 
 | 3300 |     	2 * data_transfer_instructions; | 
 | 3301 |  | 
 | 3302 |     cmd_datain = datain ? tmp->data_transfer_start : NULL; | 
 | 3303 |     cmd_dataout = dataout ? (datain ? cmd_datain + 2 * datain : tmp-> | 
 | 3304 |     	data_transfer_start) : NULL; | 
 | 3305 |  | 
 | 3306 |     /* | 
 | 3307 |      * Fill in the NCR53c7x0_cmd structure as follows | 
 | 3308 |      * dsa, with fixed up DSA code | 
 | 3309 |      * datain code | 
 | 3310 |      * dataout code | 
 | 3311 |      */ | 
 | 3312 |  | 
 | 3313 |     /* Copy template code into dsa and perform all necessary fixups */ | 
 | 3314 |     if (hostdata->dsa_fixup) | 
 | 3315 |     	hostdata->dsa_fixup(tmp); | 
 | 3316 |  | 
 | 3317 |     patch_dsa_32(tmp->dsa, dsa_next, 0, 0); | 
 | 3318 |     /* | 
 | 3319 |      * XXX is this giving 53c710 access to the Scsi_Cmnd in some way? | 
 | 3320 |      * Do we need to change it for caching reasons? | 
 | 3321 |      */ | 
 | 3322 |     patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd)); | 
 | 3323 |  | 
 | 3324 |     if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) { | 
 | 3325 |  | 
 | 3326 | 	exp_select_indirect = ((1 << cmd->device->id) << 16) | | 
 | 3327 | 			(hostdata->sync[cmd->device->id].sxfer_sanity << 8); | 
 | 3328 |  | 
 | 3329 | 	if (hostdata->sync[cmd->device->id].select_indirect != | 
 | 3330 | 				exp_select_indirect) { | 
 | 3331 | 	    printk ("scsi%d :  sanity check failed select_indirect=0x%x\n", | 
 | 3332 | 		host->host_no, hostdata->sync[cmd->device->id].select_indirect); | 
 | 3333 | 	    FATAL(host); | 
 | 3334 |  | 
 | 3335 | 	} | 
 | 3336 |     } | 
 | 3337 |  | 
 | 3338 |     patch_dsa_32(tmp->dsa, dsa_select, 0, | 
 | 3339 | 		hostdata->sync[cmd->device->id].select_indirect); | 
 | 3340 |  | 
 | 3341 |     /* | 
 | 3342 |      * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on | 
 | 3343 |      * different commands; although it should be trivial to do them | 
 | 3344 |      * both at the same time. | 
 | 3345 |      */ | 
 | 3346 |     if (hostdata->initiate_wdtr & (1 << cmd->device->id)) { | 
 | 3347 | 	memcpy ((void *) (tmp->select + 1), (void *) wdtr_message, | 
 | 3348 | 	    sizeof(wdtr_message)); | 
 | 3349 |     	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message)); | 
 | 3350 | 	local_irq_save(flags); | 
 | 3351 | 	hostdata->initiate_wdtr &= ~(1 << cmd->device->id); | 
 | 3352 | 	local_irq_restore(flags); | 
 | 3353 |     } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) { | 
 | 3354 | 	memcpy ((void *) (tmp->select + 1), (void *) sdtr_message,  | 
 | 3355 | 	    sizeof(sdtr_message)); | 
 | 3356 |     	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message)); | 
 | 3357 | 	tmp->flags |= CMD_FLAG_SDTR; | 
 | 3358 | 	local_irq_save(flags); | 
 | 3359 | 	hostdata->initiate_sdtr &= ~(1 << cmd->device->id); | 
 | 3360 | 	local_irq_restore(flags); | 
 | 3361 |      | 
 | 3362 |     } | 
 | 3363 | #if 1 | 
 | 3364 |     else if (!(hostdata->talked_to & (1 << cmd->device->id)) && | 
 | 3365 | 		!(hostdata->options & OPTION_NO_ASYNC)) { | 
 | 3366 |  | 
 | 3367 | 	memcpy ((void *) (tmp->select + 1), (void *) async_message,  | 
 | 3368 | 	    sizeof(async_message)); | 
 | 3369 |     	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(async_message)); | 
 | 3370 | 	tmp->flags |= CMD_FLAG_SDTR; | 
 | 3371 |     }  | 
 | 3372 | #endif | 
 | 3373 |     else  | 
 | 3374 |     	patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1); | 
 | 3375 |  | 
 | 3376 |     hostdata->talked_to |= (1 << cmd->device->id); | 
 | 3377 |     tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ?  | 
 | 3378 | 	IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun); | 
 | 3379 |     patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select)); | 
 | 3380 |     patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len); | 
 | 3381 |     patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd)); | 
 | 3382 |     patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ?  | 
 | 3383 |     	    virt_to_bus (cmd_dataout) | 
 | 3384 | 	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer); | 
 | 3385 |     patch_dsa_32(tmp->dsa, dsa_datain, 0, cmd_datain ?  | 
 | 3386 |     	    virt_to_bus (cmd_datain)  | 
 | 3387 | 	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer); | 
 | 3388 |     /*  | 
 | 3389 |      * XXX - need to make endian aware, should use separate variables | 
 | 3390 |      * for both status and message bytes. | 
 | 3391 |      */ | 
 | 3392 |     patch_dsa_32(tmp->dsa, dsa_msgin, 0, 1); | 
 | 3393 | /*  | 
 | 3394 |  * FIXME : these only works for little endian.  We probably want to  | 
 | 3395 |  * 	provide message and status fields in the NCR53c7x0_cmd  | 
 | 3396 |  *	structure, and assign them to cmd->result when we're done. | 
 | 3397 |  */ | 
 | 3398 | #ifdef BIG_ENDIAN | 
 | 3399 |     patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2); | 
 | 3400 |     patch_dsa_32(tmp->dsa, dsa_status, 0, 1); | 
 | 3401 |     patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3); | 
 | 3402 | #else | 
 | 3403 |     patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1); | 
 | 3404 |     patch_dsa_32(tmp->dsa, dsa_status, 0, 1); | 
 | 3405 |     patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result)); | 
 | 3406 | #endif | 
 | 3407 |     patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1); | 
 | 3408 |     patch_dsa_32(tmp->dsa, dsa_msgout_other, 1,  | 
 | 3409 | 	virt_to_bus(&(hostdata->NCR53c7xx_msg_nop))); | 
 | 3410 |      | 
 | 3411 |     /* | 
 | 3412 |      * Generate code for zero or more of the DATA IN, DATA OUT phases  | 
 | 3413 |      * in the format  | 
 | 3414 |      * | 
 | 3415 |      * CALL data_transfer, WHEN NOT phase | 
 | 3416 |      * MOVE first buffer length, first buffer address, WHEN phase | 
 | 3417 |      * ... | 
 | 3418 |      * MOVE last buffer length, last buffer address, WHEN phase | 
 | 3419 |      * JUMP other_transfer | 
 | 3420 |      */ | 
 | 3421 |  | 
 | 3422 | /*  | 
 | 3423 |  * See if we're getting to data transfer by generating an unconditional  | 
 | 3424 |  * interrupt. | 
 | 3425 |  */ | 
 | 3426 | #if 0 | 
 | 3427 |     if (datain) { | 
 | 3428 | 	cmd_datain[0] = 0x98080000; | 
 | 3429 | 	cmd_datain[1] = 0x03ffd00d; | 
 | 3430 | 	cmd_datain += 2; | 
 | 3431 |     } | 
 | 3432 | #endif | 
 | 3433 |  | 
 | 3434 | /*  | 
 | 3435 |  * XXX - I'm undecided whether all of this nonsense is faster | 
 | 3436 |  * in the long run, or whether I should just go and implement a loop | 
 | 3437 |  * on the NCR chip using table indirect mode? | 
 | 3438 |  * | 
 | 3439 |  * In any case, this is how it _must_ be done for 53c700/700-66 chips, | 
 | 3440 |  * so this stays even when we come up with something better. | 
 | 3441 |  * | 
 | 3442 |  * When we're limited to 1 simultaneous command, no overlapping processing, | 
 | 3443 |  * we're seeing 630K/sec, with 7% CPU usage on a slow Syquest 45M | 
 | 3444 |  * drive. | 
 | 3445 |  * | 
 | 3446 |  * Not bad, not good. We'll see. | 
 | 3447 |  */ | 
 | 3448 |  | 
 | 3449 |     tmp->bounce.len = 0;	/* Assume aligned buffer */ | 
 | 3450 |  | 
 | 3451 |     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4,  | 
 | 3452 | 	cmd_dataout += 4, ++i) { | 
 | 3453 | 	u32 vbuf = cmd->use_sg | 
 | 3454 | 	    ? (u32)page_address(((struct scatterlist *)cmd->buffer)[i].page)+ | 
 | 3455 | 	      ((struct scatterlist *)cmd->buffer)[i].offset | 
 | 3456 | 	    : (u32)(cmd->request_buffer); | 
 | 3457 | 	u32 bbuf = virt_to_bus((void *)vbuf); | 
 | 3458 | 	u32 count = cmd->use_sg ? | 
 | 3459 | 	    ((struct scatterlist *)cmd->buffer)[i].length : | 
 | 3460 | 	    cmd->request_bufflen; | 
 | 3461 |  | 
 | 3462 | 	/* | 
 | 3463 | 	 * If we have buffers which are not aligned with 16 byte cache | 
 | 3464 | 	 * lines, then we just hope nothing accesses the other parts of | 
 | 3465 | 	 * those cache lines while the transfer is in progress.  That would | 
 | 3466 | 	 * fill the cache, and subsequent reads of the dma data would pick | 
 | 3467 | 	 * up the wrong thing. | 
 | 3468 | 	 * XXX We need a bounce buffer to handle that correctly. | 
 | 3469 | 	 */ | 
 | 3470 |  | 
 | 3471 | 	if (((bbuf & 15) || (count & 15)) && (datain || dataout)) | 
 | 3472 | 	{ | 
 | 3473 | 	    /* Bounce buffer needed */ | 
 | 3474 | 	    if (cmd->use_sg) | 
 | 3475 | 		printk ("53c7xx: Non-aligned buffer with use_sg\n"); | 
 | 3476 | 	    else if (datain && dataout) | 
 | 3477 |                 printk ("53c7xx: Non-aligned buffer with datain && dataout\n"); | 
 | 3478 |             else if (count > 256) | 
 | 3479 | 		printk ("53c7xx: Non-aligned transfer > 256 bytes\n"); | 
 | 3480 | 	    else | 
 | 3481 | 	    { | 
 | 3482 | 		    if (datain) | 
 | 3483 | 		    { | 
 | 3484 | 			tmp->bounce.len = count; | 
 | 3485 | 			tmp->bounce.addr = vbuf; | 
 | 3486 | 			bbuf = virt_to_bus(tmp->bounce.buf); | 
 | 3487 | 			tmp->bounce.buf[0] = 0xff; | 
 | 3488 | 			tmp->bounce.buf[1] = 0xfe; | 
 | 3489 | 			tmp->bounce.buf[2] = 0xfd; | 
 | 3490 | 			tmp->bounce.buf[3] = 0xfc; | 
 | 3491 | 	    	    } | 
 | 3492 | 	    	    if (dataout) | 
 | 3493 | 	    	    { | 
 | 3494 | 			memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count); | 
 | 3495 | 			bbuf = virt_to_bus(tmp->bounce.buf); | 
 | 3496 | 		    } | 
 | 3497 | 	    } | 
 | 3498 | 	} | 
 | 3499 |  | 
 | 3500 | 	if (datain) { | 
 | 3501 |             cache_clear(virt_to_phys((void *)vbuf), count); | 
 | 3502 | 	    /* CALL other_in, WHEN NOT DATA_IN */   | 
 | 3503 | 	    cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL |  | 
 | 3504 | 		DCMD_TCI_IO) << 24) |  | 
 | 3505 | 		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; | 
 | 3506 | 	    cmd_datain[1] = virt_to_bus (hostdata->script) +  | 
 | 3507 | 		hostdata->E_other_in; | 
 | 3508 | 	    /* MOVE count, buf, WHEN DATA_IN */ | 
 | 3509 | 	    cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO)  | 
 | 3510 |     	    	<< 24) | count; | 
 | 3511 | 	    cmd_datain[3] = bbuf; | 
 | 3512 | #if 0 | 
 | 3513 | 	    print_insn (host, cmd_datain, "dynamic ", 1); | 
 | 3514 | 	    print_insn (host, cmd_datain + 2, "dynamic ", 1); | 
 | 3515 | #endif | 
 | 3516 | 	} | 
 | 3517 | 	if (dataout) { | 
 | 3518 |             cache_push(virt_to_phys((void *)vbuf), count); | 
 | 3519 | 	    /* CALL other_out, WHEN NOT DATA_OUT */ | 
 | 3520 | 	    cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) |  | 
 | 3521 | 		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; | 
 | 3522 | 	    cmd_dataout[1] = virt_to_bus(hostdata->script) +  | 
 | 3523 |     	    	hostdata->E_other_out; | 
 | 3524 | 	    /* MOVE count, buf, WHEN DATA+OUT */ | 
 | 3525 | 	    cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24)  | 
 | 3526 | 		| count; | 
 | 3527 | 	    cmd_dataout[3] = bbuf; | 
 | 3528 | #if 0 | 
 | 3529 | 	    print_insn (host, cmd_dataout, "dynamic ", 1); | 
 | 3530 | 	    print_insn (host, cmd_dataout + 2, "dynamic ", 1); | 
 | 3531 | #endif | 
 | 3532 | 	} | 
 | 3533 |     } | 
 | 3534 |  | 
 | 3535 |     /* | 
 | 3536 |      * Install JUMP instructions after the data transfer routines to return | 
 | 3537 |      * control to the do_other_transfer routines. | 
 | 3538 |      */ | 
 | 3539 |    | 
 | 3540 |      | 
 | 3541 |     if (datain) { | 
 | 3542 | 	cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) | | 
 | 3543 |     	    DBC_TCI_TRUE; | 
 | 3544 | 	cmd_datain[1] = virt_to_bus(hostdata->script) +  | 
 | 3545 |     	    hostdata->E_other_transfer; | 
 | 3546 | #if 0 | 
 | 3547 | 	print_insn (host, cmd_datain, "dynamic jump ", 1); | 
 | 3548 | #endif | 
 | 3549 | 	cmd_datain += 2;  | 
 | 3550 |     } | 
 | 3551 | #if 0 | 
 | 3552 |     if (datain) { | 
 | 3553 | 	cmd_datain[0] = 0x98080000; | 
 | 3554 | 	cmd_datain[1] = 0x03ffdeed; | 
 | 3555 | 	cmd_datain += 2; | 
 | 3556 |     } | 
 | 3557 | #endif | 
 | 3558 |     if (dataout) { | 
 | 3559 | 	cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_JUMP) << 24) | | 
 | 3560 |     	    DBC_TCI_TRUE; | 
 | 3561 | 	cmd_dataout[1] = virt_to_bus(hostdata->script) +  | 
 | 3562 |     	    hostdata->E_other_transfer; | 
 | 3563 | #if 0 | 
 | 3564 | 	print_insn (host, cmd_dataout, "dynamic jump ", 1); | 
 | 3565 | #endif | 
 | 3566 | 	cmd_dataout += 2; | 
 | 3567 |     } | 
 | 3568 |  | 
 | 3569 |     return tmp; | 
 | 3570 | } | 
 | 3571 |  | 
 | 3572 | /* | 
 | 3573 |  * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd, | 
 | 3574 |  *      void (*done)(Scsi_Cmnd *)) | 
 | 3575 |  * | 
 | 3576 |  * Purpose :  enqueues a SCSI command | 
 | 3577 |  * | 
 | 3578 |  * Inputs : cmd - SCSI command, done - function called on completion, with | 
 | 3579 |  *      a pointer to the command descriptor. | 
 | 3580 |  * | 
 | 3581 |  * Returns : 0 | 
 | 3582 |  * | 
 | 3583 |  * Side effects : | 
 | 3584 |  *      cmd is added to the per instance driver issue_queue, with major | 
 | 3585 |  *      twiddling done to the host specific fields of cmd.  If the | 
 | 3586 |  *      process_issue_queue coroutine isn't running, it is restarted. | 
 | 3587 |  *  | 
 | 3588 |  * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to  | 
 | 3589 |  *	hold our own data, and pervert the ptr field of the SCp field | 
 | 3590 |  *	to create a linked list. | 
 | 3591 |  */ | 
 | 3592 |  | 
 | 3593 | int | 
 | 3594 | NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { | 
 | 3595 |     struct Scsi_Host *host = cmd->device->host; | 
 | 3596 |     struct NCR53c7x0_hostdata *hostdata =  | 
 | 3597 | 	(struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 3598 |     unsigned long flags; | 
 | 3599 |     Scsi_Cmnd *tmp; | 
 | 3600 |  | 
 | 3601 |     cmd->scsi_done = done; | 
 | 3602 |     cmd->host_scribble = NULL; | 
 | 3603 |     cmd->SCp.ptr = NULL; | 
 | 3604 |     cmd->SCp.buffer = NULL; | 
 | 3605 |  | 
 | 3606 | #ifdef VALID_IDS | 
 | 3607 |     /* Ignore commands on invalid IDs */ | 
 | 3608 |     if (!hostdata->valid_ids[cmd->device->id]) { | 
 | 3609 |         printk("scsi%d : ignoring target %d lun %d\n", host->host_no, | 
 | 3610 |             cmd->device->id, cmd->device->lun); | 
 | 3611 |         cmd->result = (DID_BAD_TARGET << 16); | 
 | 3612 |         done(cmd); | 
 | 3613 |         return 0; | 
 | 3614 |     } | 
 | 3615 | #endif | 
 | 3616 |  | 
 | 3617 |     local_irq_save(flags); | 
 | 3618 |     if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY))  | 
 | 3619 | 	|| ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && | 
 | 3620 | 	    !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun))) | 
 | 3621 | #ifdef LINUX_1_2 | 
 | 3622 | 	|| cmd->device->id > 7 | 
 | 3623 | #else | 
 | 3624 | 	|| cmd->device->id > host->max_id | 
 | 3625 | #endif | 
 | 3626 | 	|| cmd->device->id == host->this_id | 
 | 3627 | 	|| hostdata->state == STATE_DISABLED) { | 
 | 3628 | 	printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no, | 
 | 3629 | 	    cmd->device->id, cmd->device->lun); | 
 | 3630 | 	cmd->result = (DID_BAD_TARGET << 16); | 
 | 3631 | 	done(cmd); | 
 | 3632 | 	local_irq_restore(flags); | 
 | 3633 | 	return 0; | 
 | 3634 |     } | 
 | 3635 |  | 
 | 3636 |     if ((hostdata->options & OPTION_DEBUG_NCOMMANDS_LIMIT) && | 
 | 3637 | 	(hostdata->debug_count_limit == 0)) { | 
 | 3638 | 	printk("scsi%d : maximum commands exceeded\n", host->host_no); | 
 | 3639 | 	cmd->result = (DID_BAD_TARGET << 16); | 
 | 3640 | 	done(cmd); | 
 | 3641 | 	local_irq_restore(flags); | 
 | 3642 | 	return 0; | 
 | 3643 |     } | 
 | 3644 |  | 
 | 3645 |     if (hostdata->options & OPTION_DEBUG_READ_ONLY) { | 
 | 3646 | 	switch (cmd->cmnd[0]) { | 
 | 3647 | 	case WRITE_6: | 
 | 3648 | 	case WRITE_10: | 
 | 3649 | 	    printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", | 
 | 3650 | 		host->host_no); | 
 | 3651 | 	    cmd->result = (DID_BAD_TARGET << 16); | 
 | 3652 | 	    done(cmd); | 
 | 3653 | 	    local_irq_restore(flags); | 
 | 3654 | 	    return 0; | 
 | 3655 | 	} | 
 | 3656 |     } | 
 | 3657 |  | 
 | 3658 |     if ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && | 
 | 3659 | 	    hostdata->debug_count_limit != -1)  | 
 | 3660 | 	--hostdata->debug_count_limit; | 
 | 3661 |  | 
 | 3662 |     cmd->result = 0xffff;	/* The NCR will overwrite message | 
 | 3663 | 				       and status with valid data */ | 
 | 3664 |     cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd); | 
 | 3665 |  | 
 | 3666 |     /* | 
 | 3667 |      * REQUEST SENSE commands are inserted at the head of the queue  | 
 | 3668 |      * so that we do not clear the contingent allegiance condition | 
 | 3669 |      * they may be looking at. | 
 | 3670 |      */ | 
 | 3671 |  | 
 | 3672 |     if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { | 
 | 3673 | 	cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue; | 
 | 3674 | 	hostdata->issue_queue = cmd; | 
 | 3675 |     } else { | 
 | 3676 | 	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr;  | 
 | 3677 | 		tmp = (Scsi_Cmnd *) tmp->SCp.ptr); | 
 | 3678 | 	tmp->SCp.ptr = (unsigned char *) cmd; | 
 | 3679 |     } | 
 | 3680 |     local_irq_restore(flags); | 
 | 3681 |     run_process_issue_queue(); | 
 | 3682 |     return 0; | 
 | 3683 | } | 
 | 3684 |  | 
 | 3685 | /* | 
 | 3686 |  * Function : void to_schedule_list (struct Scsi_Host *host, | 
 | 3687 |  * 	struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd) | 
 | 3688 |  * | 
 | 3689 |  * Purpose : takes a SCSI command which was just removed from the  | 
 | 3690 |  *	issue queue, and deals with it by inserting it in the first | 
 | 3691 |  *	free slot in the schedule list or by terminating it immediately. | 
 | 3692 |  * | 
 | 3693 |  * Inputs :  | 
 | 3694 |  *	host - SCSI host adapter; hostdata - hostdata structure for  | 
 | 3695 |  *	this adapter; cmd - a pointer to the command; should have  | 
 | 3696 |  *	the host_scribble field initialized to point to a valid  | 
 | 3697 |  *	 | 
 | 3698 |  * Side effects :  | 
 | 3699 |  *      cmd is added to the per instance schedule list, with minor  | 
 | 3700 |  *      twiddling done to the host specific fields of cmd. | 
 | 3701 |  * | 
 | 3702 |  */ | 
 | 3703 |  | 
 | 3704 | static __inline__ void | 
 | 3705 | to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, | 
 | 3706 |     struct NCR53c7x0_cmd *cmd) { | 
 | 3707 |     NCR53c7x0_local_declare(); | 
 | 3708 |     Scsi_Cmnd *tmp = cmd->cmd; | 
 | 3709 |     unsigned long flags; | 
 | 3710 |     /* dsa start is negative, so subtraction is used */ | 
 | 3711 |     volatile u32 *ncrcurrent; | 
 | 3712 |  | 
 | 3713 |     int i; | 
 | 3714 |     NCR53c7x0_local_setup(host); | 
 | 3715 | #if 0 | 
 | 3716 |     printk("scsi%d : new dsa is 0x%lx (virt 0x%p)\n", host->host_no,  | 
 | 3717 | 	virt_to_bus(hostdata->dsa), hostdata->dsa); | 
 | 3718 | #endif | 
 | 3719 |  | 
 | 3720 |     local_irq_save(flags); | 
 | 3721 |      | 
 | 3722 |     /*  | 
 | 3723 |      * Work around race condition : if an interrupt fired and we  | 
 | 3724 |      * got disabled forget about this command. | 
 | 3725 |      */ | 
 | 3726 |  | 
 | 3727 |     if (hostdata->state == STATE_DISABLED) { | 
 | 3728 | 	printk("scsi%d : driver disabled\n", host->host_no); | 
 | 3729 | 	tmp->result = (DID_BAD_TARGET << 16); | 
 | 3730 | 	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; | 
 | 3731 | 	hostdata->free = cmd; | 
 | 3732 | 	tmp->scsi_done(tmp); | 
 | 3733 | 	local_irq_restore(flags); | 
 | 3734 | 	return; | 
 | 3735 |     } | 
 | 3736 |  | 
 | 3737 |     for (i = host->can_queue, ncrcurrent = hostdata->schedule;  | 
 | 3738 | 	i > 0  && ncrcurrent[0] != hostdata->NOP_insn; | 
 | 3739 | 	--i, ncrcurrent += 2 /* JUMP instructions are two words */); | 
 | 3740 |  | 
 | 3741 |     if (i > 0) { | 
 | 3742 | 	++hostdata->busy[tmp->device->id][tmp->device->lun]; | 
 | 3743 | 	cmd->next = hostdata->running_list; | 
 | 3744 | 	hostdata->running_list = cmd; | 
 | 3745 |  | 
 | 3746 | 	/* Restore this instruction to a NOP once the command starts */ | 
 | 3747 | 	cmd->dsa [(hostdata->dsa_jump_dest - hostdata->dsa_start) /  | 
 | 3748 | 	    sizeof(u32)] = (u32) virt_to_bus ((void *)ncrcurrent); | 
 | 3749 | 	/* Replace the current jump operand.  */ | 
 | 3750 | 	ncrcurrent[1] = | 
 | 3751 | 	    virt_to_bus ((void *) cmd->dsa) + hostdata->E_dsa_code_begin - | 
 | 3752 | 	    hostdata->E_dsa_code_template; | 
 | 3753 | 	/* Replace the NOP instruction with a JUMP */ | 
 | 3754 | 	ncrcurrent[0] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24) | | 
 | 3755 | 	    DBC_TCI_TRUE; | 
 | 3756 |     }  else { | 
 | 3757 | 	printk ("scsi%d: no free slot\n", host->host_no); | 
 | 3758 | 	disable(host); | 
 | 3759 | 	tmp->result = (DID_ERROR << 16); | 
 | 3760 | 	cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; | 
 | 3761 | 	hostdata->free = cmd; | 
 | 3762 | 	tmp->scsi_done(tmp); | 
 | 3763 | 	local_irq_restore(flags); | 
 | 3764 | 	return; | 
 | 3765 |     } | 
 | 3766 |  | 
 | 3767 |     /*  | 
 | 3768 |      * If the NCR chip is in an idle state, start it running the scheduler | 
 | 3769 |      * immediately.  Otherwise, signal the chip to jump to schedule as  | 
 | 3770 |      * soon as it is idle. | 
 | 3771 |      */ | 
 | 3772 |  | 
 | 3773 |     if (hostdata->idle) { | 
 | 3774 | 	hostdata->idle = 0; | 
 | 3775 | 	hostdata->state = STATE_RUNNING; | 
 | 3776 | 	NCR53c7x0_write32 (DSP_REG,  virt_to_bus ((void *)hostdata->schedule)); | 
 | 3777 | 	if (hostdata->options & OPTION_DEBUG_TRACE) | 
 | 3778 | 	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | | 
 | 3779 | 				DCNTL_SSM | DCNTL_STD); | 
 | 3780 |     } else { | 
 | 3781 | 	NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP); | 
 | 3782 |     } | 
 | 3783 |  | 
 | 3784 |     local_irq_restore(flags); | 
 | 3785 | } | 
 | 3786 |  | 
 | 3787 | /* | 
 | 3788 |  * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata  | 
 | 3789 |  *	*hostdata, Scsi_Cmnd *cmd) | 
 | 3790 |  * | 
 | 3791 |  * Purpose : decide if we can pass the given SCSI command on to the  | 
 | 3792 |  *	device in question or not. | 
 | 3793 |  *   | 
 | 3794 |  * Returns : non-zero when we're busy, 0 when we aren't. | 
 | 3795 |  */ | 
 | 3796 |  | 
 | 3797 | static __inline__ int | 
 | 3798 | busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,  | 
 | 3799 |     Scsi_Cmnd *cmd) { | 
 | 3800 |     /* FIXME : in the future, this needs to accommodate SCSI-II tagged | 
 | 3801 |        queuing, and we may be able to play with fairness here a bit. | 
 | 3802 |      */ | 
 | 3803 |     return hostdata->busy[cmd->device->id][cmd->device->lun]; | 
 | 3804 | } | 
 | 3805 |  | 
 | 3806 | /* | 
 | 3807 |  * Function : process_issue_queue (void) | 
 | 3808 |  * | 
 | 3809 |  * Purpose : transfer commands from the issue queue to NCR start queue  | 
 | 3810 |  *	of each NCR53c7/8xx in the system, avoiding kernel stack  | 
 | 3811 |  *	overflows when the scsi_done() function is invoked recursively. | 
 | 3812 |  *  | 
 | 3813 |  * NOTE : process_issue_queue exits with interrupts *disabled*, so the  | 
 | 3814 |  *	caller must reenable them if it desires. | 
 | 3815 |  *  | 
 | 3816 |  * NOTE : process_issue_queue should be called from both  | 
 | 3817 |  *	NCR53c7x0_queue_command() and from the interrupt handler  | 
 | 3818 |  *	after command completion in case NCR53c7x0_queue_command() | 
 | 3819 |  * 	isn't invoked again but we've freed up resources that are | 
 | 3820 |  *	needed. | 
 | 3821 |  */ | 
 | 3822 |  | 
 | 3823 | static void  | 
 | 3824 | process_issue_queue (unsigned long flags) { | 
 | 3825 |     Scsi_Cmnd *tmp, *prev; | 
 | 3826 |     struct Scsi_Host *host; | 
 | 3827 |     struct NCR53c7x0_hostdata *hostdata; | 
 | 3828 |     int done; | 
 | 3829 |  | 
 | 3830 |     /* | 
 | 3831 |      * We run (with interrupts disabled) until we're sure that none of  | 
 | 3832 |      * the host adapters have anything that can be done, at which point  | 
 | 3833 |      * we set process_issue_queue_running to 0 and exit. | 
 | 3834 |      * | 
 | 3835 |      * Interrupts are enabled before doing various other internal  | 
 | 3836 |      * instructions, after we've decided that we need to run through | 
 | 3837 |      * the loop again. | 
 | 3838 |      * | 
 | 3839 |      */ | 
 | 3840 |  | 
 | 3841 |     do { | 
 | 3842 | 	local_irq_disable(); /* Freeze request queues */ | 
 | 3843 | 	done = 1; | 
 | 3844 | 	for (host = first_host; host && host->hostt == the_template; | 
 | 3845 | 	    host = host->next) { | 
 | 3846 | 	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 3847 | 	    local_irq_disable(); | 
 | 3848 | 	    if (hostdata->issue_queue) { | 
 | 3849 | 	    	if (hostdata->state == STATE_DISABLED) { | 
 | 3850 | 		    tmp = (Scsi_Cmnd *) hostdata->issue_queue; | 
 | 3851 | 		    hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr; | 
 | 3852 | 		    tmp->result = (DID_BAD_TARGET << 16); | 
 | 3853 | 		    if (tmp->host_scribble) { | 
 | 3854 | 			((struct NCR53c7x0_cmd *)tmp->host_scribble)->next =  | 
 | 3855 | 			    hostdata->free; | 
 | 3856 | 			hostdata->free =  | 
 | 3857 | 			    (struct NCR53c7x0_cmd *)tmp->host_scribble; | 
 | 3858 | 			tmp->host_scribble = NULL; | 
 | 3859 | 		    } | 
 | 3860 | 		    tmp->scsi_done (tmp); | 
 | 3861 | 		    done = 0; | 
 | 3862 | 		} else  | 
 | 3863 | 		    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue,  | 
 | 3864 | 			prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *)  | 
 | 3865 | 			tmp->SCp.ptr)  | 
 | 3866 | 			if (!tmp->host_scribble ||  | 
 | 3867 | 			    !busyp (host, hostdata, tmp)) { | 
 | 3868 | 				if (prev) | 
 | 3869 | 				    prev->SCp.ptr = tmp->SCp.ptr; | 
 | 3870 | 				else | 
 | 3871 | 				    hostdata->issue_queue = (Scsi_Cmnd *)  | 
 | 3872 | 					tmp->SCp.ptr; | 
 | 3873 | 			    tmp->SCp.ptr = NULL; | 
 | 3874 | 			    if (tmp->host_scribble) { | 
 | 3875 | 				if (hostdata->options & OPTION_DEBUG_QUEUES)  | 
 | 3876 | 				    printk ("scsi%d : moving command for target %d lun %d to start list\n", | 
 | 3877 | 					host->host_no, tmp->device->id, tmp->device->lun); | 
 | 3878 | 		 | 
 | 3879 |  | 
 | 3880 | 			    	to_schedule_list (host, hostdata,  | 
 | 3881 | 				    (struct NCR53c7x0_cmd *) | 
 | 3882 | 				    tmp->host_scribble); | 
 | 3883 | 			    } else { | 
 | 3884 | 				if (((tmp->result & 0xff) == 0xff) || | 
 | 3885 | 			    	    ((tmp->result & 0xff00) == 0xff00)) { | 
 | 3886 | 				    printk ("scsi%d : danger Will Robinson!\n", | 
 | 3887 | 					host->host_no); | 
 | 3888 | 				    tmp->result = DID_ERROR << 16; | 
 | 3889 | 				    disable (host); | 
 | 3890 | 				} | 
 | 3891 | 				tmp->scsi_done(tmp); | 
 | 3892 | 			    } | 
 | 3893 | 			    done = 0; | 
 | 3894 | 			} /* if target/lun is not busy */ | 
 | 3895 | 	    } /* if hostdata->issue_queue */ | 
 | 3896 | 	    if (!done) | 
 | 3897 | 		local_irq_restore(flags); | 
 | 3898 |     	} /* for host */ | 
 | 3899 |     } while (!done); | 
 | 3900 |     process_issue_queue_running = 0; | 
 | 3901 | } | 
 | 3902 |  | 
 | 3903 | /* | 
 | 3904 |  * Function : static void intr_scsi (struct Scsi_Host *host,  | 
 | 3905 |  * 	struct NCR53c7x0_cmd *cmd) | 
 | 3906 |  * | 
 | 3907 |  * Purpose : handle all SCSI interrupts, indicated by the setting  | 
 | 3908 |  * 	of the SIP bit in the ISTAT register. | 
 | 3909 |  * | 
 | 3910 |  * Inputs : host, cmd - host and NCR command causing the interrupt, cmd | 
 | 3911 |  * 	may be NULL. | 
 | 3912 |  */ | 
 | 3913 |  | 
 | 3914 | static void  | 
 | 3915 | intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { | 
 | 3916 |     NCR53c7x0_local_declare(); | 
 | 3917 |     struct NCR53c7x0_hostdata *hostdata =  | 
 | 3918 |     	(struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 3919 |     unsigned char sstat0_sist0, sist1, 		/* Registers */ | 
 | 3920 | 	    fatal; 				/* Did a fatal interrupt  | 
 | 3921 | 						   occur ? */ | 
 | 3922 |     | 
 | 3923 |     NCR53c7x0_local_setup(host); | 
 | 3924 |  | 
 | 3925 |     fatal = 0; | 
 | 3926 |  | 
 | 3927 |     sstat0_sist0 = NCR53c7x0_read8(SSTAT0_REG); | 
 | 3928 |     sist1 = 0; | 
 | 3929 |  | 
 | 3930 |     if (hostdata->options & OPTION_DEBUG_INTR)  | 
 | 3931 | 	printk ("scsi%d : SIST0 0x%0x, SIST1 0x%0x\n", host->host_no, | 
 | 3932 | 	    sstat0_sist0, sist1); | 
 | 3933 |  | 
 | 3934 |     /* 250ms selection timeout */ | 
 | 3935 |     if (sstat0_sist0 & SSTAT0_700_STO) { | 
 | 3936 | 	fatal = 1; | 
 | 3937 | 	if (hostdata->options & OPTION_DEBUG_INTR) { | 
 | 3938 | 	    printk ("scsi%d : Selection Timeout\n", host->host_no); | 
 | 3939 |     	    if (cmd) { | 
 | 3940 |     	    	printk("scsi%d : target %d, lun %d, command ", | 
 | 3941 | 		    host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 3942 |     	    	__scsi_print_command (cmd->cmd->cmnd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3943 | 		printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no, | 
 | 3944 | 		    NCR53c7x0_read32(DSP_REG), | 
 | 3945 | 		    bus_to_virt(NCR53c7x0_read32(DSP_REG))); | 
 | 3946 |     	    } else { | 
 | 3947 |     	    	printk("scsi%d : no command\n", host->host_no); | 
 | 3948 |     	    } | 
 | 3949 |     	} | 
 | 3950 | /* | 
 | 3951 |  * XXX - question : how do we want to handle the Illegal Instruction | 
 | 3952 |  * 	interrupt, which may occur before or after the Selection Timeout | 
 | 3953 |  * 	interrupt? | 
 | 3954 |  */ | 
 | 3955 |  | 
 | 3956 | 	if (1) { | 
 | 3957 | 	    hostdata->idle = 1; | 
 | 3958 | 	    hostdata->expecting_sto = 0; | 
 | 3959 |  | 
 | 3960 | 	    if (hostdata->test_running) { | 
 | 3961 | 		hostdata->test_running = 0; | 
 | 3962 | 		hostdata->test_completed = 3; | 
 | 3963 | 	    } else if (cmd) { | 
 | 3964 | 		abnormal_finished(cmd, DID_BAD_TARGET << 16); | 
 | 3965 | 	    } | 
 | 3966 | #if 0	     | 
 | 3967 | 	    hostdata->intrs = 0; | 
 | 3968 | #endif | 
 | 3969 | 	} | 
 | 3970 |     }  | 
 | 3971 |  | 
 | 3972 | /* | 
 | 3973 |  * FIXME : in theory, we can also get a UDC when a STO occurs. | 
 | 3974 |  */ | 
 | 3975 |     if (sstat0_sist0 & SSTAT0_UDC) { | 
 | 3976 | 	fatal = 1; | 
 | 3977 | 	if (cmd) { | 
 | 3978 | 	    printk("scsi%d : target %d lun %d unexpected disconnect\n", | 
 | 3979 | 		host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); | 
 | 3980 | 	    print_lots (host); | 
 | 3981 | 	    abnormal_finished(cmd, DID_ERROR << 16); | 
 | 3982 | 	} else  | 
 | 3983 | 	     printk("scsi%d : unexpected disconnect (no command)\n", | 
 | 3984 | 		host->host_no); | 
 | 3985 |  | 
 | 3986 | 	hostdata->dsp = (u32 *) hostdata->schedule; | 
 | 3987 | 	hostdata->dsp_changed = 1; | 
 | 3988 |     } | 
 | 3989 |  | 
 | 3990 |     /* SCSI PARITY error */ | 
 | 3991 |     if (sstat0_sist0 & SSTAT0_PAR) { | 
 | 3992 | 	fatal = 1; | 
 | 3993 | 	if (cmd && cmd->cmd) { | 
 | 3994 | 	    printk("scsi%d : target %d lun %d parity error.\n", | 
 | 3995 | 		host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); | 
 | 3996 | 	    abnormal_finished (cmd, DID_PARITY << 16);  | 
 | 3997 | 	} else | 
 | 3998 | 	    printk("scsi%d : parity error\n", host->host_no); | 
 | 3999 | 	/* Should send message out, parity error */ | 
 | 4000 |  | 
 | 4001 | 	/* XXX - Reduce synchronous transfer rate! */ | 
 | 4002 | 	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / | 
 | 4003 |     	    sizeof(u32); | 
 | 4004 | 	hostdata->dsp_changed = 1;  | 
 | 4005 |     /* SCSI GROSS error */ | 
 | 4006 |     }  | 
 | 4007 |  | 
 | 4008 |     if (sstat0_sist0 & SSTAT0_SGE) { | 
 | 4009 | 	fatal = 1; | 
 | 4010 | 	printk("scsi%d : gross error, saved2_dsa = 0x%x\n", host->host_no, | 
 | 4011 | 					(unsigned int)hostdata->saved2_dsa); | 
 | 4012 | 	print_lots (host); | 
 | 4013 | 	 | 
 | 4014 | 	/*  | 
 | 4015 |          * A SCSI gross error may occur when we have  | 
 | 4016 | 	 * | 
 | 4017 | 	 * - A synchronous offset which causes the SCSI FIFO to be overwritten. | 
 | 4018 | 	 * | 
 | 4019 | 	 * - A REQ which causes the maximum synchronous offset programmed in  | 
 | 4020 | 	 * 	the SXFER register to be exceeded. | 
 | 4021 | 	 * | 
 | 4022 | 	 * - A phase change with an outstanding synchronous offset. | 
 | 4023 | 	 * | 
 | 4024 | 	 * - Residual data in the synchronous data FIFO, with a transfer | 
 | 4025 | 	 *	other than a synchronous receive is started.$# | 
 | 4026 | 	 */ | 
 | 4027 | 		 | 
 | 4028 |  | 
 | 4029 | 	/* XXX Should deduce synchronous transfer rate! */ | 
 | 4030 | 	hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / | 
 | 4031 |     	    sizeof(u32); | 
 | 4032 | 	hostdata->dsp_changed = 1; | 
 | 4033 |     /* Phase mismatch */ | 
 | 4034 |     }  | 
 | 4035 |  | 
 | 4036 |     if (sstat0_sist0 & SSTAT0_MA) { | 
 | 4037 | 	fatal = 1; | 
 | 4038 | 	if (hostdata->options & OPTION_DEBUG_INTR) | 
 | 4039 | 	    printk ("scsi%d : SSTAT0_MA\n", host->host_no); | 
 | 4040 | 	intr_phase_mismatch (host, cmd); | 
 | 4041 |     } | 
 | 4042 |  | 
 | 4043 | #if 0 | 
 | 4044 |     if (sstat0_sist0 & SIST0_800_RSL)  | 
 | 4045 | 	printk ("scsi%d : Oh no Mr. Bill!\n", host->host_no); | 
 | 4046 | #endif | 
 | 4047 |      | 
 | 4048 | /* | 
 | 4049 |  * If a fatal SCSI interrupt occurs, we must insure that the DMA and | 
 | 4050 |  * SCSI FIFOs were flushed. | 
 | 4051 |  */ | 
 | 4052 |  | 
 | 4053 |     if (fatal) { | 
 | 4054 | 	if (!hostdata->dstat_valid) { | 
 | 4055 | 	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); | 
 | 4056 | 	    hostdata->dstat_valid = 1; | 
 | 4057 | 	} | 
 | 4058 |  | 
 | 4059 | 	if (!(hostdata->dstat & DSTAT_DFE)) { | 
 | 4060 | 	  printk ("scsi%d : DMA FIFO not empty\n", host->host_no); | 
 | 4061 | 	  /* | 
 | 4062 | 	   * Really need to check this code for 710  RGH. | 
 | 4063 | 	   * Havn't seen any problems, but maybe we should FLUSH before | 
 | 4064 | 	   * clearing sometimes. | 
 | 4065 | 	   */ | 
 | 4066 |           NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF); | 
 | 4067 |           while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF) | 
 | 4068 | 		; | 
 | 4069 | 	  hostdata->dstat |= DSTAT_DFE; | 
 | 4070 |     	} | 
 | 4071 |     } | 
 | 4072 | } | 
 | 4073 |  | 
 | 4074 | #ifdef CYCLIC_TRACE | 
 | 4075 |  | 
 | 4076 | /* | 
 | 4077 |  * The following implements a cyclic log of instructions executed, if you turn | 
 | 4078 |  * TRACE on.  It will also print the log for you.  Very useful when debugging | 
 | 4079 |  * 53c710 support, possibly not really needed any more. | 
 | 4080 |  */ | 
 | 4081 |  | 
 | 4082 | u32 insn_log[4096]; | 
 | 4083 | u32 insn_log_index = 0; | 
 | 4084 |  | 
 | 4085 | void log1 (u32 i) | 
 | 4086 | { | 
 | 4087 | 	insn_log[insn_log_index++] = i; | 
 | 4088 | 	if (insn_log_index == 4096) | 
 | 4089 | 		insn_log_index = 0; | 
 | 4090 | } | 
 | 4091 |  | 
 | 4092 | void log_insn (u32 *ip) | 
 | 4093 | { | 
 | 4094 | 	log1 ((u32)ip); | 
 | 4095 | 	log1 (*ip); | 
 | 4096 | 	log1 (*(ip+1)); | 
 | 4097 | 	if (((*ip >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI) | 
 | 4098 | 		log1 (*(ip+2)); | 
 | 4099 | } | 
 | 4100 |  | 
 | 4101 | void dump_log(void) | 
 | 4102 | { | 
 | 4103 | 	int cnt = 0; | 
 | 4104 | 	int i = insn_log_index; | 
 | 4105 | 	int size; | 
 | 4106 | 	struct Scsi_Host *host = first_host; | 
 | 4107 |  | 
 | 4108 | 	while (cnt < 4096) { | 
 | 4109 | 		printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4); | 
 | 4110 | 		if (++i == 4096) | 
 | 4111 | 			i = 0; | 
 | 4112 | 		cnt++; | 
 | 4113 | 		if (((insn_log[i]  >> 24) & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)  | 
 | 4114 | 			size = 3; | 
 | 4115 | 		else | 
 | 4116 | 			size = 2; | 
 | 4117 | 		while (size--) { | 
 | 4118 | 			printk ("%08x ", insn_log[i]); | 
 | 4119 | 			if (++i == 4096) | 
 | 4120 | 				i = 0; | 
 | 4121 | 			cnt++; | 
 | 4122 | 		} | 
 | 4123 | 		printk ("\n"); | 
 | 4124 | 	} | 
 | 4125 | } | 
 | 4126 | #endif | 
 | 4127 |  | 
 | 4128 |  | 
 | 4129 | /* | 
 | 4130 |  * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host) | 
 | 4131 |  * | 
 | 4132 |  * Purpose : Scan command queue for specified host, looking for completed | 
 | 4133 |  *           commands. | 
 | 4134 |  *  | 
 | 4135 |  * Inputs : Scsi_Host pointer. | 
 | 4136 |  * | 
 | 4137 |  * 	This is called from the interrupt handler, when a simulated INTFLY | 
 | 4138 |  * 	interrupt occurs. | 
 | 4139 |  */ | 
 | 4140 |  | 
 | 4141 | static void | 
 | 4142 | NCR53c7x0_intfly (struct Scsi_Host *host) | 
 | 4143 | { | 
 | 4144 |     NCR53c7x0_local_declare(); | 
 | 4145 |     struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */ | 
 | 4146 |     struct NCR53c7x0_cmd *cmd,			/* command which halted */ | 
 | 4147 | 	**cmd_prev_ptr; | 
 | 4148 |     unsigned long flags;				 | 
 | 4149 |     char search_found = 0;			/* Got at least one ? */ | 
 | 4150 |  | 
 | 4151 |     hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 4152 |     NCR53c7x0_local_setup(host); | 
 | 4153 |  | 
 | 4154 |     if (hostdata->options & OPTION_DEBUG_INTR) | 
 | 4155 |     printk ("scsi%d : INTFLY\n", host->host_no);  | 
 | 4156 |  | 
 | 4157 |     /* | 
 | 4158 |     * Traverse our list of running commands, and look | 
 | 4159 |     * for those with valid (non-0xff ff) status and message | 
 | 4160 |     * bytes encoded in the result which signify command | 
 | 4161 |     * completion. | 
 | 4162 |     */ | 
 | 4163 |  | 
 | 4164 |     local_irq_save(flags); | 
 | 4165 | restart: | 
 | 4166 |     for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list), | 
 | 4167 | 	cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ; | 
 | 4168 | 	cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next),  | 
 | 4169 |     	cmd = (struct NCR53c7x0_cmd *) cmd->next) | 
 | 4170 |     { | 
 | 4171 | 	Scsi_Cmnd *tmp; | 
 | 4172 |  | 
 | 4173 | 	if (!cmd) { | 
 | 4174 | 	    printk("scsi%d : very weird.\n", host->host_no); | 
 | 4175 | 	    break; | 
 | 4176 | 	} | 
 | 4177 |  | 
 | 4178 | 	if (!(tmp = cmd->cmd)) { | 
 | 4179 | 	    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n", | 
 | 4180 | 		    host->host_no); | 
 | 4181 | 	    continue; | 
 | 4182 | 	} | 
 | 4183 | 	/* Copy the result over now; may not be complete, | 
 | 4184 | 	 * but subsequent tests may as well be done on | 
 | 4185 | 	 * cached memory. | 
 | 4186 | 	 */ | 
 | 4187 | 	tmp->result = cmd->result; | 
 | 4188 |  | 
 | 4189 | 	if (((tmp->result & 0xff) == 0xff) || | 
 | 4190 | 			    ((tmp->result & 0xff00) == 0xff00)) | 
 | 4191 | 	    continue; | 
 | 4192 |  | 
 | 4193 | 	search_found = 1; | 
 | 4194 |  | 
 | 4195 | 	if (cmd->bounce.len) | 
 | 4196 | 	    memcpy ((void *)cmd->bounce.addr, | 
 | 4197 | 				(void *)cmd->bounce.buf, cmd->bounce.len); | 
 | 4198 |  | 
 | 4199 | 	/* Important - remove from list _before_ done is called */ | 
 | 4200 | 	if (cmd_prev_ptr) | 
 | 4201 | 	    *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next; | 
 | 4202 |  | 
 | 4203 | 	--hostdata->busy[tmp->device->id][tmp->device->lun]; | 
 | 4204 | 	cmd->next = hostdata->free; | 
 | 4205 | 	hostdata->free = cmd; | 
 | 4206 |  | 
 | 4207 | 	tmp->host_scribble = NULL; | 
 | 4208 |  | 
 | 4209 | 	if (hostdata->options & OPTION_DEBUG_INTR) { | 
 | 4210 | 	    printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ",  | 
 | 4211 | 		  host->host_no, tmp->pid, tmp->device->id, tmp->device->lun, tmp->result); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 4212 | 	    __scsi_print_command (tmp->cmnd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4213 | 	} | 
 | 4214 |  | 
 | 4215 | 	tmp->scsi_done(tmp); | 
 | 4216 | 	goto restart; | 
 | 4217 |     } | 
 | 4218 |     local_irq_restore(flags); | 
 | 4219 |  | 
 | 4220 |     if (!search_found)  { | 
 | 4221 | 	printk ("scsi%d : WARNING : INTFLY with no completed commands.\n", | 
 | 4222 | 			    host->host_no); | 
 | 4223 |     } else { | 
 | 4224 | 	run_process_issue_queue(); | 
 | 4225 |     } | 
 | 4226 |     return; | 
 | 4227 | } | 
 | 4228 |  | 
 | 4229 | /* | 
 | 4230 |  * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) | 
 | 4231 |  * | 
 | 4232 |  * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing | 
 | 4233 |  *	the same IRQ line.   | 
 | 4234 |  *  | 
 | 4235 |  * Inputs : Since we're using the SA_INTERRUPT interrupt handler | 
 | 4236 |  *	semantics, irq indicates the interrupt which invoked  | 
 | 4237 |  *	this handler.   | 
 | 4238 |  * | 
 | 4239 |  * On the 710 we simualte an INTFLY with a script interrupt, and the | 
 | 4240 |  * script interrupt handler will call back to this function. | 
 | 4241 |  */ | 
 | 4242 |  | 
 | 4243 | static irqreturn_t | 
 | 4244 | NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) | 
 | 4245 | { | 
 | 4246 |     NCR53c7x0_local_declare(); | 
 | 4247 |     struct Scsi_Host *host;			/* Host we are looking at */ | 
 | 4248 |     unsigned char istat; 			/* Values of interrupt regs */ | 
 | 4249 |     struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */ | 
 | 4250 |     struct NCR53c7x0_cmd *cmd;			/* command which halted */ | 
 | 4251 |     u32 *dsa;					/* DSA */ | 
 | 4252 |     int handled = 0; | 
 | 4253 |  | 
 | 4254 | #ifdef NCR_DEBUG | 
 | 4255 |     char buf[80];				/* Debugging sprintf buffer */ | 
 | 4256 |     size_t buflen;				/* Length of same */ | 
 | 4257 | #endif | 
 | 4258 |  | 
 | 4259 |     host     = (struct Scsi_Host *)dev_id; | 
 | 4260 |     hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 4261 |     NCR53c7x0_local_setup(host); | 
 | 4262 |  | 
 | 4263 |     /* | 
 | 4264 |      * Only read istat once per loop, since reading it again will unstack | 
 | 4265 |      * interrupts | 
 | 4266 |      */ | 
 | 4267 |  | 
 | 4268 |     while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) { | 
 | 4269 | 	handled = 1; | 
 | 4270 | 	hostdata->dsp_changed = 0; | 
 | 4271 | 	hostdata->dstat_valid = 0; | 
 | 4272 |     	hostdata->state = STATE_HALTED; | 
 | 4273 |  | 
 | 4274 | 	if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK)  | 
 | 4275 | 	    printk ("scsi%d : SCSI FIFO not empty\n", host->host_no); | 
 | 4276 |  | 
 | 4277 | 	/* | 
 | 4278 | 	 * NCR53c700 and NCR53c700-66 change the current SCSI | 
 | 4279 | 	 * process, hostdata->ncrcurrent, in the Linux driver so | 
 | 4280 | 	 * cmd = hostdata->ncrcurrent. | 
 | 4281 | 	 * | 
 | 4282 | 	 * With other chips, we must look through the commands | 
 | 4283 | 	 * executing and find the command structure which  | 
 | 4284 | 	 * corresponds to the DSA register. | 
 | 4285 | 	 */ | 
 | 4286 |  | 
 | 4287 | 	if (hostdata->options & OPTION_700) { | 
 | 4288 | 	    cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent; | 
 | 4289 | 	} else { | 
 | 4290 | 	    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); | 
 | 4291 | 	    for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; | 
 | 4292 | 		cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa; | 
 | 4293 | 		    cmd = (struct NCR53c7x0_cmd *)(cmd->next)) | 
 | 4294 | 		; | 
 | 4295 | 	} | 
 | 4296 | 	if (hostdata->options & OPTION_DEBUG_INTR) { | 
 | 4297 | 	    if (cmd) { | 
 | 4298 | 		printk("scsi%d : interrupt for pid %lu, id %d, lun %d ",  | 
 | 4299 | 		    host->host_no, cmd->cmd->pid, (int) cmd->cmd->device->id, | 
 | 4300 | 		    (int) cmd->cmd->device->lun); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 4301 | 		__scsi_print_command (cmd->cmd->cmnd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 4302 | 	    } else { | 
 | 4303 | 		printk("scsi%d : no active command\n", host->host_no); | 
 | 4304 | 	    } | 
 | 4305 | 	} | 
 | 4306 | 	 | 
 | 4307 | 	if (istat & ISTAT_SIP) { | 
 | 4308 | 	    if (hostdata->options & OPTION_DEBUG_INTR)  | 
 | 4309 | 		printk ("scsi%d : ISTAT_SIP\n", host->host_no); | 
 | 4310 | 	    intr_scsi (host, cmd); | 
 | 4311 | 	} | 
 | 4312 | 	 | 
 | 4313 | 	if (istat & ISTAT_DIP) { | 
 | 4314 | 	    if (hostdata->options & OPTION_DEBUG_INTR)  | 
 | 4315 | 		printk ("scsi%d : ISTAT_DIP\n", host->host_no); | 
 | 4316 | 	    intr_dma (host, cmd); | 
 | 4317 | 	} | 
 | 4318 | 	 | 
 | 4319 | 	if (!hostdata->dstat_valid) { | 
 | 4320 | 	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); | 
 | 4321 | 	    hostdata->dstat_valid = 1; | 
 | 4322 | 	} | 
 | 4323 | 	 | 
 | 4324 | 	if (!(hostdata->dstat & DSTAT_DFE)) { | 
 | 4325 | 	    printk ("scsi%d : DMA FIFO not empty\n", host->host_no); | 
 | 4326 | 	    /* Really need to check this out for 710 RGH */ | 
 | 4327 | 	    NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF); | 
 | 4328 | 	    while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF) | 
 | 4329 | 		; | 
 | 4330 | 	    hostdata->dstat |= DSTAT_DFE; | 
 | 4331 | 	} | 
 | 4332 |  | 
 | 4333 | 	if (!hostdata->idle && hostdata->state == STATE_HALTED) { | 
 | 4334 | 	    if (!hostdata->dsp_changed) | 
 | 4335 | 		hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG)); | 
 | 4336 | #if 0 | 
 | 4337 | 	    printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n", | 
 | 4338 | 		host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp); | 
 | 4339 | #endif | 
 | 4340 | 		 | 
 | 4341 | 	    hostdata->state = STATE_RUNNING; | 
 | 4342 | 	    NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp)); | 
 | 4343 | 	    if (hostdata->options & OPTION_DEBUG_TRACE) { | 
 | 4344 | #ifdef CYCLIC_TRACE | 
 | 4345 | 		log_insn (hostdata->dsp); | 
 | 4346 | #else | 
 | 4347 | 	    	print_insn (host, hostdata->dsp, "t ", 1); | 
 | 4348 | #endif | 
 | 4349 | 		NCR53c7x0_write8 (DCNTL_REG, | 
 | 4350 | 			hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD); | 
 | 4351 | 	    } | 
 | 4352 | 	} | 
 | 4353 |     } | 
 | 4354 |     return IRQ_HANDLED; | 
 | 4355 | } | 
 | 4356 |  | 
 | 4357 |  | 
 | 4358 | /*  | 
 | 4359 |  * Function : static int abort_connected (struct Scsi_Host *host) | 
 | 4360 |  * | 
 | 4361 |  * Purpose : Assuming that the NCR SCSI processor is currently  | 
 | 4362 |  * 	halted, break the currently established nexus.  Clean | 
 | 4363 |  *	up of the NCR53c7x0_cmd and Scsi_Cmnd structures should | 
 | 4364 |  *	be done on receipt of the abort interrupt. | 
 | 4365 |  * | 
 | 4366 |  * Inputs : host - SCSI host | 
 | 4367 |  * | 
 | 4368 |  */ | 
 | 4369 |  | 
 | 4370 | static int  | 
 | 4371 | abort_connected (struct Scsi_Host *host) { | 
 | 4372 | #ifdef NEW_ABORT | 
 | 4373 |     NCR53c7x0_local_declare(); | 
 | 4374 | #endif | 
 | 4375 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 4376 | 	host->hostdata[0]; | 
 | 4377 | /* FIXME : this probably should change for production kernels; at the  | 
 | 4378 |    least, counter should move to a per-host structure. */ | 
 | 4379 |     static int counter = 5; | 
 | 4380 | #ifdef NEW_ABORT | 
 | 4381 |     int sstat, phase, offset; | 
 | 4382 |     u32 *script; | 
 | 4383 |     NCR53c7x0_local_setup(host); | 
 | 4384 | #endif | 
 | 4385 |  | 
 | 4386 |     if (--counter <= 0) { | 
 | 4387 | 	disable(host); | 
 | 4388 | 	return 0; | 
 | 4389 |     } | 
 | 4390 |  | 
 | 4391 |     printk ("scsi%d : DANGER : abort_connected() called \n", | 
 | 4392 | 	host->host_no); | 
 | 4393 |  | 
 | 4394 | #ifdef NEW_ABORT | 
 | 4395 |  | 
 | 4396 | /* | 
 | 4397 |  * New strategy : Rather than using a generic abort routine, | 
 | 4398 |  * we'll specifically try to source or sink the appropriate | 
 | 4399 |  * amount of data for the phase we're currently in (taking into  | 
 | 4400 |  * account the current synchronous offset)  | 
 | 4401 |  */ | 
 | 4402 |  | 
 | 4403 |     sstat = (NCR53c8x0_read8 (SSTAT2_REG); | 
 | 4404 |     offset = OFFSET (sstat & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; | 
 | 4405 |     phase = sstat & SSTAT2_PHASE_MASK; | 
 | 4406 |  | 
 | 4407 | /* | 
 | 4408 |  * SET ATN | 
 | 4409 |  * MOVE source_or_sink, WHEN CURRENT PHASE  | 
 | 4410 |  * < repeat for each outstanding byte > | 
 | 4411 |  * JUMP send_abort_message | 
 | 4412 |  */ | 
 | 4413 |  | 
 | 4414 |     script = hostdata->abort_script = kmalloc ( | 
 | 4415 | 	8  /* instruction size */ * ( | 
 | 4416 | 	    1 /* set ATN */ + | 
 | 4417 | 	    (!offset ? 1 : offset) /* One transfer per outstanding byte */ + | 
 | 4418 | 	    1 /* send abort message */), | 
 | 4419 | 	GFP_ATOMIC); | 
 | 4420 |  | 
 | 4421 |  | 
 | 4422 | #else /* def NEW_ABORT */ | 
 | 4423 |     hostdata->dsp = hostdata->script + hostdata->E_initiator_abort / | 
 | 4424 | 	    sizeof(u32); | 
 | 4425 | #endif /* def NEW_ABORT */ | 
 | 4426 |     hostdata->dsp_changed = 1; | 
 | 4427 |  | 
 | 4428 | /* XXX - need to flag the command as aborted after the abort_connected | 
 | 4429 |  	 code runs  | 
 | 4430 |  */ | 
 | 4431 |     return 0; | 
 | 4432 | } | 
 | 4433 |  | 
 | 4434 | /* | 
 | 4435 |  * Function : static int datapath_residual (Scsi_Host *host) | 
 | 4436 |  * | 
 | 4437 |  * Purpose : return residual data count of what's in the chip. | 
 | 4438 |  * | 
 | 4439 |  * Inputs : host - SCSI host | 
 | 4440 |  */ | 
 | 4441 |  | 
 | 4442 | static int | 
 | 4443 | datapath_residual (struct Scsi_Host *host) { | 
 | 4444 |     NCR53c7x0_local_declare(); | 
 | 4445 |     int count, synchronous, sstat; | 
 | 4446 |     unsigned int ddir; | 
 | 4447 |  | 
 | 4448 |     NCR53c7x0_local_setup(host); | 
 | 4449 |     /* COMPAT : the 700 and 700-66 need to use DFIFO_00_BO_MASK */ | 
 | 4450 |     count = ((NCR53c7x0_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) - | 
 | 4451 | 	(NCR53c7x0_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK; | 
 | 4452 |     synchronous = NCR53c7x0_read8 (SXFER_REG) & SXFER_MO_MASK; | 
 | 4453 |     /* COMPAT : DDIR is elsewhere on non-'8xx chips. */ | 
 | 4454 |     ddir = NCR53c7x0_read8 (CTEST0_REG_700) & CTEST0_700_DDIR; | 
 | 4455 |  | 
 | 4456 |     if (ddir) { | 
 | 4457 |     /* Receive */ | 
 | 4458 | 	if (synchronous)  | 
 | 4459 | 	    count += (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT; | 
 | 4460 | 	else | 
 | 4461 | 	    if (NCR53c7x0_read8 (SSTAT1_REG) & SSTAT1_ILF) | 
 | 4462 | 		++count; | 
 | 4463 |     } else { | 
 | 4464 |     /* Send */ | 
 | 4465 | 	sstat = NCR53c7x0_read8 (SSTAT1_REG); | 
 | 4466 | 	if (sstat & SSTAT1_OLF) | 
 | 4467 | 	    ++count; | 
 | 4468 | 	if (synchronous && (sstat & SSTAT1_ORF)) | 
 | 4469 | 	    ++count; | 
 | 4470 |     } | 
 | 4471 |     return count; | 
 | 4472 | } | 
 | 4473 |  | 
 | 4474 | /*  | 
 | 4475 |  * Function : static const char * sbcl_to_phase (int sbcl)_ | 
 | 4476 |  * | 
 | 4477 |  * Purpose : Convert SBCL register to user-parsable phase representation | 
 | 4478 |  * | 
 | 4479 |  * Inputs : sbcl - value of sbcl register | 
 | 4480 |  */ | 
 | 4481 |  | 
 | 4482 |  | 
 | 4483 | static const char * | 
 | 4484 | sbcl_to_phase (int sbcl) { | 
 | 4485 |     switch (sbcl & SBCL_PHASE_MASK) { | 
 | 4486 |     case SBCL_PHASE_DATAIN: | 
 | 4487 | 	return "DATAIN"; | 
 | 4488 |     case SBCL_PHASE_DATAOUT: | 
 | 4489 | 	return "DATAOUT"; | 
 | 4490 |     case SBCL_PHASE_MSGIN: | 
 | 4491 | 	return "MSGIN"; | 
 | 4492 |     case SBCL_PHASE_MSGOUT: | 
 | 4493 | 	return "MSGOUT"; | 
 | 4494 |     case SBCL_PHASE_CMDOUT: | 
 | 4495 | 	return "CMDOUT"; | 
 | 4496 |     case SBCL_PHASE_STATIN: | 
 | 4497 | 	return "STATUSIN"; | 
 | 4498 |     default: | 
 | 4499 | 	return "unknown"; | 
 | 4500 |     } | 
 | 4501 | } | 
 | 4502 |  | 
 | 4503 | /*  | 
 | 4504 |  * Function : static const char * sstat2_to_phase (int sstat)_ | 
 | 4505 |  * | 
 | 4506 |  * Purpose : Convert SSTAT2 register to user-parsable phase representation | 
 | 4507 |  * | 
 | 4508 |  * Inputs : sstat - value of sstat register | 
 | 4509 |  */ | 
 | 4510 |  | 
 | 4511 |  | 
 | 4512 | static const char * | 
 | 4513 | sstat2_to_phase (int sstat) { | 
 | 4514 |     switch (sstat & SSTAT2_PHASE_MASK) { | 
 | 4515 |     case SSTAT2_PHASE_DATAIN: | 
 | 4516 | 	return "DATAIN"; | 
 | 4517 |     case SSTAT2_PHASE_DATAOUT: | 
 | 4518 | 	return "DATAOUT"; | 
 | 4519 |     case SSTAT2_PHASE_MSGIN: | 
 | 4520 | 	return "MSGIN"; | 
 | 4521 |     case SSTAT2_PHASE_MSGOUT: | 
 | 4522 | 	return "MSGOUT"; | 
 | 4523 |     case SSTAT2_PHASE_CMDOUT: | 
 | 4524 | 	return "CMDOUT"; | 
 | 4525 |     case SSTAT2_PHASE_STATIN: | 
 | 4526 | 	return "STATUSIN"; | 
 | 4527 |     default: | 
 | 4528 | 	return "unknown"; | 
 | 4529 |     } | 
 | 4530 | } | 
 | 4531 |  | 
 | 4532 | /*  | 
 | 4533 |  * Function : static void intr_phase_mismatch (struct Scsi_Host *host,  | 
 | 4534 |  *	struct NCR53c7x0_cmd *cmd) | 
 | 4535 |  * | 
 | 4536 |  * Purpose : Handle phase mismatch interrupts | 
 | 4537 |  * | 
 | 4538 |  * Inputs : host, cmd - host and NCR command causing the interrupt, cmd | 
 | 4539 |  * 	may be NULL. | 
 | 4540 |  * | 
 | 4541 |  * Side effects : The abort_connected() routine is called or the NCR chip  | 
 | 4542 |  *	is restarted, jumping to the command_complete entry point, or  | 
 | 4543 |  *	patching the address and transfer count of the current instruction  | 
 | 4544 |  *	and calling the msg_in entry point as appropriate. | 
 | 4545 |  */ | 
 | 4546 |  | 
 | 4547 | static void  | 
 | 4548 | intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { | 
 | 4549 |     NCR53c7x0_local_declare(); | 
 | 4550 |     u32 dbc_dcmd, *dsp, *dsp_next; | 
 | 4551 |     unsigned char dcmd, sbcl; | 
 | 4552 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 4553 |     	host->hostdata[0]; | 
 | 4554 |     int residual; | 
 | 4555 |     enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action =  | 
 | 4556 | 	ACTION_ABORT_PRINT; | 
 | 4557 |     const char *where = NULL; | 
 | 4558 |  | 
 | 4559 |     NCR53c7x0_local_setup(host); | 
 | 4560 |  | 
 | 4561 |     /* | 
 | 4562 |      * Corrective action is based on where in the SCSI SCRIPT(tm) the error  | 
 | 4563 |      * occurred, as well as which SCSI phase we are currently in. | 
 | 4564 |      */ | 
 | 4565 |     dsp_next = bus_to_virt(NCR53c7x0_read32(DSP_REG)); | 
 | 4566 |  | 
 | 4567 |     /*  | 
 | 4568 |      * Fetch the current instruction, and remove the operands for easier  | 
 | 4569 |      * interpretation. | 
 | 4570 |      */ | 
 | 4571 |     dbc_dcmd = NCR53c7x0_read32(DBC_REG); | 
 | 4572 |     dcmd = (dbc_dcmd & 0xff000000) >> 24; | 
 | 4573 |     /* | 
 | 4574 |      * Like other processors, the NCR adjusts the instruction pointer before | 
 | 4575 |      * instruction decode.  Set the DSP address back to what it should | 
 | 4576 |      * be for this instruction based on its size (2 or 3 32 bit words). | 
 | 4577 |      */ | 
 | 4578 |     dsp = dsp_next - NCR53c7x0_insn_size(dcmd); | 
 | 4579 |  | 
 | 4580 |  | 
 | 4581 |     /* | 
 | 4582 |      * Read new SCSI phase from the SBCL lines.  Since all of our code uses  | 
 | 4583 |      * a WHEN conditional instead of an IF conditional, we don't need to  | 
 | 4584 |      * wait for a new REQ. | 
 | 4585 |      */ | 
 | 4586 |     sbcl = NCR53c7x0_read8(SBCL_REG) & SBCL_PHASE_MASK; | 
 | 4587 |  | 
 | 4588 |     if (!cmd) { | 
 | 4589 | 	action = ACTION_ABORT_PRINT; | 
 | 4590 | 	where = "no current command"; | 
 | 4591 |     /* | 
 | 4592 |      * The way my SCSI SCRIPTS(tm) are architected, recoverable phase | 
 | 4593 |      * mismatches should only occur where we're doing a multi-byte   | 
 | 4594 |      * BMI instruction.  Specifically, this means  | 
 | 4595 |      * | 
 | 4596 |      *  - select messages (a SCSI-I target may ignore additional messages | 
 | 4597 |      * 		after the IDENTIFY; any target may reject a SDTR or WDTR) | 
 | 4598 |      * | 
 | 4599 |      *  - command out (targets may send a message to signal an error  | 
 | 4600 |      * 		condition, or go into STATUSIN after they've decided  | 
 | 4601 |      *		they don't like the command. | 
 | 4602 |      * | 
 | 4603 |      *	- reply_message (targets may reject a multi-byte message in the  | 
 | 4604 |      *		middle) | 
 | 4605 |      * | 
 | 4606 |      * 	- data transfer routines (command completion with buffer space | 
 | 4607 |      *		left, disconnect message, or error message) | 
 | 4608 |      */ | 
 | 4609 |     } else if (((dsp >= cmd->data_transfer_start &&  | 
 | 4610 | 	dsp < cmd->data_transfer_end)) || dsp == (cmd->residual + 2)) { | 
 | 4611 | 	if ((dcmd & (DCMD_TYPE_MASK|DCMD_BMI_OP_MASK|DCMD_BMI_INDIRECT| | 
 | 4612 | 		DCMD_BMI_MSG|DCMD_BMI_CD)) == (DCMD_TYPE_BMI| | 
 | 4613 | 		DCMD_BMI_OP_MOVE_I)) { | 
 | 4614 | 	    residual = datapath_residual (host); | 
 | 4615 | 	    if (hostdata->options & OPTION_DEBUG_DISCONNECT) | 
 | 4616 | 	    	printk ("scsi%d : handling residual transfer (+ %d bytes from DMA FIFO)\n",  | 
 | 4617 | 		    host->host_no, residual); | 
 | 4618 |  | 
 | 4619 | 	    /* | 
 | 4620 | 	     * The first instruction is a CALL to the alternate handler for  | 
 | 4621 | 	     * this data transfer phase, so we can do calls to  | 
 | 4622 | 	     * munge_msg_restart as we would if control were passed  | 
 | 4623 | 	     * from normal dynamic code. | 
 | 4624 | 	     */ | 
 | 4625 | 	    if (dsp != cmd->residual + 2) { | 
 | 4626 | 		cmd->residual[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | | 
 | 4627 | 			((dcmd & DCMD_BMI_IO) ? DCMD_TCI_IO : 0)) << 24) |  | 
 | 4628 | 		    DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE; | 
 | 4629 | 		cmd->residual[1] = virt_to_bus(hostdata->script) | 
 | 4630 | 		    + ((dcmd & DCMD_BMI_IO) | 
 | 4631 | 		       ? hostdata->E_other_in : hostdata->E_other_out); | 
 | 4632 | 	    } | 
 | 4633 |  | 
 | 4634 | 	    /* | 
 | 4635 | 	     * The second instruction is the a data transfer block | 
 | 4636 | 	     * move instruction, reflecting the pointer and count at the  | 
 | 4637 | 	     * time of the phase mismatch. | 
 | 4638 | 	     */ | 
 | 4639 | 	    cmd->residual[2] = dbc_dcmd + residual; | 
 | 4640 | 	    cmd->residual[3] = NCR53c7x0_read32(DNAD_REG) - residual; | 
 | 4641 |  | 
 | 4642 | 	    /* | 
 | 4643 | 	     * The third and final instruction is a jump to the instruction | 
 | 4644 | 	     * which follows the instruction which had to be 'split' | 
 | 4645 | 	     */ | 
 | 4646 | 	    if (dsp != cmd->residual + 2) { | 
 | 4647 | 		cmd->residual[4] = ((DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP)  | 
 | 4648 | 		    << 24) | DBC_TCI_TRUE; | 
 | 4649 | 		cmd->residual[5] = virt_to_bus(dsp_next); | 
 | 4650 | 	    } | 
 | 4651 |  | 
 | 4652 | 	    /* | 
 | 4653 | 	     * For the sake of simplicity, transfer control to the  | 
 | 4654 | 	     * conditional CALL at the start of the residual buffer. | 
 | 4655 | 	     */ | 
 | 4656 | 	    hostdata->dsp = cmd->residual; | 
 | 4657 | 	    hostdata->dsp_changed = 1; | 
 | 4658 | 	    action = ACTION_CONTINUE; | 
 | 4659 | 	} else { | 
 | 4660 | 	    where = "non-BMI dynamic DSA code"; | 
 | 4661 | 	    action = ACTION_ABORT_PRINT; | 
 | 4662 | 	} | 
 | 4663 |     } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4 + 2)) { | 
 | 4664 | 	/* RGH 290697:  Added +2 above, to compensate for the script | 
 | 4665 | 	 * instruction which disables the selection timer. */ | 
 | 4666 | 	/* Release ATN */ | 
 | 4667 | 	NCR53c7x0_write8 (SOCL_REG, 0); | 
 | 4668 | 	switch (sbcl) { | 
 | 4669 |     /*  | 
 | 4670 |      * Some devices (SQ555 come to mind) grab the IDENTIFY message | 
 | 4671 |      * sent on selection, and decide to go into COMMAND OUT phase | 
 | 4672 |      * rather than accepting the rest of the messages or rejecting | 
 | 4673 |      * them.  Handle these devices gracefully. | 
 | 4674 |      */ | 
 | 4675 | 	case SBCL_PHASE_CMDOUT: | 
 | 4676 | 	    hostdata->dsp = dsp + 2 /* two _words_ */; | 
 | 4677 | 	    hostdata->dsp_changed = 1; | 
 | 4678 | 	    printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n",  | 
 | 4679 | 		host->host_no, cmd->cmd->device->id); | 
 | 4680 | 	    cmd->flags &= ~CMD_FLAG_SDTR; | 
 | 4681 | 	    action = ACTION_CONTINUE; | 
 | 4682 | 	    break; | 
 | 4683 | 	case SBCL_PHASE_MSGIN: | 
 | 4684 | 	    hostdata->dsp = hostdata->script + hostdata->E_msg_in /  | 
 | 4685 | 		sizeof(u32); | 
 | 4686 | 	    hostdata->dsp_changed = 1; | 
 | 4687 | 	    action = ACTION_CONTINUE; | 
 | 4688 | 	    break; | 
 | 4689 | 	default: | 
 | 4690 | 	    where="select message out"; | 
 | 4691 | 	    action = ACTION_ABORT_PRINT; | 
 | 4692 | 	} | 
 | 4693 |     /* | 
 | 4694 |      * Some SCSI devices will interpret a command as they read the bytes | 
 | 4695 |      * off the SCSI bus, and may decide that the command is Bogus before  | 
 | 4696 |      * they've read the entire command off the bus. | 
 | 4697 |      */ | 
 | 4698 |     } else if (dsp == hostdata->script + hostdata->E_cmdout_cmdout / sizeof  | 
 | 4699 | 	(u32)) { | 
 | 4700 | 	hostdata->dsp = hostdata->script + hostdata->E_data_transfer / | 
 | 4701 | 	    sizeof (u32); | 
 | 4702 | 	hostdata->dsp_changed = 1; | 
 | 4703 | 	action = ACTION_CONTINUE; | 
 | 4704 |     /* FIXME : we need to handle message reject, etc. within msg_respond. */ | 
 | 4705 | #ifdef notyet | 
 | 4706 |     } else if (dsp == hostdata->script + hostdata->E_reply_message) { | 
 | 4707 | 	switch (sbcl) { | 
 | 4708 |     /* Any other phase mismatches abort the currently executing command.  */ | 
 | 4709 | #endif | 
 | 4710 |     } else { | 
 | 4711 | 	where = "unknown location"; | 
 | 4712 | 	action = ACTION_ABORT_PRINT; | 
 | 4713 |     } | 
 | 4714 |  | 
 | 4715 |     /* Flush DMA FIFO */ | 
 | 4716 |     if (!hostdata->dstat_valid) { | 
 | 4717 | 	hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); | 
 | 4718 | 	hostdata->dstat_valid = 1; | 
 | 4719 |     } | 
 | 4720 |     if (!(hostdata->dstat & DSTAT_DFE)) { | 
 | 4721 |       /* Really need to check this out for 710 RGH */ | 
 | 4722 |       NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF); | 
 | 4723 |       while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF); | 
 | 4724 |       hostdata->dstat |= DSTAT_DFE; | 
 | 4725 |     } | 
 | 4726 |  | 
 | 4727 |     switch (action) { | 
 | 4728 |     case ACTION_ABORT_PRINT: | 
 | 4729 | 	printk("scsi%d : %s : unexpected phase %s.\n", | 
 | 4730 | 	     host->host_no, where ? where : "unknown location",  | 
 | 4731 | 	     sbcl_to_phase(sbcl)); | 
 | 4732 | 	print_lots (host); | 
 | 4733 |     /* Fall through to ACTION_ABORT */ | 
 | 4734 |     case ACTION_ABORT: | 
 | 4735 | 	abort_connected (host); | 
 | 4736 | 	break; | 
 | 4737 |     case ACTION_CONTINUE: | 
 | 4738 | 	break; | 
 | 4739 |     } | 
 | 4740 |  | 
 | 4741 | #if 0 | 
 | 4742 |     if (hostdata->dsp_changed) { | 
 | 4743 | 	printk("scsi%d: new dsp 0x%p\n", host->host_no, hostdata->dsp); | 
 | 4744 | 	print_insn (host, hostdata->dsp, "", 1); | 
 | 4745 |     } | 
 | 4746 | #endif | 
 | 4747 | } | 
 | 4748 |  | 
 | 4749 | /* | 
 | 4750 |  * Function : static void intr_bf (struct Scsi_Host *host,  | 
 | 4751 |  * 	struct NCR53c7x0_cmd *cmd) | 
 | 4752 |  * | 
 | 4753 |  * Purpose : handle BUS FAULT interrupts  | 
 | 4754 |  * | 
 | 4755 |  * Inputs : host, cmd - host and NCR command causing the interrupt, cmd | 
 | 4756 |  * 	may be NULL. | 
 | 4757 |  */ | 
 | 4758 |  | 
 | 4759 | static void | 
 | 4760 | intr_bf (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { | 
 | 4761 |     NCR53c7x0_local_declare(); | 
 | 4762 |     u32 *dsp, | 
 | 4763 | 	*next_dsp,		/* Current dsp */ | 
 | 4764 |     	*dsa, | 
 | 4765 | 	dbc_dcmd;		/* DCMD (high eight bits) + DBC */ | 
 | 4766 |     char *reason = NULL; | 
 | 4767 |     /* Default behavior is for a silent error, with a retry until we've | 
 | 4768 |        exhausted retries. */ | 
 | 4769 |     enum {MAYBE, ALWAYS, NEVER} retry = MAYBE; | 
 | 4770 |     int report = 0; | 
 | 4771 |     NCR53c7x0_local_setup(host); | 
 | 4772 |  | 
 | 4773 |     dbc_dcmd = NCR53c7x0_read32 (DBC_REG); | 
 | 4774 |     next_dsp = bus_to_virt (NCR53c7x0_read32(DSP_REG)); | 
 | 4775 |     dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff); | 
 | 4776 | /* FIXME - check chip type  */ | 
 | 4777 |     dsa = bus_to_virt (NCR53c7x0_read32(DSA_REG)); | 
 | 4778 |  | 
 | 4779 |     /* | 
 | 4780 |      * Bus faults can be caused by either a Bad Address or  | 
 | 4781 |      * Target Abort. We should check the Received Target Abort | 
 | 4782 |      * bit of the PCI status register and Master Abort Bit. | 
 | 4783 |      * | 
 | 4784 |      * 	- Master Abort bit indicates that no device claimed | 
 | 4785 |      *		the address with DEVSEL within five clocks | 
 | 4786 |      * | 
 | 4787 |      *	- Target Abort bit indicates that a target claimed it, | 
 | 4788 |      *		but changed its mind once it saw the byte enables. | 
 | 4789 |      * | 
 | 4790 |      */ | 
 | 4791 |  | 
 | 4792 |     /* 53c710, not PCI system */ | 
 | 4793 |     report = 1; | 
 | 4794 |     reason = "Unknown"; | 
 | 4795 |  | 
 | 4796 | #ifndef notyet | 
 | 4797 |     report = 1; | 
 | 4798 | #endif | 
 | 4799 |     if (report && reason) | 
 | 4800 |     { | 
 | 4801 | 	printk(KERN_ALERT "scsi%d : BUS FAULT reason = %s\n", | 
 | 4802 | 	     host->host_no, reason ? reason : "unknown"); | 
 | 4803 | 	print_lots (host); | 
 | 4804 |     } | 
 | 4805 |  | 
 | 4806 | #ifndef notyet | 
 | 4807 |     retry = NEVER; | 
 | 4808 | #endif | 
 | 4809 |  | 
 | 4810 |     /*  | 
 | 4811 |      * TODO : we should attempt to recover from any spurious bus  | 
 | 4812 |      * faults.  After X retries, we should figure that things are  | 
 | 4813 |      * sufficiently wedged, and call NCR53c7xx_reset. | 
 | 4814 |      * | 
 | 4815 |      * This code should only get executed once we've decided that we  | 
 | 4816 |      * cannot retry. | 
 | 4817 |      */ | 
 | 4818 |  | 
 | 4819 |     if (retry == NEVER) { | 
 | 4820 |     	printk(KERN_ALERT "          mail richard@sleepie.demon.co.uk\n"); | 
 | 4821 |     	FATAL (host); | 
 | 4822 |     } | 
 | 4823 | } | 
 | 4824 |  | 
 | 4825 | /* | 
 | 4826 |  * Function : static void intr_dma (struct Scsi_Host *host,  | 
 | 4827 |  * 	struct NCR53c7x0_cmd *cmd) | 
 | 4828 |  * | 
 | 4829 |  * Purpose : handle all DMA interrupts, indicated by the setting  | 
 | 4830 |  * 	of the DIP bit in the ISTAT register. | 
 | 4831 |  * | 
 | 4832 |  * Inputs : host, cmd - host and NCR command causing the interrupt, cmd | 
 | 4833 |  * 	may be NULL. | 
 | 4834 |  */ | 
 | 4835 |  | 
 | 4836 | static void  | 
 | 4837 | intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { | 
 | 4838 |     NCR53c7x0_local_declare(); | 
 | 4839 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 4840 | 	host->hostdata[0]; | 
 | 4841 |     unsigned char dstat;	/* DSTAT */	 | 
 | 4842 |     u32 *dsp, | 
 | 4843 | 	*next_dsp,		/* Current dsp */ | 
 | 4844 |     	*dsa, | 
 | 4845 | 	dbc_dcmd;		/* DCMD (high eight bits) + DBC */ | 
 | 4846 |     int tmp; | 
 | 4847 |     unsigned long flags; | 
 | 4848 |     NCR53c7x0_local_setup(host); | 
 | 4849 |  | 
 | 4850 |     if (!hostdata->dstat_valid) { | 
 | 4851 | 	hostdata->dstat = NCR53c7x0_read8(DSTAT_REG); | 
 | 4852 | 	hostdata->dstat_valid = 1; | 
 | 4853 |     } | 
 | 4854 |      | 
 | 4855 |     dstat = hostdata->dstat; | 
 | 4856 |      | 
 | 4857 |     if (hostdata->options & OPTION_DEBUG_INTR) | 
 | 4858 | 	printk("scsi%d : DSTAT=0x%x\n", host->host_no, (int) dstat); | 
 | 4859 |  | 
 | 4860 |     dbc_dcmd = NCR53c7x0_read32 (DBC_REG); | 
 | 4861 |     next_dsp = bus_to_virt(NCR53c7x0_read32(DSP_REG)); | 
 | 4862 |     dsp = next_dsp - NCR53c7x0_insn_size ((dbc_dcmd >> 24) & 0xff); | 
 | 4863 | /* XXX - check chip type */ | 
 | 4864 |     dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); | 
 | 4865 |  | 
 | 4866 |     /* | 
 | 4867 |      * DSTAT_ABRT is the aborted interrupt.  This is set whenever the  | 
 | 4868 |      * SCSI chip is aborted.   | 
 | 4869 |      *  | 
 | 4870 |      * With NCR53c700 and NCR53c700-66 style chips, we should only  | 
 | 4871 |      * get this when the chip is currently running the accept  | 
 | 4872 |      * reselect/select code and we have set the abort bit in the  | 
 | 4873 |      * ISTAT register. | 
 | 4874 |      * | 
 | 4875 |      */ | 
 | 4876 |      | 
 | 4877 |     if (dstat & DSTAT_ABRT) { | 
 | 4878 | #if 0 | 
 | 4879 | 	/* XXX - add code here to deal with normal abort */ | 
 | 4880 | 	if ((hostdata->options & OPTION_700) && (hostdata->state == | 
 | 4881 | 	    STATE_ABORTING)) { | 
 | 4882 | 	} else  | 
 | 4883 | #endif | 
 | 4884 | 	{ | 
 | 4885 | 	    printk(KERN_ALERT "scsi%d : unexpected abort interrupt at\n"  | 
 | 4886 | 		   "         ", host->host_no); | 
 | 4887 | 	    print_insn (host, dsp, KERN_ALERT "s ", 1); | 
 | 4888 | 	    FATAL (host); | 
 | 4889 | 	} | 
 | 4890 |     } | 
 | 4891 |  | 
 | 4892 |     /* | 
 | 4893 |      * DSTAT_SSI is the single step interrupt.  Should be generated  | 
 | 4894 |      * whenever we have single stepped or are tracing. | 
 | 4895 |      */ | 
 | 4896 |  | 
 | 4897 |     if (dstat & DSTAT_SSI) { | 
 | 4898 | 	if (hostdata->options & OPTION_DEBUG_TRACE) { | 
 | 4899 | 	    /* Don't print instr. until we write DSP at end of intr function */ | 
 | 4900 | 	} else if (hostdata->options & OPTION_DEBUG_SINGLE) { | 
 | 4901 | 	    print_insn (host, dsp, "s ", 0); | 
 | 4902 | 	    local_irq_save(flags); | 
 | 4903 | /* XXX - should we do this, or can we get away with writing dsp? */ | 
 | 4904 |  | 
 | 4905 | 	    NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) &  | 
 | 4906 |     	    	~DCNTL_SSM) | DCNTL_STD); | 
 | 4907 | 	    local_irq_restore(flags); | 
 | 4908 | 	} else { | 
 | 4909 | 	    printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n" | 
 | 4910 | 		   "         ", host->host_no); | 
 | 4911 | 	    print_insn (host, dsp, KERN_ALERT "", 1); | 
 | 4912 | 	    printk(KERN_ALERT "         mail drew@PoohSticks.ORG\n"); | 
 | 4913 |     	    FATAL (host); | 
 | 4914 |     	} | 
 | 4915 |     } | 
 | 4916 |  | 
 | 4917 |     /* | 
 | 4918 |      * DSTAT_IID / DSTAT_OPC (same bit, same meaning, only the name  | 
 | 4919 |      * is different) is generated whenever an illegal instruction is  | 
 | 4920 |      * encountered.   | 
 | 4921 |      *  | 
 | 4922 |      * XXX - we may want to emulate INTFLY here, so we can use  | 
 | 4923 |      *    the same SCSI SCRIPT (tm) for NCR53c710 through NCR53c810   | 
 | 4924 |      *	  chips. | 
 | 4925 |      */ | 
 | 4926 |  | 
 | 4927 |     if (dstat & DSTAT_OPC) { | 
 | 4928 |     /*  | 
 | 4929 |      * Ascertain if this IID interrupts occurred before or after a STO  | 
 | 4930 |      * interrupt.  Since the interrupt handling code now leaves  | 
 | 4931 |      * DSP unmodified until _after_ all stacked interrupts have been | 
 | 4932 |      * processed, reading the DSP returns the original DSP register. | 
 | 4933 |      * This means that if dsp lies between the select code, and  | 
 | 4934 |      * message out following the selection code (where the IID interrupt | 
 | 4935 |      * would have to have occurred by due to the implicit wait for REQ), | 
 | 4936 |      * we have an IID interrupt resulting from a STO condition and  | 
 | 4937 |      * can ignore it. | 
 | 4938 |      */ | 
 | 4939 |  | 
 | 4940 | 	if (((dsp >= (hostdata->script + hostdata->E_select / sizeof(u32))) && | 
 | 4941 | 	    (dsp <= (hostdata->script + hostdata->E_select_msgout /  | 
 | 4942 |     	    sizeof(u32) + 8))) || (hostdata->test_running == 2)) { | 
 | 4943 | 	    if (hostdata->options & OPTION_DEBUG_INTR)  | 
 | 4944 | 		printk ("scsi%d : ignoring DSTAT_IID for SSTAT_STO\n", | 
 | 4945 | 		    host->host_no); | 
 | 4946 | 	    if (hostdata->expecting_iid) { | 
 | 4947 | 		hostdata->expecting_iid = 0; | 
 | 4948 | 		hostdata->idle = 1; | 
 | 4949 | 		if (hostdata->test_running == 2) { | 
 | 4950 | 		    hostdata->test_running = 0; | 
 | 4951 | 		    hostdata->test_completed = 3; | 
 | 4952 | 		} else if (cmd)  | 
 | 4953 | 			abnormal_finished (cmd, DID_BAD_TARGET << 16); | 
 | 4954 | 	    } else { | 
 | 4955 | 		hostdata->expecting_sto = 1; | 
 | 4956 | 	    } | 
 | 4957 |     /* | 
 | 4958 |      * We can't guarantee we'll be able to execute the WAIT DISCONNECT | 
 | 4959 |      * instruction within the 3.4us of bus free and arbitration delay | 
 | 4960 |      * that a target can RESELECT in and assert REQ after we've dropped | 
 | 4961 |      * ACK.  If this happens, we'll get an illegal instruction interrupt. | 
 | 4962 |      * Doing away with the WAIT DISCONNECT instructions broke everything, | 
 | 4963 |      * so instead I'll settle for moving one WAIT DISCONNECT a few  | 
 | 4964 |      * instructions closer to the CLEAR ACK before it to minimize the | 
 | 4965 |      * chances of this happening, and handle it if it occurs anyway. | 
 | 4966 |      * | 
 | 4967 |      * Simply continue with what we were doing, and control should | 
 | 4968 |      * be transferred to the schedule routine which will ultimately | 
 | 4969 |      * pass control onto the reselection or selection (not yet) | 
 | 4970 |      * code. | 
 | 4971 |      */ | 
 | 4972 | 	} else if (dbc_dcmd == 0x48000000 && (NCR53c7x0_read8 (SBCL_REG) & | 
 | 4973 | 	    SBCL_REQ)) { | 
 | 4974 | 	    if (!(hostdata->options & OPTION_NO_PRINT_RACE)) | 
 | 4975 | 	    { | 
 | 4976 | 		printk("scsi%d: REQ before WAIT DISCONNECT IID\n",  | 
 | 4977 | 		    host->host_no); | 
 | 4978 | 		hostdata->options |= OPTION_NO_PRINT_RACE; | 
 | 4979 | 	    } | 
 | 4980 | 	} else { | 
 | 4981 | 	    printk(KERN_ALERT "scsi%d : invalid instruction\n", host->host_no); | 
 | 4982 | 	    print_lots (host); | 
 | 4983 | 	    printk(KERN_ALERT "         mail Richard@sleepie.demon.co.uk with ALL\n" | 
 | 4984 | 		              "         boot messages and diagnostic output\n"); | 
 | 4985 |     	    FATAL (host); | 
 | 4986 | 	} | 
 | 4987 |     } | 
 | 4988 |  | 
 | 4989 |     /*  | 
 | 4990 |      * DSTAT_BF are bus fault errors.  DSTAT_800_BF is valid for 710 also. | 
 | 4991 |      */ | 
 | 4992 |      | 
 | 4993 |     if (dstat & DSTAT_800_BF) { | 
 | 4994 | 	intr_bf (host, cmd); | 
 | 4995 |     } | 
 | 4996 | 	 | 
 | 4997 |  | 
 | 4998 |     /*  | 
 | 4999 |      * DSTAT_SIR interrupts are generated by the execution of  | 
 | 5000 |      * the INT instruction.  Since the exact values available  | 
 | 5001 |      * are determined entirely by the SCSI script running,  | 
 | 5002 |      * and are local to a particular script, a unique handler | 
 | 5003 |      * is called for each script. | 
 | 5004 |      */ | 
 | 5005 |  | 
 | 5006 |     if (dstat & DSTAT_SIR) { | 
 | 5007 | 	if (hostdata->options & OPTION_DEBUG_INTR) | 
 | 5008 | 	    printk ("scsi%d : DSTAT_SIR\n", host->host_no); | 
 | 5009 | 	switch ((tmp = hostdata->dstat_sir_intr (host, cmd))) { | 
 | 5010 | 	case SPECIFIC_INT_NOTHING: | 
 | 5011 | 	case SPECIFIC_INT_RESTART: | 
 | 5012 | 	    break; | 
 | 5013 | 	case SPECIFIC_INT_ABORT: | 
 | 5014 | 	    abort_connected(host); | 
 | 5015 | 	    break; | 
 | 5016 | 	case SPECIFIC_INT_PANIC: | 
 | 5017 | 	    printk(KERN_ALERT "scsi%d : failure at ", host->host_no); | 
 | 5018 | 	    print_insn (host, dsp, KERN_ALERT "", 1); | 
 | 5019 | 	    printk(KERN_ALERT "          dstat_sir_intr() returned SPECIFIC_INT_PANIC\n"); | 
 | 5020 |     	    FATAL (host); | 
 | 5021 | 	    break; | 
 | 5022 | 	case SPECIFIC_INT_BREAK: | 
 | 5023 | 	    intr_break (host, cmd); | 
 | 5024 | 	    break; | 
 | 5025 | 	default: | 
 | 5026 | 	    printk(KERN_ALERT "scsi%d : failure at ", host->host_no); | 
 | 5027 | 	    print_insn (host, dsp, KERN_ALERT "", 1); | 
 | 5028 | 	    printk(KERN_ALERT"          dstat_sir_intr() returned unknown value %d\n",  | 
 | 5029 | 		tmp); | 
 | 5030 |     	    FATAL (host); | 
 | 5031 | 	} | 
 | 5032 |     }  | 
 | 5033 | } | 
 | 5034 |  | 
 | 5035 | /* | 
 | 5036 |  * Function : static int print_insn (struct Scsi_Host *host,  | 
 | 5037 |  * 	u32 *insn, int kernel) | 
 | 5038 |  * | 
 | 5039 |  * Purpose : print numeric representation of the instruction pointed | 
 | 5040 |  * 	to by insn to the debugging or kernel message buffer | 
 | 5041 |  *	as appropriate.   | 
 | 5042 |  * | 
 | 5043 |  * 	If desired, a user level program can interpret this  | 
 | 5044 |  * 	information. | 
 | 5045 |  * | 
 | 5046 |  * Inputs : host, insn - host, pointer to instruction, prefix -  | 
 | 5047 |  *	string to prepend, kernel - use printk instead of debugging buffer. | 
 | 5048 |  * | 
 | 5049 |  * Returns : size, in u32s, of instruction printed. | 
 | 5050 |  */ | 
 | 5051 |  | 
 | 5052 | /* | 
 | 5053 |  * FIXME: should change kernel parameter so that it takes an ENUM | 
 | 5054 |  * 	specifying severity - either KERN_ALERT or KERN_PANIC so | 
 | 5055 |  *	all panic messages are output with the same severity. | 
 | 5056 |  */ | 
 | 5057 |  | 
 | 5058 | static int  | 
 | 5059 | print_insn (struct Scsi_Host *host, const u32 *insn,  | 
 | 5060 |     const char *prefix, int kernel) { | 
 | 5061 |     char buf[160], 		/* Temporary buffer and pointer.  ICKY  | 
 | 5062 | 				   arbitrary length.  */ | 
 | 5063 |  | 
 | 5064 | 		 | 
 | 5065 | 	*tmp;			 | 
 | 5066 |     unsigned char dcmd;		/* dcmd register for *insn */ | 
 | 5067 |     int size; | 
 | 5068 |  | 
 | 5069 |     /*  | 
 | 5070 |      * Check to see if the instruction pointer is not bogus before  | 
 | 5071 |      * indirecting through it; avoiding red-zone at start of  | 
 | 5072 |      * memory. | 
 | 5073 |      * | 
 | 5074 |      * FIXME: icky magic needs to happen here on non-intel boxes which | 
 | 5075 |      * don't have kernel memory mapped in like this.  Might be reasonable | 
 | 5076 |      * to use vverify()? | 
 | 5077 |      */ | 
 | 5078 |  | 
 | 5079 |     if (virt_to_phys((void *)insn) < PAGE_SIZE ||  | 
 | 5080 | 	virt_to_phys((void *)(insn + 8)) > virt_to_phys(high_memory) || | 
 | 5081 | 	((((dcmd = (insn[0] >> 24) & 0xff) & DCMD_TYPE_MMI) == DCMD_TYPE_MMI) && | 
 | 5082 | 	virt_to_phys((void *)(insn + 12)) > virt_to_phys(high_memory))) { | 
 | 5083 | 	size = 0; | 
 | 5084 | 	sprintf (buf, "%s%p: address out of range\n", | 
 | 5085 | 	    prefix, insn); | 
 | 5086 |     } else { | 
 | 5087 | /*  | 
 | 5088 |  * FIXME : (void *) cast in virt_to_bus should be unnecessary, because | 
 | 5089 |  * 	it should take const void * as argument. | 
 | 5090 |  */ | 
 | 5091 | #if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000) | 
 | 5092 | 	sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)",  | 
 | 5093 | 	    (prefix ? prefix : ""), virt_to_bus((void *) insn), insn,   | 
 | 5094 | 	    insn[0], insn[1], bus_to_virt (insn[1])); | 
 | 5095 | #else | 
 | 5096 | 	/* Remove virtual addresses to reduce output, as they are the same */ | 
 | 5097 | 	sprintf(buf, "%s0x%x (+%x) : 0x%08x 0x%08x",  | 
 | 5098 | 	    (prefix ? prefix : ""), (u32)insn, ((u32)insn - | 
 | 5099 | 		(u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4,  | 
 | 5100 | 	    insn[0], insn[1]); | 
 | 5101 | #endif | 
 | 5102 | 	tmp = buf + strlen(buf); | 
 | 5103 | 	if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)  { | 
 | 5104 | #if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000) | 
 | 5105 | 	    sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2],  | 
 | 5106 | 		bus_to_virt(insn[2])); | 
 | 5107 | #else | 
 | 5108 | 	    /* Remove virtual addr to reduce output, as it is the same */ | 
 | 5109 | 	    sprintf (tmp, " 0x%08x\n", insn[2]); | 
 | 5110 | #endif | 
 | 5111 | 	    size = 3; | 
 | 5112 | 	} else { | 
 | 5113 | 	    sprintf (tmp, "\n"); | 
 | 5114 | 	    size = 2; | 
 | 5115 | 	} | 
 | 5116 |     } | 
 | 5117 |  | 
 | 5118 |     if (kernel)  | 
 | 5119 | 	printk ("%s", buf); | 
 | 5120 | #ifdef NCR_DEBUG | 
 | 5121 |     else { | 
 | 5122 | 	size_t len = strlen(buf); | 
 | 5123 | 	debugger_kernel_write(host, buf, len); | 
 | 5124 |     } | 
 | 5125 | #endif | 
 | 5126 |     return size; | 
 | 5127 | } | 
 | 5128 |  | 
 | 5129 | /* | 
 | 5130 |  * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd) | 
 | 5131 |  *  | 
 | 5132 |  * Purpose : Abort an errant SCSI command, doing all necessary | 
 | 5133 |  *	cleanup of the issue_queue, running_list, shared Linux/NCR | 
 | 5134 |  *	dsa issue and reconnect queues. | 
 | 5135 |  * | 
 | 5136 |  * Inputs : cmd - command to abort, code - entire result field | 
 | 5137 |  * | 
 | 5138 |  * Returns : 0 on success, -1 on failure. | 
 | 5139 |  */ | 
 | 5140 |  | 
 | 5141 | int  | 
 | 5142 | NCR53c7xx_abort (Scsi_Cmnd *cmd) { | 
 | 5143 |     NCR53c7x0_local_declare(); | 
 | 5144 |     struct Scsi_Host *host = cmd->device->host; | 
 | 5145 |     struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *)  | 
 | 5146 | 	host->hostdata[0] : NULL; | 
 | 5147 |     unsigned long flags; | 
 | 5148 |     struct NCR53c7x0_cmd *curr, **prev; | 
 | 5149 |     Scsi_Cmnd *me, **last; | 
 | 5150 | #if 0 | 
 | 5151 |     static long cache_pid = -1; | 
 | 5152 | #endif | 
 | 5153 |  | 
 | 5154 |  | 
 | 5155 |     if (!host) { | 
 | 5156 | 	printk ("Bogus SCSI command pid %ld; no host structure\n", | 
 | 5157 | 	    cmd->pid); | 
 | 5158 | 	return SCSI_ABORT_ERROR; | 
 | 5159 |     } else if (!hostdata) { | 
 | 5160 | 	printk ("Bogus SCSI host %d; no hostdata\n", host->host_no); | 
 | 5161 | 	return SCSI_ABORT_ERROR; | 
 | 5162 |     } | 
 | 5163 |     NCR53c7x0_local_setup(host); | 
 | 5164 |  | 
 | 5165 | /* | 
 | 5166 |  * CHECK : I don't think that reading ISTAT will unstack any interrupts, | 
 | 5167 |  *	since we need to write the INTF bit to clear it, and SCSI/DMA | 
 | 5168 |  * 	interrupts don't clear until we read SSTAT/SIST and DSTAT registers. | 
 | 5169 |  *	 | 
 | 5170 |  *	See that this is the case.  Appears to be correct on the 710, at least. | 
 | 5171 |  * | 
 | 5172 |  * I suspect that several of our failures may be coming from a new fatal | 
 | 5173 |  * interrupt (possibly due to a phase mismatch) happening after we've left | 
 | 5174 |  * the interrupt handler, but before the PIC has had the interrupt condition | 
 | 5175 |  * cleared. | 
 | 5176 |  */ | 
 | 5177 |  | 
 | 5178 |     if (NCR53c7x0_read8(hostdata->istat) & (ISTAT_DIP|ISTAT_SIP)) { | 
 | 5179 | 	printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no, | 
 | 5180 | 	    cmd->pid); | 
 | 5181 | 	NCR53c7x0_intr (host->irq, NULL, NULL); | 
 | 5182 | 	return SCSI_ABORT_BUSY; | 
 | 5183 |     } | 
 | 5184 | 	 | 
 | 5185 |     local_irq_save(flags); | 
 | 5186 | #if 0 | 
 | 5187 |     if (cache_pid == cmd->pid)  | 
 | 5188 | 	panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid); | 
 | 5189 |     else | 
 | 5190 | 	cache_pid = cmd->pid; | 
 | 5191 | #endif | 
 | 5192 | 	 | 
 | 5193 |  | 
 | 5194 | /* | 
 | 5195 |  * The command could be hiding in the issue_queue.  This would be very | 
 | 5196 |  * nice, as commands can't be moved from the high level driver's issue queue  | 
 | 5197 |  * into the shared queue until an interrupt routine is serviced, and this | 
 | 5198 |  * moving is atomic.   | 
 | 5199 |  * | 
 | 5200 |  * If this is the case, we don't have to worry about anything - we simply | 
 | 5201 |  * pull the command out of the old queue, and call it aborted. | 
 | 5202 |  */ | 
 | 5203 |  | 
 | 5204 |     for (me = (Scsi_Cmnd *) hostdata->issue_queue,  | 
 | 5205 |          last = (Scsi_Cmnd **) &(hostdata->issue_queue); | 
 | 5206 | 	 me && me != cmd;  last = (Scsi_Cmnd **)&(me->SCp.ptr),  | 
 | 5207 | 	 me = (Scsi_Cmnd *)me->SCp.ptr); | 
 | 5208 |  | 
 | 5209 |     if (me) { | 
 | 5210 | 	*last = (Scsi_Cmnd *) me->SCp.ptr; | 
 | 5211 | 	if (me->host_scribble) { | 
 | 5212 | 	    ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free; | 
 | 5213 | 	    hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble; | 
 | 5214 | 	    me->host_scribble = NULL; | 
 | 5215 | 	} | 
 | 5216 | 	cmd->result = DID_ABORT << 16; | 
 | 5217 | 	cmd->scsi_done(cmd); | 
 | 5218 | 	printk ("scsi%d : found command %ld in Linux issue queue\n",  | 
 | 5219 | 	    host->host_no, me->pid); | 
 | 5220 | 	local_irq_restore(flags); | 
 | 5221 |     	run_process_issue_queue(); | 
 | 5222 | 	return SCSI_ABORT_SUCCESS; | 
 | 5223 |     } | 
 | 5224 |  | 
 | 5225 | /*  | 
 | 5226 |  * That failing, the command could be in our list of already executing  | 
 | 5227 |  * commands.  If this is the case, drastic measures are called for.   | 
 | 5228 |  */  | 
 | 5229 |  | 
 | 5230 |     for (curr = (struct NCR53c7x0_cmd *) hostdata->running_list,  | 
 | 5231 |     	 prev = (struct NCR53c7x0_cmd **) &(hostdata->running_list); | 
 | 5232 | 	 curr && curr->cmd != cmd; prev = (struct NCR53c7x0_cmd **)  | 
 | 5233 |          &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next); | 
 | 5234 |  | 
 | 5235 |     if (curr) { | 
 | 5236 | 	if ((curr->result & 0xff) != 0xff && (curr->result & 0xff00) != 0xff00) { | 
 | 5237 |             cmd->result = curr->result; | 
 | 5238 | 	    if (prev) | 
 | 5239 | 		*prev = (struct NCR53c7x0_cmd *) curr->next; | 
 | 5240 | 	    curr->next = (struct NCR53c7x0_cmd *) hostdata->free; | 
 | 5241 | 	    cmd->host_scribble = NULL; | 
 | 5242 | 	    hostdata->free = curr; | 
 | 5243 | 	    cmd->scsi_done(cmd); | 
 | 5244 | 	printk ("scsi%d : found finished command %ld in running list\n",  | 
 | 5245 | 	    host->host_no, cmd->pid); | 
 | 5246 | 	    local_irq_restore(flags); | 
 | 5247 | 	    return SCSI_ABORT_NOT_RUNNING; | 
 | 5248 | 	} else { | 
 | 5249 | 	    printk ("scsi%d : DANGER : command running, can not abort.\n", | 
 | 5250 | 		cmd->device->host->host_no); | 
 | 5251 | 	    local_irq_restore(flags); | 
 | 5252 | 	    return SCSI_ABORT_BUSY; | 
 | 5253 | 	} | 
 | 5254 |     } | 
 | 5255 |  | 
 | 5256 | /*  | 
 | 5257 |  * And if we couldn't find it in any of our queues, it must have been  | 
 | 5258 |  * a dropped interrupt. | 
 | 5259 |  */ | 
 | 5260 |  | 
 | 5261 |     curr = (struct NCR53c7x0_cmd *) cmd->host_scribble; | 
 | 5262 |     if (curr) { | 
 | 5263 | 	curr->next = hostdata->free; | 
 | 5264 | 	hostdata->free = curr; | 
 | 5265 | 	cmd->host_scribble = NULL; | 
 | 5266 |     } | 
 | 5267 |  | 
 | 5268 |     if (curr == NULL || ((curr->result & 0xff00) == 0xff00) || | 
 | 5269 | 		((curr->result & 0xff) == 0xff)) { | 
 | 5270 | 	printk ("scsi%d : did this command ever run?\n", host->host_no); | 
 | 5271 | 	    cmd->result = DID_ABORT << 16; | 
 | 5272 |     } else { | 
 | 5273 | 	printk ("scsi%d : probably lost INTFLY, normal completion\n",  | 
 | 5274 | 	    host->host_no); | 
 | 5275 |         cmd->result = curr->result; | 
 | 5276 | /*  | 
 | 5277 |  * FIXME : We need to add an additional flag which indicates if a  | 
 | 5278 |  * command was ever counted as BUSY, so if we end up here we can | 
 | 5279 |  * decrement the busy count if and only if it is necessary. | 
 | 5280 |  */ | 
 | 5281 |         --hostdata->busy[cmd->device->id][cmd->device->lun]; | 
 | 5282 |     } | 
 | 5283 |     local_irq_restore(flags); | 
 | 5284 |     cmd->scsi_done(cmd); | 
 | 5285 |  | 
 | 5286 | /*  | 
 | 5287 |  * We need to run process_issue_queue since termination of this command  | 
 | 5288 |  * may allow another queued command to execute first?  | 
 | 5289 |  */ | 
 | 5290 |     return SCSI_ABORT_NOT_RUNNING; | 
 | 5291 | } | 
 | 5292 |  | 
 | 5293 | /* | 
 | 5294 |  * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd)  | 
 | 5295 |  *  | 
 | 5296 |  * Purpose : perform a hard reset of the SCSI bus and NCR | 
 | 5297 |  * 	chip. | 
 | 5298 |  * | 
 | 5299 |  * Inputs : cmd - command which caused the SCSI RESET | 
 | 5300 |  * | 
 | 5301 |  * Returns : 0 on success. | 
 | 5302 |  */ | 
 | 5303 |   | 
 | 5304 | int  | 
 | 5305 | NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) { | 
 | 5306 |     NCR53c7x0_local_declare(); | 
 | 5307 |     unsigned long flags; | 
 | 5308 |     int found = 0; | 
 | 5309 |     struct NCR53c7x0_cmd * c; | 
 | 5310 |     Scsi_Cmnd *tmp; | 
 | 5311 |     /* | 
 | 5312 |      * When we call scsi_done(), it's going to wake up anything sleeping on the | 
 | 5313 |      * resources which were in use by the aborted commands, and we'll start to  | 
 | 5314 |      * get new commands. | 
 | 5315 |      * | 
 | 5316 |      * We can't let this happen until after we've re-initialized the driver | 
 | 5317 |      * structures, and can't reinitialize those structures until after we've  | 
 | 5318 |      * dealt with their contents. | 
 | 5319 |      * | 
 | 5320 |      * So, we need to find all of the commands which were running, stick | 
 | 5321 |      * them on a linked list of completed commands (we'll use the host_scribble | 
 | 5322 |      * pointer), do our reinitialization, and then call the done function for | 
 | 5323 |      * each command.   | 
 | 5324 |      */ | 
 | 5325 |     Scsi_Cmnd *nuke_list = NULL; | 
 | 5326 |     struct Scsi_Host *host = cmd->device->host; | 
 | 5327 |     struct NCR53c7x0_hostdata *hostdata =  | 
 | 5328 |     	(struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 5329 |  | 
 | 5330 |     NCR53c7x0_local_setup(host); | 
 | 5331 |     local_irq_save(flags); | 
 | 5332 |     ncr_halt (host); | 
 | 5333 |     print_lots (host); | 
 | 5334 |     dump_events (host, 30); | 
 | 5335 |     ncr_scsi_reset (host); | 
 | 5336 |     for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */, | 
 | 5337 | 	0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer) | 
 | 5338 | 	if (tmp == cmd) { | 
 | 5339 | 	    found = 1; | 
 | 5340 | 	    break; | 
 | 5341 | 	} | 
 | 5342 | 	     | 
 | 5343 |     /*  | 
 | 5344 |      * If we didn't find the command which caused this reset in our running | 
 | 5345 |      * list, then we've lost it.  See that it terminates normally anyway. | 
 | 5346 |      */ | 
 | 5347 |     if (!found) { | 
 | 5348 |     	c = (struct NCR53c7x0_cmd *) cmd->host_scribble; | 
 | 5349 |     	if (c) { | 
 | 5350 | 	    cmd->host_scribble = NULL; | 
 | 5351 |     	    c->next = hostdata->free; | 
 | 5352 |     	    hostdata->free = c; | 
 | 5353 |     	} else | 
 | 5354 | 	    printk ("scsi%d: lost command %ld\n", host->host_no, cmd->pid); | 
 | 5355 | 	cmd->SCp.buffer = (struct scatterlist *) nuke_list; | 
 | 5356 | 	nuke_list = cmd; | 
 | 5357 |     } | 
 | 5358 |  | 
 | 5359 |     NCR53c7x0_driver_init (host); | 
 | 5360 |     hostdata->soft_reset (host); | 
 | 5361 |     if (hostdata->resets == 0)  | 
 | 5362 | 	disable(host); | 
 | 5363 |     else if (hostdata->resets != -1) | 
 | 5364 | 	--hostdata->resets; | 
 | 5365 |     local_irq_restore(flags); | 
 | 5366 |     for (; nuke_list; nuke_list = tmp) { | 
 | 5367 | 	tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; | 
 | 5368 |     	nuke_list->result = DID_RESET << 16; | 
 | 5369 | 	nuke_list->scsi_done (nuke_list); | 
 | 5370 |     } | 
 | 5371 |     local_irq_restore(flags); | 
 | 5372 |     return SCSI_RESET_SUCCESS; | 
 | 5373 | } | 
 | 5374 |  | 
 | 5375 | /* | 
 | 5376 |  * The NCR SDMS bios follows Annex A of the SCSI-CAM draft, and  | 
 | 5377 |  * therefore shares the scsicam_bios_param function. | 
 | 5378 |  */ | 
 | 5379 |  | 
 | 5380 | /* | 
 | 5381 |  * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) | 
 | 5382 |  * | 
 | 5383 |  * Purpose : convert instructions stored at NCR pointer into data  | 
 | 5384 |  *	pointer offset. | 
 | 5385 |  *  | 
 | 5386 |  * Inputs : cmd - SCSI command; insn - pointer to instruction.  Either current | 
 | 5387 |  *	DSP, or saved data pointer. | 
 | 5388 |  * | 
 | 5389 |  * Returns : offset on success, -1 on failure. | 
 | 5390 |  */ | 
 | 5391 |  | 
 | 5392 |  | 
 | 5393 | static int  | 
 | 5394 | insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { | 
 | 5395 |     struct NCR53c7x0_hostdata *hostdata =  | 
 | 5396 | 	(struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0]; | 
 | 5397 |     struct NCR53c7x0_cmd *ncmd =  | 
 | 5398 | 	(struct NCR53c7x0_cmd *) cmd->host_scribble; | 
 | 5399 |     int offset = 0, buffers; | 
 | 5400 |     struct scatterlist *segment; | 
 | 5401 |     char *ptr; | 
 | 5402 |     int found = 0; | 
 | 5403 |  | 
 | 5404 | /* | 
 | 5405 |  * With the current code implementation, if the insn is inside dynamically  | 
 | 5406 |  * generated code, the data pointer will be the instruction preceding  | 
 | 5407 |  * the next transfer segment. | 
 | 5408 |  */ | 
 | 5409 |  | 
 | 5410 |     if (!check_address ((unsigned long) ncmd, sizeof (struct NCR53c7x0_cmd)) && | 
 | 5411 | 	((insn >= ncmd->data_transfer_start &&   | 
 | 5412 |     	    insn < ncmd->data_transfer_end) || | 
 | 5413 |     	(insn >= ncmd->residual && | 
 | 5414 |     	    insn < (ncmd->residual +  | 
 | 5415 |     	    	sizeof(ncmd->residual))))) { | 
 | 5416 | 	    ptr = bus_to_virt(insn[3]); | 
 | 5417 |  | 
 | 5418 | 	    if ((buffers = cmd->use_sg)) { | 
 | 5419 |     	    	for (offset = 0,  | 
 | 5420 | 		     	segment = (struct scatterlist *) cmd->buffer; | 
 | 5421 |     	    	     buffers && !((found = ((ptr >= (char *)page_address(segment->page)+segment->offset) &&  | 
 | 5422 |     	    	    	    (ptr < ((char *)page_address(segment->page)+segment->offset+segment->length))))); | 
 | 5423 |     	    	     --buffers, offset += segment->length, ++segment) | 
 | 5424 | #if 0 | 
 | 5425 | 		    printk("scsi%d: comparing 0x%p to 0x%p\n",  | 
 | 5426 | 			cmd->device->host->host_no, saved, page_address(segment->page+segment->offset); | 
 | 5427 | #else | 
 | 5428 | 		    ; | 
 | 5429 | #endif | 
 | 5430 |     	    	    offset += ptr - ((char *)page_address(segment->page)+segment->offset); | 
 | 5431 |     	    } else { | 
 | 5432 | 		found = 1; | 
 | 5433 |     	    	offset = ptr - (char *) (cmd->request_buffer); | 
 | 5434 |     	    } | 
 | 5435 |     } else if ((insn >= hostdata->script +  | 
 | 5436 | 		hostdata->E_data_transfer / sizeof(u32)) && | 
 | 5437 | 	       (insn <= hostdata->script + | 
 | 5438 | 		hostdata->E_end_data_transfer / sizeof(u32))) { | 
 | 5439 |     	found = 1; | 
 | 5440 | 	offset = 0; | 
 | 5441 |     } | 
 | 5442 |     return found ? offset : -1; | 
 | 5443 | } | 
 | 5444 |  | 
 | 5445 |  | 
 | 5446 |  | 
 | 5447 | /* | 
 | 5448 |  * Function : void print_progress (Scsi_Cmnd *cmd)  | 
 | 5449 |  *  | 
 | 5450 |  * Purpose : print the current location of the saved data pointer | 
 | 5451 |  * | 
 | 5452 |  * Inputs : cmd - command we are interested in | 
 | 5453 |  * | 
 | 5454 |  */ | 
 | 5455 |  | 
 | 5456 | static void  | 
 | 5457 | print_progress (Scsi_Cmnd *cmd) { | 
 | 5458 |     NCR53c7x0_local_declare(); | 
 | 5459 |     struct NCR53c7x0_cmd *ncmd =  | 
 | 5460 | 	(struct NCR53c7x0_cmd *) cmd->host_scribble; | 
 | 5461 |     int offset, i; | 
 | 5462 |     char *where; | 
 | 5463 |     u32 *ptr; | 
 | 5464 |     NCR53c7x0_local_setup (cmd->device->host); | 
 | 5465 |  | 
 | 5466 |     if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0) | 
 | 5467 |     { | 
 | 5468 | 	printk("\nNCR53c7x0_cmd fields:\n"); | 
 | 5469 | 	printk("  bounce.len=0x%x, addr=0x%0x, buf[]=0x%02x %02x %02x %02x\n", | 
 | 5470 | 	    ncmd->bounce.len, ncmd->bounce.addr, ncmd->bounce.buf[0], | 
 | 5471 | 	    ncmd->bounce.buf[1], ncmd->bounce.buf[2], ncmd->bounce.buf[3]); | 
 | 5472 | 	printk("  result=%04x, cdb[0]=0x%02x\n", ncmd->result, ncmd->cmnd[0]); | 
 | 5473 |     } | 
 | 5474 |  | 
 | 5475 |     for (i = 0; i < 2; ++i) { | 
 | 5476 | 	if (check_address ((unsigned long) ncmd,  | 
 | 5477 | 	    sizeof (struct NCR53c7x0_cmd)) == -1)  | 
 | 5478 | 	    continue; | 
 | 5479 | 	if (!i) { | 
 | 5480 | 	    where = "saved"; | 
 | 5481 | 	    ptr = bus_to_virt(ncmd->saved_data_pointer); | 
 | 5482 | 	} else { | 
 | 5483 | 	    where = "active"; | 
 | 5484 | 	    ptr = bus_to_virt (NCR53c7x0_read32 (DSP_REG) - | 
 | 5485 | 		NCR53c7x0_insn_size (NCR53c7x0_read8 (DCMD_REG)) * | 
 | 5486 | 		sizeof(u32)); | 
 | 5487 | 	}  | 
 | 5488 | 	offset = insn_to_offset (cmd, ptr); | 
 | 5489 |  | 
 | 5490 | 	if (offset != -1)  | 
 | 5491 | 	    printk ("scsi%d : %s data pointer at offset %d\n", | 
 | 5492 | 		cmd->device->host->host_no, where, offset); | 
 | 5493 | 	else { | 
 | 5494 | 	    int size; | 
 | 5495 | 	    printk ("scsi%d : can't determine %s data pointer offset\n", | 
 | 5496 | 		cmd->device->host->host_no, where); | 
 | 5497 | 	    if (ncmd) { | 
 | 5498 | 		size = print_insn (cmd->device->host, | 
 | 5499 | 		    bus_to_virt(ncmd->saved_data_pointer), "", 1); | 
 | 5500 | 		print_insn (cmd->device->host, | 
 | 5501 | 		    bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32), | 
 | 5502 | 		    "", 1); | 
 | 5503 | 	    } | 
 | 5504 | 	} | 
 | 5505 |     } | 
 | 5506 | } | 
 | 5507 |  | 
 | 5508 |  | 
 | 5509 | static void  | 
 | 5510 | print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) { | 
 | 5511 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5512 | 	host->hostdata[0]; | 
 | 5513 |     int i, len; | 
 | 5514 |     char *ptr; | 
 | 5515 |     Scsi_Cmnd *cmd; | 
 | 5516 |  | 
 | 5517 |     if (check_address ((unsigned long) dsa, hostdata->dsa_end -  | 
 | 5518 | 	hostdata->dsa_start) == -1) { | 
 | 5519 | 	printk("scsi%d : bad dsa virt 0x%p\n", host->host_no, dsa); | 
 | 5520 | 	return; | 
 | 5521 |     } | 
 | 5522 |     printk("%sscsi%d : dsa at phys 0x%lx (virt 0x%p)\n" | 
 | 5523 | 	    "        + %d : dsa_msgout length = %u, data = 0x%x (virt 0x%p)\n" , | 
 | 5524 |     	    prefix ? prefix : "", | 
 | 5525 |     	    host->host_no,  virt_to_bus (dsa), dsa, hostdata->dsa_msgout, | 
 | 5526 |     	    dsa[hostdata->dsa_msgout / sizeof(u32)], | 
 | 5527 | 	    dsa[hostdata->dsa_msgout / sizeof(u32) + 1], | 
 | 5528 | 	    bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1])); | 
 | 5529 |  | 
 | 5530 |     /*  | 
 | 5531 |      * Only print messages if they're sane in length so we don't | 
 | 5532 |      * blow the kernel printk buffer on something which won't buy us | 
 | 5533 |      * anything. | 
 | 5534 |      */ | 
 | 5535 |  | 
 | 5536 |     if (dsa[hostdata->dsa_msgout / sizeof(u32)] <  | 
 | 5537 | 	    sizeof (hostdata->free->select))  | 
 | 5538 | 	for (i = dsa[hostdata->dsa_msgout / sizeof(u32)], | 
 | 5539 | 	    ptr = bus_to_virt (dsa[hostdata->dsa_msgout / sizeof(u32) + 1]);  | 
 | 5540 | 	    i > 0 && !check_address ((unsigned long) ptr, 1); | 
 | 5541 | 	    ptr += len, i -= len) { | 
 | 5542 | 	    printk("               "); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 5543 | 	    len = scsi_print_msg (ptr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5544 | 	    printk("\n"); | 
 | 5545 | 	    if (!len) | 
 | 5546 | 		break; | 
 | 5547 | 	} | 
 | 5548 |  | 
 | 5549 |     printk("        + %d : select_indirect = 0x%x\n", | 
 | 5550 | 	hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]); | 
 | 5551 |     cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]); | 
 | 5552 |     printk("        + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd, | 
 | 5553 | 	   (u32) virt_to_bus(cmd)); | 
 | 5554 |     /* XXX Maybe we should access cmd->host_scribble->result here. RGH */ | 
 | 5555 |     if (cmd) { | 
 | 5556 | 	printk("               result = 0x%x, target = %d, lun = %d, cmd = ", | 
 | 5557 | 	    cmd->result, cmd->device->id, cmd->device->lun); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 5558 | 	__scsi_print_command(cmd->cmnd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 5559 |     } else | 
 | 5560 | 	printk("\n"); | 
 | 5561 |     printk("        + %d : dsa_next = 0x%x\n", hostdata->dsa_next, | 
 | 5562 | 	dsa[hostdata->dsa_next / sizeof(u32)]); | 
 | 5563 |     if (cmd) {  | 
 | 5564 | 	printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n" | 
 | 5565 | 	       "                   script : ", | 
 | 5566 | 	    host->host_no, cmd->device->id, | 
 | 5567 | 	    hostdata->sync[cmd->device->id].sxfer_sanity, | 
 | 5568 | 	    hostdata->sync[cmd->device->id].scntl3_sanity); | 
 | 5569 | 	for (i = 0; i < (sizeof(hostdata->sync[cmd->device->id].script) / 4); ++i) | 
 | 5570 | 	    printk ("0x%x ", hostdata->sync[cmd->device->id].script[i]); | 
 | 5571 | 	printk ("\n"); | 
 | 5572 |     	print_progress (cmd); | 
 | 5573 |     } | 
 | 5574 | } | 
 | 5575 | /* | 
 | 5576 |  * Function : void print_queues (Scsi_Host *host)  | 
 | 5577 |  *  | 
 | 5578 |  * Purpose : print the contents of the NCR issue and reconnect queues | 
 | 5579 |  * | 
 | 5580 |  * Inputs : host - SCSI host we are interested in | 
 | 5581 |  * | 
 | 5582 |  */ | 
 | 5583 |  | 
 | 5584 | static void  | 
 | 5585 | print_queues (struct Scsi_Host *host) { | 
 | 5586 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5587 | 	host->hostdata[0]; | 
 | 5588 |     u32 *dsa, *next_dsa; | 
 | 5589 |     volatile u32 *ncrcurrent; | 
 | 5590 |     int left; | 
 | 5591 |     Scsi_Cmnd *cmd, *next_cmd; | 
 | 5592 |     unsigned long flags; | 
 | 5593 |  | 
 | 5594 |     printk ("scsi%d : issue queue\n", host->host_no); | 
 | 5595 |  | 
 | 5596 |     for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue;  | 
 | 5597 | 	    left >= 0 && cmd;  | 
 | 5598 | 	    cmd = next_cmd) { | 
 | 5599 | 	next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr; | 
 | 5600 | 	local_irq_save(flags); | 
 | 5601 | 	if (cmd->host_scribble) { | 
 | 5602 | 	    if (check_address ((unsigned long) (cmd->host_scribble),  | 
 | 5603 | 		sizeof (cmd->host_scribble)) == -1) | 
 | 5604 | 		printk ("scsi%d: scsi pid %ld bad pointer to NCR53c7x0_cmd\n", | 
 | 5605 | 		    host->host_no, cmd->pid); | 
 | 5606 | 	    /* print_dsa does sanity check on address, no need to check */ | 
 | 5607 | 	    else | 
 | 5608 | 	    	print_dsa (host, ((struct NCR53c7x0_cmd *) cmd->host_scribble) | 
 | 5609 | 		    -> dsa, ""); | 
 | 5610 | 	} else  | 
 | 5611 | 	    printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n", | 
 | 5612 | 		host->host_no, cmd->pid, cmd->device->id, cmd->device->lun); | 
 | 5613 | 	local_irq_restore(flags); | 
 | 5614 |     } | 
 | 5615 |  | 
 | 5616 |     if (left <= 0) { | 
 | 5617 | 	printk ("scsi%d : loop detected in issue queue\n", | 
 | 5618 | 	    host->host_no); | 
 | 5619 |     } | 
 | 5620 |  | 
 | 5621 |     /* | 
 | 5622 |      * Traverse the NCR reconnect and start DSA structures, printing out  | 
 | 5623 |      * each element until we hit the end or detect a loop.  Currently, | 
 | 5624 |      * the reconnect structure is a linked list; and the start structure | 
 | 5625 |      * is an array.  Eventually, the reconnect structure will become a  | 
 | 5626 |      * list as well, since this simplifies the code. | 
 | 5627 |      */ | 
 | 5628 |  | 
 | 5629 |     printk ("scsi%d : schedule dsa array :\n", host->host_no); | 
 | 5630 |     for (left = host->can_queue, ncrcurrent = hostdata->schedule; | 
 | 5631 | 	    left > 0; ncrcurrent += 2, --left) | 
 | 5632 | 	if (ncrcurrent[0] != hostdata->NOP_insn)  | 
 | 5633 | /* FIXME : convert pointer to dsa_begin to pointer to dsa. */ | 
 | 5634 | 	    print_dsa (host, bus_to_virt (ncrcurrent[1] -  | 
 | 5635 | 		(hostdata->E_dsa_code_begin -  | 
 | 5636 | 		hostdata->E_dsa_code_template)), ""); | 
 | 5637 |     printk ("scsi%d : end schedule dsa array\n", host->host_no); | 
 | 5638 |      | 
 | 5639 |     printk ("scsi%d : reconnect_dsa_head :\n", host->host_no); | 
 | 5640 | 	     | 
 | 5641 |     for (left = host->can_queue,  | 
 | 5642 | 	dsa = bus_to_virt (hostdata->reconnect_dsa_head); | 
 | 5643 | 	left >= 0 && dsa;  | 
 | 5644 | 	dsa = next_dsa) { | 
 | 5645 | 	local_irq_save(flags); | 
 | 5646 | 	if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) { | 
 | 5647 | 	    printk ("scsi%d: bad DSA pointer 0x%p", host->host_no, | 
 | 5648 | 		dsa); | 
 | 5649 | 	    next_dsa = NULL; | 
 | 5650 | 	} | 
 | 5651 | 	else  | 
 | 5652 | 	{ | 
 | 5653 | 	    next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]); | 
 | 5654 | 	    print_dsa (host, dsa, ""); | 
 | 5655 | 	} | 
 | 5656 | 	local_irq_restore(flags); | 
 | 5657 |     } | 
 | 5658 |     printk ("scsi%d : end reconnect_dsa_head\n", host->host_no); | 
 | 5659 |     if (left < 0) | 
 | 5660 | 	printk("scsi%d: possible loop in ncr reconnect list\n", | 
 | 5661 | 	    host->host_no); | 
 | 5662 | } | 
 | 5663 |  | 
 | 5664 | static void | 
 | 5665 | print_lots (struct Scsi_Host *host) { | 
 | 5666 |     NCR53c7x0_local_declare(); | 
 | 5667 |     struct NCR53c7x0_hostdata *hostdata =  | 
 | 5668 | 	(struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 5669 |     u32 *dsp_next, *dsp, *dsa, dbc_dcmd; | 
 | 5670 |     unsigned char dcmd, sbcl; | 
 | 5671 |     int i, size; | 
 | 5672 |     NCR53c7x0_local_setup(host); | 
 | 5673 |  | 
 | 5674 |     if ((dsp_next = bus_to_virt(NCR53c7x0_read32 (DSP_REG)))) { | 
 | 5675 |     	dbc_dcmd = NCR53c7x0_read32(DBC_REG); | 
 | 5676 |     	dcmd = (dbc_dcmd & 0xff000000) >> 24; | 
 | 5677 |     	dsp = dsp_next - NCR53c7x0_insn_size(dcmd); | 
 | 5678 | 	dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG)); | 
 | 5679 | 	sbcl = NCR53c7x0_read8 (SBCL_REG); | 
 | 5680 | 	     | 
 | 5681 | 	/* | 
 | 5682 | 	 * For the 53c710, the following will report value 0 for SCNTL3 | 
 | 5683 | 	 * and STEST0 - we don't have these registers. | 
 | 5684 | 	 */ | 
 | 5685 |     	printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n" | 
 | 5686 | 		"         DSA=0x%lx (virt 0x%p)\n" | 
 | 5687 | 	        "         DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n" | 
 | 5688 | 		"         SXFER=0x%x, SCNTL3=0x%x\n" | 
 | 5689 | 		"         %s%s%sphase=%s, %d bytes in SCSI FIFO\n" | 
 | 5690 | 		"         SCRATCH=0x%x, saved2_dsa=0x%0lx\n", | 
 | 5691 | 	    host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG), | 
 | 5692 | 		bus_to_virt(NCR53c7x0_read32(DNAD_REG)), | 
 | 5693 | 	    virt_to_bus(dsa), dsa, | 
 | 5694 | 	    NCR53c7x0_read32(DSPS_REG), NCR53c7x0_read32(TEMP_REG),  | 
 | 5695 | 	    bus_to_virt (NCR53c7x0_read32(TEMP_REG)), | 
 | 5696 | 	    (int) NCR53c7x0_read8(hostdata->dmode), | 
 | 5697 | 	    (int) NCR53c7x0_read8(SXFER_REG),  | 
 | 5698 | 	    ((hostdata->chip / 100) == 8) ? | 
 | 5699 | 		(int) NCR53c7x0_read8(SCNTL3_REG_800) : 0, | 
 | 5700 | 	    (sbcl & SBCL_BSY) ? "BSY " : "", | 
 | 5701 | 	    (sbcl & SBCL_SEL) ? "SEL " : "", | 
 | 5702 | 	    (sbcl & SBCL_REQ) ? "REQ " : "", | 
 | 5703 | 	    sstat2_to_phase(NCR53c7x0_read8 (((hostdata->chip / 100) == 8) ? | 
 | 5704 | 	    	SSTAT1_REG : SSTAT2_REG)), | 
 | 5705 | 	    (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ?  | 
 | 5706 | 		SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT, | 
 | 5707 | 	    ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (STEST0_REG_800) : | 
 | 5708 | 		NCR53c7x0_read32(SCRATCHA_REG_800), | 
 | 5709 | 	    hostdata->saved2_dsa); | 
 | 5710 | 	printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no,  | 
 | 5711 | 	    virt_to_bus(dsp), dsp); | 
 | 5712 |     	for (i = 6; i > 0; --i, dsp += size) | 
 | 5713 | 	    size = print_insn (host, dsp, "", 1); | 
 | 5714 | 	if (NCR53c7x0_read8 (SCNTL1_REG) & SCNTL1_CON)  { | 
 | 5715 | 	    if ((hostdata->chip / 100) == 8) | 
 | 5716 | 	        printk ("scsi%d : connected (SDID=0x%x, SSID=0x%x)\n", | 
 | 5717 | 		    host->host_no, NCR53c7x0_read8 (SDID_REG_800), | 
 | 5718 | 		    NCR53c7x0_read8 (SSID_REG_800)); | 
 | 5719 | 	    else | 
 | 5720 | 		printk ("scsi%d : connected (SDID=0x%x)\n", | 
 | 5721 | 		    host->host_no, NCR53c7x0_read8 (SDID_REG_700)); | 
 | 5722 | 	    print_dsa (host, dsa, ""); | 
 | 5723 | 	} | 
 | 5724 |  | 
 | 5725 | #if 1 | 
 | 5726 | 	print_queues (host); | 
 | 5727 | #endif | 
 | 5728 |     } | 
 | 5729 | } | 
 | 5730 |  | 
 | 5731 | /* | 
 | 5732 |  * Function : static int shutdown (struct Scsi_Host *host) | 
 | 5733 |  *  | 
 | 5734 |  * Purpose : does a clean (we hope) shutdown of the NCR SCSI  | 
 | 5735 |  *	chip.  Use prior to dumping core, unloading the NCR driver, | 
 | 5736 |  *  | 
 | 5737 |  * Returns : 0 on success | 
 | 5738 |  */ | 
 | 5739 | static int  | 
 | 5740 | shutdown (struct Scsi_Host *host) { | 
 | 5741 |     NCR53c7x0_local_declare(); | 
 | 5742 |     unsigned long flags; | 
 | 5743 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5744 | 	host->hostdata[0]; | 
 | 5745 |     NCR53c7x0_local_setup(host); | 
 | 5746 |     local_irq_save(flags); | 
 | 5747 | /* Get in a state where we can reset the SCSI bus */ | 
 | 5748 |     ncr_halt (host); | 
 | 5749 |     ncr_scsi_reset (host); | 
 | 5750 |     hostdata->soft_reset(host); | 
 | 5751 |  | 
 | 5752 |     disable (host); | 
 | 5753 |     local_irq_restore(flags); | 
 | 5754 |     return 0; | 
 | 5755 | } | 
 | 5756 |  | 
 | 5757 | /* | 
 | 5758 |  * Function : void ncr_scsi_reset (struct Scsi_Host *host) | 
 | 5759 |  * | 
 | 5760 |  * Purpose : reset the SCSI bus. | 
 | 5761 |  */ | 
 | 5762 |  | 
 | 5763 | static void  | 
 | 5764 | ncr_scsi_reset (struct Scsi_Host *host) { | 
 | 5765 |     NCR53c7x0_local_declare(); | 
 | 5766 |     unsigned long flags; | 
 | 5767 |     NCR53c7x0_local_setup(host); | 
 | 5768 |     local_irq_save(flags); | 
 | 5769 |     NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST); | 
 | 5770 |     udelay(25);	/* Minimum amount of time to assert RST */ | 
 | 5771 |     NCR53c7x0_write8(SCNTL1_REG, 0); | 
 | 5772 |     local_irq_restore(flags); | 
 | 5773 | } | 
 | 5774 |  | 
 | 5775 | /*  | 
 | 5776 |  * Function : void hard_reset (struct Scsi_Host *host) | 
 | 5777 |  * | 
 | 5778 |  */ | 
 | 5779 |  | 
 | 5780 | static void  | 
 | 5781 | hard_reset (struct Scsi_Host *host) { | 
 | 5782 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5783 | 	host->hostdata[0]; | 
 | 5784 |     unsigned long flags; | 
 | 5785 |     local_irq_save(flags); | 
 | 5786 |     ncr_scsi_reset(host); | 
 | 5787 |     NCR53c7x0_driver_init (host); | 
 | 5788 |     if (hostdata->soft_reset) | 
 | 5789 | 	hostdata->soft_reset (host); | 
 | 5790 |     local_irq_restore(flags); | 
 | 5791 | } | 
 | 5792 |  | 
 | 5793 |  | 
 | 5794 | /* | 
 | 5795 |  * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host, | 
 | 5796 |  *	int free, int issue) | 
 | 5797 |  * | 
 | 5798 |  * Purpose : return a linked list (using the SCp.buffer field as next, | 
 | 5799 |  *	so we don't perturb hostdata.  We don't use a field of the  | 
 | 5800 |  *	NCR53c7x0_cmd structure since we may not have allocated one  | 
 | 5801 |  *	for the command causing the reset.) of Scsi_Cmnd structures that  | 
 | 5802 |  *  	had propagated below the Linux issue queue level.  If free is set,  | 
 | 5803 |  *	free the NCR53c7x0_cmd structures which are associated with  | 
 | 5804 |  *	the Scsi_Cmnd structures, and clean up any internal  | 
 | 5805 |  *	NCR lists that the commands were on.  If issue is set, | 
 | 5806 |  *	also return commands in the issue queue. | 
 | 5807 |  * | 
 | 5808 |  * Returns : linked list of commands | 
 | 5809 |  * | 
 | 5810 |  * NOTE : the caller should insure that the NCR chip is halted | 
 | 5811 |  *	if the free flag is set.  | 
 | 5812 |  */ | 
 | 5813 |  | 
 | 5814 | static Scsi_Cmnd * | 
 | 5815 | return_outstanding_commands (struct Scsi_Host *host, int free, int issue) { | 
 | 5816 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5817 | 	host->hostdata[0]; | 
 | 5818 |     struct NCR53c7x0_cmd *c; | 
 | 5819 |     int i; | 
 | 5820 |     u32 *ncrcurrent; | 
 | 5821 |     Scsi_Cmnd *list = NULL, *tmp; | 
 | 5822 |     for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c;  | 
 | 5823 |     	c = (struct NCR53c7x0_cmd *) c->next)  { | 
 | 5824 | 	if (c->cmd->SCp.buffer) { | 
 | 5825 | 	    printk ("scsi%d : loop detected in running list!\n", host->host_no); | 
 | 5826 | 	    break; | 
 | 5827 | 	} else { | 
 | 5828 | 	    printk ("Duh? Bad things happening in the NCR driver\n"); | 
 | 5829 | 	    break; | 
 | 5830 | 	} | 
 | 5831 |  | 
 | 5832 | 	c->cmd->SCp.buffer = (struct scatterlist *) list; | 
 | 5833 | 	list = c->cmd; | 
 | 5834 | 	if (free) { | 
 | 5835 |     	    c->next = hostdata->free; | 
 | 5836 |     	    hostdata->free = c; | 
 | 5837 | 	} | 
 | 5838 |     } | 
 | 5839 |  | 
 | 5840 |     if (free) {  | 
 | 5841 | 	for (i = 0, ncrcurrent = (u32 *) hostdata->schedule;  | 
 | 5842 | 	    i < host->can_queue; ++i, ncrcurrent += 2) { | 
 | 5843 | 	    ncrcurrent[0] = hostdata->NOP_insn; | 
 | 5844 | 	    ncrcurrent[1] = 0xdeadbeef; | 
 | 5845 | 	} | 
 | 5846 | 	hostdata->ncrcurrent = NULL; | 
 | 5847 |     } | 
 | 5848 |  | 
 | 5849 |     if (issue) { | 
 | 5850 | 	for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) { | 
 | 5851 | 	    if (tmp->SCp.buffer) { | 
 | 5852 | 		printk ("scsi%d : loop detected in issue queue!\n",  | 
 | 5853 | 			host->host_no); | 
 | 5854 | 		break; | 
 | 5855 | 	    } | 
 | 5856 | 	    tmp->SCp.buffer = (struct scatterlist *) list; | 
 | 5857 | 	    list = tmp; | 
 | 5858 | 	} | 
 | 5859 | 	if (free) | 
 | 5860 | 	    hostdata->issue_queue = NULL; | 
 | 5861 | 		 | 
 | 5862 |     } | 
 | 5863 |     return list; | 
 | 5864 | } | 
 | 5865 |  | 
 | 5866 | /*  | 
 | 5867 |  * Function : static int disable (struct Scsi_Host *host) | 
 | 5868 |  * | 
 | 5869 |  * Purpose : disables the given NCR host, causing all commands | 
 | 5870 |  * 	to return a driver error.  Call this so we can unload the | 
 | 5871 |  * 	module during development and try again.  Eventually,  | 
 | 5872 |  * 	we should be able to find clean workarounds for these | 
 | 5873 |  * 	problems. | 
 | 5874 |  * | 
 | 5875 |  * Inputs : host - hostadapter to twiddle | 
 | 5876 |  * | 
 | 5877 |  * Returns : 0 on success. | 
 | 5878 |  */ | 
 | 5879 |  | 
 | 5880 | static int  | 
 | 5881 | disable (struct Scsi_Host *host) { | 
 | 5882 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5883 | 	host->hostdata[0]; | 
 | 5884 |     unsigned long flags; | 
 | 5885 |     Scsi_Cmnd *nuke_list, *tmp; | 
 | 5886 |     local_irq_save(flags); | 
 | 5887 |     if (hostdata->state != STATE_HALTED) | 
 | 5888 | 	ncr_halt (host); | 
 | 5889 |     nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */); | 
 | 5890 |     hard_reset (host); | 
 | 5891 |     hostdata->state = STATE_DISABLED; | 
 | 5892 |     local_irq_restore(flags); | 
 | 5893 |     printk ("scsi%d : nuking commands\n", host->host_no); | 
 | 5894 |     for (; nuke_list; nuke_list = tmp) { | 
 | 5895 | 	    tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; | 
 | 5896 | 	    nuke_list->result = DID_ERROR << 16; | 
 | 5897 | 	    nuke_list->scsi_done(nuke_list); | 
 | 5898 |     } | 
 | 5899 |     printk ("scsi%d : done. \n", host->host_no); | 
 | 5900 |     printk (KERN_ALERT "scsi%d : disabled.  Unload and reload\n", | 
 | 5901 |     	host->host_no); | 
 | 5902 |     return 0; | 
 | 5903 | } | 
 | 5904 |  | 
 | 5905 | /* | 
 | 5906 |  * Function : static int ncr_halt (struct Scsi_Host *host) | 
 | 5907 |  *  | 
 | 5908 |  * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip | 
 | 5909 |  * | 
 | 5910 |  * Inputs : host - SCSI chip to halt | 
 | 5911 |  * | 
 | 5912 |  * Returns : 0 on success | 
 | 5913 |  */ | 
 | 5914 |  | 
 | 5915 | static int  | 
 | 5916 | ncr_halt (struct Scsi_Host *host) { | 
 | 5917 |     NCR53c7x0_local_declare(); | 
 | 5918 |     unsigned long flags; | 
 | 5919 |     unsigned char istat, tmp; | 
 | 5920 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5921 | 	host->hostdata[0]; | 
 | 5922 |     int stage; | 
 | 5923 |     NCR53c7x0_local_setup(host); | 
 | 5924 |  | 
 | 5925 |     local_irq_save(flags); | 
 | 5926 |     /* Stage 0 : eat all interrupts | 
 | 5927 |        Stage 1 : set ABORT | 
 | 5928 |        Stage 2 : eat all but abort interrupts | 
 | 5929 |        Stage 3 : eat all interrupts | 
 | 5930 |      */ | 
 | 5931 |     for (stage = 0;;) { | 
 | 5932 | 	if (stage == 1) { | 
 | 5933 | 	    NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT); | 
 | 5934 | 	    ++stage; | 
 | 5935 | 	} | 
 | 5936 | 	istat = NCR53c7x0_read8 (hostdata->istat); | 
 | 5937 | 	if (istat & ISTAT_SIP) { | 
 | 5938 | 	    tmp = NCR53c7x0_read8(SSTAT0_REG); | 
 | 5939 | 	} else if (istat & ISTAT_DIP) { | 
 | 5940 | 	    tmp = NCR53c7x0_read8(DSTAT_REG); | 
 | 5941 | 	    if (stage == 2) { | 
 | 5942 | 		if (tmp & DSTAT_ABRT) { | 
 | 5943 | 		    NCR53c7x0_write8(hostdata->istat, 0); | 
 | 5944 | 		    ++stage; | 
 | 5945 | 		} else { | 
 | 5946 | 		    printk(KERN_ALERT "scsi%d : could not halt NCR chip\n",  | 
 | 5947 | 			host->host_no); | 
 | 5948 | 		    disable (host); | 
 | 5949 | 	    	} | 
 | 5950 |     	    } | 
 | 5951 | 	} | 
 | 5952 | 	if (!(istat & (ISTAT_SIP|ISTAT_DIP))) { | 
 | 5953 | 	    if (stage == 0) | 
 | 5954 | 	    	++stage; | 
 | 5955 | 	    else if (stage == 3) | 
 | 5956 | 		break; | 
 | 5957 | 	} | 
 | 5958 |     } | 
 | 5959 |     hostdata->state = STATE_HALTED; | 
 | 5960 |     local_irq_restore(flags); | 
 | 5961 | #if 0 | 
 | 5962 |     print_lots (host); | 
 | 5963 | #endif | 
 | 5964 |     return 0; | 
 | 5965 | } | 
 | 5966 |  | 
 | 5967 | /*  | 
 | 5968 |  * Function: event_name (int event) | 
 | 5969 |  *  | 
 | 5970 |  * Purpose: map event enum into user-readable strings. | 
 | 5971 |  */ | 
 | 5972 |  | 
 | 5973 | static const char * | 
 | 5974 | event_name (int event) { | 
 | 5975 |     switch (event) { | 
 | 5976 |     case EVENT_NONE:		return "none"; | 
 | 5977 |     case EVENT_ISSUE_QUEUE:	return "to issue queue"; | 
 | 5978 |     case EVENT_START_QUEUE:	return "to start queue"; | 
 | 5979 |     case EVENT_SELECT:		return "selected"; | 
 | 5980 |     case EVENT_DISCONNECT:	return "disconnected"; | 
 | 5981 |     case EVENT_RESELECT:	return "reselected"; | 
 | 5982 |     case EVENT_COMPLETE:	return "completed"; | 
 | 5983 |     case EVENT_IDLE:		return "idle"; | 
 | 5984 |     case EVENT_SELECT_FAILED:	return "select failed"; | 
 | 5985 |     case EVENT_BEFORE_SELECT:	return "before select"; | 
 | 5986 |     case EVENT_RESELECT_FAILED:	return "reselect failed"; | 
 | 5987 |     default:			return "unknown"; | 
 | 5988 |     } | 
 | 5989 | } | 
 | 5990 |  | 
 | 5991 | /* | 
 | 5992 |  * Function : void dump_events (struct Scsi_Host *host, count) | 
 | 5993 |  * | 
 | 5994 |  * Purpose : print last count events which have occurred. | 
 | 5995 |  */  | 
 | 5996 | static void | 
 | 5997 | dump_events (struct Scsi_Host *host, int count) { | 
 | 5998 |     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) | 
 | 5999 | 	host->hostdata[0]; | 
 | 6000 |     struct NCR53c7x0_event event; | 
 | 6001 |     int i; | 
 | 6002 |     unsigned long flags; | 
 | 6003 |     if (hostdata->events) { | 
 | 6004 | 	if (count > hostdata->event_size) | 
 | 6005 | 	    count = hostdata->event_size; | 
 | 6006 | 	for (i = hostdata->event_index; count > 0;  | 
 | 6007 | 	    i = (i ? i - 1 : hostdata->event_size -1), --count) { | 
 | 6008 | /* | 
 | 6009 |  * By copying the event we're currently examining with interrupts | 
 | 6010 |  * disabled, we can do multiple printk(), etc. operations and  | 
 | 6011 |  * still be guaranteed that they're happening on the same  | 
 | 6012 |  * event structure. | 
 | 6013 |  */ | 
 | 6014 | 	    local_irq_save(flags); | 
 | 6015 | #if 0 | 
 | 6016 | 	    event = hostdata->events[i]; | 
 | 6017 | #else | 
 | 6018 | 	    memcpy ((void *) &event, (void *) &(hostdata->events[i]), | 
 | 6019 | 		sizeof(event)); | 
 | 6020 | #endif | 
 | 6021 |  | 
 | 6022 | 	    local_irq_restore(flags); | 
 | 6023 | 	    printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n", | 
 | 6024 | 		host->host_no, event_name (event.event), count, | 
 | 6025 | 		(long) event.time.tv_sec, (long) event.time.tv_usec, | 
 | 6026 | 		event.target, event.lun); | 
 | 6027 | 	    if (event.dsa)  | 
 | 6028 | 		printk ("         event for dsa 0x%lx (virt 0x%p)\n",  | 
 | 6029 | 		    virt_to_bus(event.dsa), event.dsa); | 
 | 6030 | 	    if (event.pid != -1) { | 
 | 6031 | 		printk ("         event for pid %ld ", event.pid); | 
 | db9dff3 | 2005-04-03 14:53:59 -0500 | [diff] [blame] | 6032 | 		__scsi_print_command (event.cmnd); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6033 | 	    } | 
 | 6034 | 	} | 
 | 6035 |     } | 
 | 6036 | } | 
 | 6037 |  | 
 | 6038 | /* | 
 | 6039 |  * Function: check_address | 
 | 6040 |  * | 
 | 6041 |  * Purpose: Check to see if a possibly corrupt pointer will fault the  | 
 | 6042 |  *	kernel. | 
 | 6043 |  * | 
 | 6044 |  * Inputs: addr - address; size - size of area | 
 | 6045 |  * | 
 | 6046 |  * Returns: 0 if area is OK, -1 on error. | 
 | 6047 |  * | 
 | 6048 |  * NOTES: should be implemented in terms of vverify on kernels  | 
 | 6049 |  *	that have it. | 
 | 6050 |  */ | 
 | 6051 |  | 
 | 6052 | static int  | 
 | 6053 | check_address (unsigned long addr, int size) { | 
 | 6054 |     return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ?  -1 : 0); | 
 | 6055 | } | 
 | 6056 |  | 
 | 6057 | #ifdef MODULE | 
 | 6058 | int  | 
 | 6059 | NCR53c7x0_release(struct Scsi_Host *host) { | 
 | 6060 |     struct NCR53c7x0_hostdata *hostdata =  | 
 | 6061 | 	(struct NCR53c7x0_hostdata *) host->hostdata[0]; | 
 | 6062 |     struct NCR53c7x0_cmd *cmd, *tmp; | 
 | 6063 |     shutdown (host); | 
 | 6064 |     if (host->irq != SCSI_IRQ_NONE) | 
 | 6065 | 	{ | 
 | 6066 | 	    int irq_count; | 
 | 6067 | 	    struct Scsi_Host *tmp; | 
 | 6068 | 	    for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next) | 
 | 6069 | 		if (tmp->hostt == the_template && tmp->irq == host->irq) | 
 | 6070 | 		    ++irq_count; | 
 | 6071 | 	    if (irq_count == 1) | 
 | 6072 | 		free_irq(host->irq, NULL); | 
 | 6073 | 	} | 
 | 6074 |     if (host->dma_channel != DMA_NONE) | 
 | 6075 | 	free_dma(host->dma_channel); | 
 | 6076 |     if (host->io_port) | 
 | 6077 | 	release_region(host->io_port, host->n_io_port); | 
 | 6078 |      | 
 | 6079 |     for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp,  | 
 | 6080 | 	--hostdata->num_cmds) { | 
 | 6081 | 	tmp = (struct NCR53c7x0_cmd *) cmd->next; | 
 | 6082 |     /*  | 
 | 6083 |      * If we're going to loop, try to stop it to get a more accurate | 
 | 6084 |      * count of the leaked commands. | 
 | 6085 |      */ | 
 | 6086 | 	cmd->next = NULL; | 
 | 6087 | 	if (cmd->free) | 
 | 6088 | 	    cmd->free ((void *) cmd->real, cmd->size); | 
 | 6089 |     } | 
 | 6090 |     if (hostdata->num_cmds) | 
 | 6091 | 	printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n", | 
 | 6092 | 	    host->host_no, hostdata->num_cmds); | 
| Jesper Juhl | f9101210 | 2005-09-10 00:26:54 -0700 | [diff] [blame] | 6093 |  | 
 | 6094 |     vfree(hostdata->events); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 6095 |  | 
 | 6096 |     /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which | 
 | 6097 |      * XXX may be invalid (CONFIG_060_WRITETHROUGH) | 
 | 6098 |      */ | 
 | 6099 |     kernel_set_cachemode((void *)hostdata, 8192, IOMAP_FULL_CACHING); | 
 | 6100 |     free_pages ((u32)hostdata, 1); | 
 | 6101 |     return 1; | 
 | 6102 | } | 
 | 6103 | #endif /* def MODULE */ |