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