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