|
|
1.1 ! root 1: /* ! 2: * in2000.c - Linux device driver for the ! 3: * Always IN2000 ISA SCSI card. ! 4: * ! 5: * Copyright (c) 1996 John Shifflett, GeoLog Consulting ! 6: * [email protected] ! 7: * [email protected] ! 8: * ! 9: * This program is free software; you can redistribute it and/or modify ! 10: * it under the terms of the GNU General Public License as published by ! 11: * the Free Software Foundation; either version 2, or (at your option) ! 12: * any later version. ! 13: * ! 14: * This program is distributed in the hope that it will be useful, ! 15: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 17: * GNU General Public License for more details. ! 18: * ! 19: * ! 20: * Drew Eckhardt's excellent 'Generic NCR5380' sources provided ! 21: * much of the inspiration and some of the code for this driver. ! 22: * The Linux IN2000 driver distributed in the Linux kernels through ! 23: * version 1.2.13 was an extremely valuable reference on the arcane ! 24: * (and still mysterious) workings of the IN2000's fifo. It also ! 25: * is where I lifted in2000_biosparam(), the gist of the card ! 26: * detection scheme, and other bits of code. Many thanks to the ! 27: * talented and courageous people who wrote, contributed to, and ! 28: * maintained that driver (including Brad McLean, Shaun Savage, ! 29: * Bill Earnest, Larry Doolittle, Roger Sunshine, John Luckey, ! 30: * Matt Postiff, Peter Lu, [email protected], and Eric ! 31: * Youngdale). I should also mention the driver written by ! 32: * Hamish Macdonald for the (GASP!) Amiga A2091 card, included ! 33: * in the Linux-m68k distribution; it gave me a good initial ! 34: * understanding of the proper way to run a WD33c93 chip, and I ! 35: * ended up stealing lots of code from it. ! 36: * ! 37: * _This_ driver is (I feel) an improvement over the old one in ! 38: * several respects: ! 39: * - All problems relating to the data size of a SCSI request are ! 40: * gone (as far as I know). The old driver couldn't handle ! 41: * swapping to partitions because that involved 4k blocks, nor ! 42: * could it deal with the st.c tape driver unmodified, because ! 43: * that usually involved 4k - 32k blocks. The old driver never ! 44: * quite got away from a morbid dependence on 2k block sizes - ! 45: * which of course is the size of the card's fifo. ! 46: * ! 47: * - Target Disconnection/Reconnection is now supported. Any ! 48: * system with more than one device active on the SCSI bus ! 49: * will benefit from this. The driver defaults to what I'm ! 50: * calling 'adaptive disconnect' - meaning that each command ! 51: * is evaluated individually as to whether or not it should ! 52: * be run with the option to disconnect/reselect (if the ! 53: * device chooses), or as a "SCSI-bus-hog". ! 54: * ! 55: * - Synchronous data transfers are now supported. Because there ! 56: * are a few devices (and many improperly terminated systems) ! 57: * that choke when doing sync, the default is sync DISABLED ! 58: * for all devices. This faster protocol can (and should!) ! 59: * be enabled on selected devices via the command-line. ! 60: * ! 61: * - Runtime operating parameters can now be specified through ! 62: * either the LILO or the 'insmod' command line. For LILO do: ! 63: * "in2000=blah,blah,blah" ! 64: * and with insmod go like: ! 65: * "insmod /usr/src/linux/modules/in2000.o setup_strings=blah,blah" ! 66: * The defaults should be good for most people. See the comment ! 67: * for 'setup_strings' below for more details. ! 68: * ! 69: * - The old driver relied exclusively on what the Western Digital ! 70: * docs call "Combination Level 2 Commands", which are a great ! 71: * idea in that the CPU is relieved of a lot of interrupt ! 72: * overhead. However, by accepting a certain (user-settable) ! 73: * amount of additional interrupts, this driver achieves ! 74: * better control over the SCSI bus, and data transfers are ! 75: * almost as fast while being much easier to define, track, ! 76: * and debug. ! 77: * ! 78: * - You can force detection of a card whose BIOS has been disabled. ! 79: * ! 80: * - Multiple IN2000 cards might almost be supported. I've tried to ! 81: * keep it in mind, but have no way to test... ! 82: * ! 83: * ! 84: * TODO: ! 85: * tagged queuing. multiple cards. ! 86: * ! 87: * ! 88: * NOTE: ! 89: * When using this or any other SCSI driver as a module, you'll ! 90: * find that with the stock kernel, at most _two_ SCSI hard ! 91: * drives will be linked into the device list (ie, usable). ! 92: * If your IN2000 card has more than 2 disks on its bus, you ! 93: * might want to change the define of 'SD_EXTRA_DEVS' in the ! 94: * 'hosts.h' file from 2 to whatever is appropriate. It took ! 95: * me a while to track down this surprisingly obscure and ! 96: * undocumented little "feature". ! 97: * ! 98: * ! 99: * People with bug reports, wish-lists, complaints, comments, ! 100: * or improvements are asked to pah-leeez email me (John Shifflett) ! 101: * at [email protected] or [email protected]! I'm anxious to get ! 102: * this thing into as good a shape as possible, and I'm positive ! 103: * there are lots of lurking bugs and "Stupid Places". ! 104: * ! 105: */ ! 106: ! 107: #include <linux/module.h> ! 108: ! 109: #include <asm/system.h> ! 110: #include <linux/sched.h> ! 111: #include <linux/string.h> ! 112: #include <linux/delay.h> ! 113: #include <linux/proc_fs.h> ! 114: #include <asm/io.h> ! 115: #include <linux/ioport.h> ! 116: #include <linux/blkdev.h> ! 117: ! 118: #include <linux/blk.h> ! 119: #include <linux/stat.h> ! 120: ! 121: #include "scsi.h" ! 122: #include "sd.h" ! 123: #include "hosts.h" ! 124: ! 125: #define IN2000_VERSION "1.33" ! 126: #define IN2000_DATE "26/August/1998" ! 127: ! 128: #include "in2000.h" ! 129: ! 130: ! 131: /* ! 132: * 'setup_strings' is a single string used to pass operating parameters and ! 133: * settings from the kernel/module command-line to the driver. 'setup_args[]' ! 134: * is an array of strings that define the compile-time default values for ! 135: * these settings. If Linux boots with a LILO or insmod command-line, those ! 136: * settings are combined with 'setup_args[]'. Note that LILO command-lines ! 137: * are prefixed with "in2000=" while insmod uses a "setup_strings=" prefix. ! 138: * The driver recognizes the following keywords (lower case required) and ! 139: * arguments: ! 140: * ! 141: * - ioport:addr -Where addr is IO address of a (usually ROM-less) card. ! 142: * - noreset -No optional args. Prevents SCSI bus reset at boot time. ! 143: * - nosync:x -x is a bitmask where the 1st 7 bits correspond with ! 144: * the 7 possible SCSI devices (bit 0 for device #0, etc). ! 145: * Set a bit to PREVENT sync negotiation on that device. ! 146: * The driver default is sync DISABLED on all devices. ! 147: * - period:ns -ns is the minimum # of nanoseconds in a SCSI data transfer ! 148: * period. Default is 500; acceptable values are 250 - 1000. ! 149: * - disconnect:x -x = 0 to never allow disconnects, 2 to always allow them. ! 150: * x = 1 does 'adaptive' disconnects, which is the default ! 151: * and generally the best choice. ! 152: * - debug:x -If 'DEBUGGING_ON' is defined, x is a bitmask that causes ! 153: * various types of debug output to printed - see the DB_xxx ! 154: * defines in in2000.h ! 155: * - proc:x -If 'PROC_INTERFACE' is defined, x is a bitmask that ! 156: * determines how the /proc interface works and what it ! 157: * does - see the PR_xxx defines in in2000.h ! 158: * ! 159: * Syntax Notes: ! 160: * - Numeric arguments can be decimal or the '0x' form of hex notation. There ! 161: * _must_ be a colon between a keyword and its numeric argument, with no ! 162: * spaces. ! 163: * - Keywords are separated by commas, no spaces, in the standard kernel ! 164: * command-line manner. ! 165: * - A keyword in the 'nth' comma-separated command-line member will overwrite ! 166: * the 'nth' element of setup_args[]. A blank command-line member (in ! 167: * other words, a comma with no preceding keyword) will _not_ overwrite ! 168: * the corresponding setup_args[] element. ! 169: * ! 170: * A few LILO examples (for insmod, use 'setup_strings' instead of 'in2000'): ! 171: * - in2000=ioport:0x220,noreset ! 172: * - in2000=period:250,disconnect:2,nosync:0x03 ! 173: * - in2000=debug:0x1e ! 174: * - in2000=proc:3 ! 175: */ ! 176: ! 177: /* Normally, no defaults are specified... */ ! 178: static char *setup_args[] = ! 179: {"","","","","","","","",""}; ! 180: ! 181: /* filled in by 'insmod' */ ! 182: static char *setup_strings = 0; ! 183: ! 184: #ifdef MODULE_PARM ! 185: MODULE_PARM(setup_strings, "s"); ! 186: #endif ! 187: ! 188: ! 189: static struct Scsi_Host *instance_list = 0; ! 190: ! 191: ! 192: ! 193: static inline uchar read_3393(struct IN2000_hostdata *hostdata, uchar reg_num) ! 194: { ! 195: write1_io(reg_num,IO_WD_ADDR); ! 196: return read1_io(IO_WD_DATA); ! 197: } ! 198: ! 199: ! 200: #define READ_AUX_STAT() read1_io(IO_WD_ASR) ! 201: ! 202: ! 203: static inline void write_3393(struct IN2000_hostdata *hostdata, uchar reg_num, uchar value) ! 204: { ! 205: write1_io(reg_num,IO_WD_ADDR); ! 206: write1_io(value,IO_WD_DATA); ! 207: } ! 208: ! 209: ! 210: static inline void write_3393_cmd(struct IN2000_hostdata *hostdata, uchar cmd) ! 211: { ! 212: /* while (READ_AUX_STAT() & ASR_CIP) ! 213: printk("|");*/ ! 214: write1_io(WD_COMMAND,IO_WD_ADDR); ! 215: write1_io(cmd,IO_WD_DATA); ! 216: } ! 217: ! 218: ! 219: static uchar read_1_byte(struct IN2000_hostdata *hostdata) ! 220: { ! 221: uchar asr, x = 0; ! 222: ! 223: write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); ! 224: write_3393_cmd(hostdata,WD_CMD_TRANS_INFO|0x80); ! 225: do { ! 226: asr = READ_AUX_STAT(); ! 227: if (asr & ASR_DBR) ! 228: x = read_3393(hostdata,WD_DATA); ! 229: } while (!(asr & ASR_INT)); ! 230: return x; ! 231: } ! 232: ! 233: ! 234: static void write_3393_count(struct IN2000_hostdata *hostdata, unsigned long value) ! 235: { ! 236: write1_io(WD_TRANSFER_COUNT_MSB,IO_WD_ADDR); ! 237: write1_io((value >> 16),IO_WD_DATA); ! 238: write1_io((value >> 8),IO_WD_DATA); ! 239: write1_io(value,IO_WD_DATA); ! 240: } ! 241: ! 242: ! 243: static unsigned long read_3393_count(struct IN2000_hostdata *hostdata) ! 244: { ! 245: unsigned long value; ! 246: ! 247: write1_io(WD_TRANSFER_COUNT_MSB,IO_WD_ADDR); ! 248: value = read1_io(IO_WD_DATA) << 16; ! 249: value |= read1_io(IO_WD_DATA) << 8; ! 250: value |= read1_io(IO_WD_DATA); ! 251: return value; ! 252: } ! 253: ! 254: ! 255: /* The 33c93 needs to be told which direction a command transfers its ! 256: * data; we use this function to figure it out. Returns true if there ! 257: * will be a DATA_OUT phase with this command, false otherwise. ! 258: * (Thanks to Joerg Dorchain for the research and suggestion.) ! 259: */ ! 260: static int is_dir_out(Scsi_Cmnd *cmd) ! 261: { ! 262: switch (cmd->cmnd[0]) { ! 263: case WRITE_6: case WRITE_10: case WRITE_12: ! 264: case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: ! 265: case WRITE_VERIFY: case WRITE_VERIFY_12: ! 266: case COMPARE: case COPY: case COPY_VERIFY: ! 267: case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: ! 268: case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: ! 269: case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: ! 270: case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: ! 271: case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: ! 272: case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: ! 273: case 0xea: ! 274: return 1; ! 275: default: ! 276: return 0; ! 277: } ! 278: } ! 279: ! 280: ! 281: ! 282: static struct sx_period sx_table[] = { ! 283: { 1, 0x20}, ! 284: {252, 0x20}, ! 285: {376, 0x30}, ! 286: {500, 0x40}, ! 287: {624, 0x50}, ! 288: {752, 0x60}, ! 289: {876, 0x70}, ! 290: {1000,0x00}, ! 291: {0, 0} }; ! 292: ! 293: static int round_period(unsigned int period) ! 294: { ! 295: int x; ! 296: ! 297: for (x=1; sx_table[x].period_ns; x++) { ! 298: if ((period <= sx_table[x-0].period_ns) && ! 299: (period > sx_table[x-1].period_ns)) { ! 300: return x; ! 301: } ! 302: } ! 303: return 7; ! 304: } ! 305: ! 306: static uchar calc_sync_xfer(unsigned int period, unsigned int offset) ! 307: { ! 308: uchar result; ! 309: ! 310: period *= 4; /* convert SDTR code to ns */ ! 311: result = sx_table[round_period(period)].reg_value; ! 312: result |= (offset < OPTIMUM_SX_OFF)?offset:OPTIMUM_SX_OFF; ! 313: return result; ! 314: } ! 315: ! 316: ! 317: ! 318: static void in2000_execute(struct Scsi_Host *instance); ! 319: ! 320: int in2000_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) ! 321: { ! 322: struct IN2000_hostdata *hostdata; ! 323: Scsi_Cmnd *tmp; ! 324: unsigned long flags; ! 325: ! 326: hostdata = (struct IN2000_hostdata *)cmd->host->hostdata; ! 327: ! 328: DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) ! 329: ! 330: /* Set up a few fields in the Scsi_Cmnd structure for our own use: ! 331: * - host_scribble is the pointer to the next cmd in the input queue ! 332: * - scsi_done points to the routine we call when a cmd is finished ! 333: * - result is what you'd expect ! 334: */ ! 335: ! 336: cmd->host_scribble = NULL; ! 337: cmd->scsi_done = done; ! 338: cmd->result = 0; ! 339: ! 340: /* We use the Scsi_Pointer structure that's included with each command ! 341: * as a scratchpad (as it's intended to be used!). The handy thing about ! 342: * the SCp.xxx fields is that they're always associated with a given ! 343: * cmd, and are preserved across disconnect-reselect. This means we ! 344: * can pretty much ignore SAVE_POINTERS and RESTORE_POINTERS messages ! 345: * if we keep all the critical pointers and counters in SCp: ! 346: * - SCp.ptr is the pointer into the RAM buffer ! 347: * - SCp.this_residual is the size of that buffer ! 348: * - SCp.buffer points to the current scatter-gather buffer ! 349: * - SCp.buffers_residual tells us how many S.G. buffers there are ! 350: * - SCp.have_data_in helps keep track of >2048 byte transfers ! 351: * - SCp.sent_command is not used ! 352: * - SCp.phase records this command's SRCID_ER bit setting ! 353: */ ! 354: ! 355: if (cmd->use_sg) { ! 356: cmd->SCp.buffer = (struct scatterlist *)cmd->buffer; ! 357: cmd->SCp.buffers_residual = cmd->use_sg - 1; ! 358: cmd->SCp.ptr = (char *)cmd->SCp.buffer->address; ! 359: cmd->SCp.this_residual = cmd->SCp.buffer->length; ! 360: } ! 361: else { ! 362: cmd->SCp.buffer = NULL; ! 363: cmd->SCp.buffers_residual = 0; ! 364: cmd->SCp.ptr = (char *)cmd->request_buffer; ! 365: cmd->SCp.this_residual = cmd->request_bufflen; ! 366: } ! 367: cmd->SCp.have_data_in = 0; ! 368: ! 369: /* We don't set SCp.phase here - that's done in in2000_execute() */ ! 370: ! 371: /* WD docs state that at the conclusion of a "LEVEL2" command, the ! 372: * status byte can be retrieved from the LUN register. Apparently, ! 373: * this is the case only for *uninterrupted* LEVEL2 commands! If ! 374: * there are any unexpected phases entered, even if they are 100% ! 375: * legal (different devices may choose to do things differently), ! 376: * the LEVEL2 command sequence is exited. This often occurs prior ! 377: * to receiving the status byte, in which case the driver does a ! 378: * status phase interrupt and gets the status byte on its own. ! 379: * While such a command can then be "resumed" (ie restarted to ! 380: * finish up as a LEVEL2 command), the LUN register will NOT be ! 381: * a valid status byte at the command's conclusion, and we must ! 382: * use the byte obtained during the earlier interrupt. Here, we ! 383: * preset SCp.Status to an illegal value (0xff) so that when ! 384: * this command finally completes, we can tell where the actual ! 385: * status byte is stored. ! 386: */ ! 387: ! 388: cmd->SCp.Status = ILLEGAL_STATUS_BYTE; ! 389: ! 390: /* We need to disable interrupts before messing with the input ! 391: * queue and calling in2000_execute(). ! 392: */ ! 393: ! 394: save_flags(flags); ! 395: cli(); ! 396: ! 397: /* ! 398: * Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE ! 399: * commands are added to the head of the queue so that the desired ! 400: * sense data is not lost before REQUEST_SENSE executes. ! 401: */ ! 402: ! 403: if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) { ! 404: cmd->host_scribble = (uchar *)hostdata->input_Q; ! 405: hostdata->input_Q = cmd; ! 406: } ! 407: else { /* find the end of the queue */ ! 408: for (tmp=(Scsi_Cmnd *)hostdata->input_Q; tmp->host_scribble; ! 409: tmp=(Scsi_Cmnd *)tmp->host_scribble) ! 410: ; ! 411: tmp->host_scribble = (uchar *)cmd; ! 412: } ! 413: ! 414: /* We know that there's at least one command in 'input_Q' now. ! 415: * Go see if any of them are runnable! ! 416: */ ! 417: ! 418: in2000_execute(cmd->host); ! 419: ! 420: DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid)) ! 421: ! 422: restore_flags(flags); ! 423: return 0; ! 424: } ! 425: ! 426: ! 427: ! 428: /* ! 429: * This routine attempts to start a scsi command. If the host_card is ! 430: * already connected, we give up immediately. Otherwise, look through ! 431: * the input_Q, using the first command we find that's intended ! 432: * for a currently non-busy target/lun. ! 433: * Note that this function is always called with interrupts already ! 434: * disabled (either from in2000_queuecommand() or in2000_intr()). ! 435: */ ! 436: static void in2000_execute (struct Scsi_Host *instance) ! 437: { ! 438: struct IN2000_hostdata *hostdata; ! 439: Scsi_Cmnd *cmd, *prev; ! 440: int i; ! 441: unsigned short *sp; ! 442: unsigned short f; ! 443: unsigned short flushbuf[16]; ! 444: ! 445: ! 446: hostdata = (struct IN2000_hostdata *)instance->hostdata; ! 447: ! 448: DB(DB_EXECUTE,printk("EX(")) ! 449: ! 450: if (hostdata->selecting || hostdata->connected) { ! 451: ! 452: DB(DB_EXECUTE,printk(")EX-0 ")) ! 453: ! 454: return; ! 455: } ! 456: ! 457: /* ! 458: * Search through the input_Q for a command destined ! 459: * for an idle target/lun. ! 460: */ ! 461: ! 462: cmd = (Scsi_Cmnd *)hostdata->input_Q; ! 463: prev = 0; ! 464: while (cmd) { ! 465: if (!(hostdata->busy[cmd->target] & (1 << cmd->lun))) ! 466: break; ! 467: prev = cmd; ! 468: cmd = (Scsi_Cmnd *)cmd->host_scribble; ! 469: } ! 470: ! 471: /* quit if queue empty or all possible targets are busy */ ! 472: ! 473: if (!cmd) { ! 474: ! 475: DB(DB_EXECUTE,printk(")EX-1 ")) ! 476: ! 477: return; ! 478: } ! 479: ! 480: /* remove command from queue */ ! 481: ! 482: if (prev) ! 483: prev->host_scribble = cmd->host_scribble; ! 484: else ! 485: hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble; ! 486: ! 487: #ifdef PROC_STATISTICS ! 488: hostdata->cmd_cnt[cmd->target]++; ! 489: #endif ! 490: ! 491: /* ! 492: * Start the selection process ! 493: */ ! 494: ! 495: if (is_dir_out(cmd)) ! 496: write_3393(hostdata,WD_DESTINATION_ID, cmd->target); ! 497: else ! 498: write_3393(hostdata,WD_DESTINATION_ID, cmd->target | DSTID_DPD); ! 499: ! 500: /* Now we need to figure out whether or not this command is a good ! 501: * candidate for disconnect/reselect. We guess to the best of our ! 502: * ability, based on a set of hierarchical rules. When several ! 503: * devices are operating simultaneously, disconnects are usually ! 504: * an advantage. In a single device system, or if only 1 device ! 505: * is being accessed, transfers usually go faster if disconnects ! 506: * are not allowed: ! 507: * ! 508: * + Commands should NEVER disconnect if hostdata->disconnect = ! 509: * DIS_NEVER (this holds for tape drives also), and ALWAYS ! 510: * disconnect if hostdata->disconnect = DIS_ALWAYS. ! 511: * + Tape drive commands should always be allowed to disconnect. ! 512: * + Disconnect should be allowed if disconnected_Q isn't empty. ! 513: * + Commands should NOT disconnect if input_Q is empty. ! 514: * + Disconnect should be allowed if there are commands in input_Q ! 515: * for a different target/lun. In this case, the other commands ! 516: * should be made disconnect-able, if not already. ! 517: * ! 518: * I know, I know - this code would flunk me out of any ! 519: * "C Programming 101" class ever offered. But it's easy ! 520: * to change around and experiment with for now. ! 521: */ ! 522: ! 523: cmd->SCp.phase = 0; /* assume no disconnect */ ! 524: if (hostdata->disconnect == DIS_NEVER) ! 525: goto no; ! 526: if (hostdata->disconnect == DIS_ALWAYS) ! 527: goto yes; ! 528: if (cmd->device->type == 1) /* tape drive? */ ! 529: goto yes; ! 530: if (hostdata->disconnected_Q) /* other commands disconnected? */ ! 531: goto yes; ! 532: if (!(hostdata->input_Q)) /* input_Q empty? */ ! 533: goto no; ! 534: for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev; ! 535: prev=(Scsi_Cmnd *)prev->host_scribble) { ! 536: if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) { ! 537: for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev; ! 538: prev=(Scsi_Cmnd *)prev->host_scribble) ! 539: prev->SCp.phase = 1; ! 540: goto yes; ! 541: } ! 542: } ! 543: goto no; ! 544: ! 545: yes: ! 546: cmd->SCp.phase = 1; ! 547: ! 548: #ifdef PROC_STATISTICS ! 549: hostdata->disc_allowed_cnt[cmd->target]++; ! 550: #endif ! 551: ! 552: no: ! 553: write_3393(hostdata,WD_SOURCE_ID,((cmd->SCp.phase)?SRCID_ER:0)); ! 554: ! 555: write_3393(hostdata,WD_TARGET_LUN, cmd->lun); ! 556: write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]); ! 557: hostdata->busy[cmd->target] |= (1 << cmd->lun); ! 558: ! 559: if ((hostdata->level2 <= L2_NONE) || ! 560: (hostdata->sync_stat[cmd->target] == SS_UNSET)) { ! 561: ! 562: /* ! 563: * Do a 'Select-With-ATN' command. This will end with ! 564: * one of the following interrupts: ! 565: * CSR_RESEL_AM: failure - can try again later. ! 566: * CSR_TIMEOUT: failure - give up. ! 567: * CSR_SELECT: success - proceed. ! 568: */ ! 569: ! 570: hostdata->selecting = cmd; ! 571: ! 572: /* Every target has its own synchronous transfer setting, kept in ! 573: * the sync_xfer array, and a corresponding status byte in sync_stat[]. ! 574: * Each target's sync_stat[] entry is initialized to SS_UNSET, and its ! 575: * sync_xfer[] entry is initialized to the default/safe value. SS_UNSET ! 576: * means that the parameters are undetermined as yet, and that we ! 577: * need to send an SDTR message to this device after selection is ! 578: * complete. We set SS_FIRST to tell the interrupt routine to do so, ! 579: * unless we don't want to even _try_ synchronous transfers: In this ! 580: * case we set SS_SET to make the defaults final. ! 581: */ ! 582: if (hostdata->sync_stat[cmd->target] == SS_UNSET) { ! 583: if (hostdata->sync_off & (1 << cmd->target)) ! 584: hostdata->sync_stat[cmd->target] = SS_SET; ! 585: else ! 586: hostdata->sync_stat[cmd->target] = SS_FIRST; ! 587: } ! 588: hostdata->state = S_SELECTING; ! 589: write_3393_count(hostdata,0); /* this guarantees a DATA_PHASE interrupt */ ! 590: write_3393_cmd(hostdata,WD_CMD_SEL_ATN); ! 591: } ! 592: ! 593: else { ! 594: ! 595: /* ! 596: * Do a 'Select-With-ATN-Xfer' command. This will end with ! 597: * one of the following interrupts: ! 598: * CSR_RESEL_AM: failure - can try again later. ! 599: * CSR_TIMEOUT: failure - give up. ! 600: * anything else: success - proceed. ! 601: */ ! 602: ! 603: hostdata->connected = cmd; ! 604: write_3393(hostdata,WD_COMMAND_PHASE, 0); ! 605: ! 606: /* copy command_descriptor_block into WD chip ! 607: * (take advantage of auto-incrementing) ! 608: */ ! 609: ! 610: write1_io(WD_CDB_1, IO_WD_ADDR); ! 611: for (i=0; i<cmd->cmd_len; i++) ! 612: write1_io(cmd->cmnd[i], IO_WD_DATA); ! 613: ! 614: /* The wd33c93 only knows about Group 0, 1, and 5 commands when ! 615: * it's doing a 'select-and-transfer'. To be safe, we write the ! 616: * size of the CDB into the OWN_ID register for every case. This ! 617: * way there won't be problems with vendor-unique, audio, etc. ! 618: */ ! 619: ! 620: write_3393(hostdata, WD_OWN_ID, cmd->cmd_len); ! 621: ! 622: /* When doing a non-disconnect command, we can save ourselves a DATA ! 623: * phase interrupt later by setting everything up now. With writes we ! 624: * need to pre-fill the fifo; if there's room for the 32 flush bytes, ! 625: * put them in there too - that'll avoid a fifo interrupt. Reads are ! 626: * somewhat simpler. ! 627: * KLUDGE NOTE: It seems that you can't completely fill the fifo here: ! 628: * This results in the IO_FIFO_COUNT register rolling over to zero, ! 629: * and apparently the gate array logic sees this as empty, not full, ! 630: * so the 3393 chip is never signalled to start reading from the ! 631: * fifo. Or maybe it's seen as a permanent fifo interrupt condition. ! 632: * Regardless, we fix this by temporarily pretending that the fifo ! 633: * is 16 bytes smaller. (I see now that the old driver has a comment ! 634: * about "don't fill completely" in an analogous place - must be the ! 635: * same deal.) This results in CDROM, swap partitions, and tape drives ! 636: * needing an extra interrupt per write command - I think we can live ! 637: * with that! ! 638: */ ! 639: ! 640: if (!(cmd->SCp.phase)) { ! 641: write_3393_count(hostdata, cmd->SCp.this_residual); ! 642: write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); ! 643: write1_io(0, IO_FIFO_WRITE); /* clear fifo counter, write mode */ ! 644: ! 645: if (is_dir_out(cmd)) { ! 646: hostdata->fifo = FI_FIFO_WRITING; ! 647: if ((i = cmd->SCp.this_residual) > (IN2000_FIFO_SIZE - 16) ) ! 648: i = IN2000_FIFO_SIZE - 16; ! 649: cmd->SCp.have_data_in = i; /* this much data in fifo */ ! 650: i >>= 1; /* Gulp. Assuming modulo 2. */ ! 651: sp = (unsigned short *)cmd->SCp.ptr; ! 652: f = hostdata->io_base + IO_FIFO; ! 653: ! 654: #ifdef FAST_WRITE_IO ! 655: ! 656: FAST_WRITE2_IO(); ! 657: #else ! 658: while (i--) ! 659: write2_io(*sp++,IO_FIFO); ! 660: ! 661: #endif ! 662: ! 663: /* Is there room for the flush bytes? */ ! 664: ! 665: if (cmd->SCp.have_data_in <= ((IN2000_FIFO_SIZE - 16) - 32)) { ! 666: sp = flushbuf; ! 667: i = 16; ! 668: ! 669: #ifdef FAST_WRITE_IO ! 670: ! 671: FAST_WRITE2_IO(); ! 672: #else ! 673: while (i--) ! 674: write2_io(0,IO_FIFO); ! 675: ! 676: #endif ! 677: ! 678: } ! 679: } ! 680: ! 681: else { ! 682: write1_io(0, IO_FIFO_READ); /* put fifo in read mode */ ! 683: hostdata->fifo = FI_FIFO_READING; ! 684: cmd->SCp.have_data_in = 0; /* nothing transfered yet */ ! 685: } ! 686: ! 687: } ! 688: else { ! 689: write_3393_count(hostdata,0); /* this guarantees a DATA_PHASE interrupt */ ! 690: } ! 691: hostdata->state = S_RUNNING_LEVEL2; ! 692: write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); ! 693: } ! 694: ! 695: /* ! 696: * Since the SCSI bus can handle only 1 connection at a time, ! 697: * we get out of here now. If the selection fails, or when ! 698: * the command disconnects, we'll come back to this routine ! 699: * to search the input_Q again... ! 700: */ ! 701: ! 702: DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid)) ! 703: ! 704: } ! 705: ! 706: ! 707: ! 708: static void transfer_pio(uchar *buf, int cnt, ! 709: int data_in_dir, struct IN2000_hostdata *hostdata) ! 710: { ! 711: uchar asr; ! 712: ! 713: DB(DB_TRANSFER,printk("(%p,%d,%s)",buf,cnt,data_in_dir?"in":"out")) ! 714: ! 715: write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); ! 716: write_3393_count(hostdata,cnt); ! 717: write_3393_cmd(hostdata,WD_CMD_TRANS_INFO); ! 718: if (data_in_dir) { ! 719: do { ! 720: asr = READ_AUX_STAT(); ! 721: if (asr & ASR_DBR) ! 722: *buf++ = read_3393(hostdata,WD_DATA); ! 723: } while (!(asr & ASR_INT)); ! 724: } ! 725: else { ! 726: do { ! 727: asr = READ_AUX_STAT(); ! 728: if (asr & ASR_DBR) ! 729: write_3393(hostdata,WD_DATA, *buf++); ! 730: } while (!(asr & ASR_INT)); ! 731: } ! 732: ! 733: /* Note: we are returning with the interrupt UN-cleared. ! 734: * Since (presumably) an entire I/O operation has ! 735: * completed, the bus phase is probably different, and ! 736: * the interrupt routine will discover this when it ! 737: * responds to the uncleared int. ! 738: */ ! 739: ! 740: } ! 741: ! 742: ! 743: ! 744: static void transfer_bytes(Scsi_Cmnd *cmd, int data_in_dir) ! 745: { ! 746: struct IN2000_hostdata *hostdata; ! 747: unsigned short *sp; ! 748: unsigned short f; ! 749: int i; ! 750: ! 751: hostdata = (struct IN2000_hostdata *)cmd->host->hostdata; ! 752: ! 753: /* Normally, you'd expect 'this_residual' to be non-zero here. ! 754: * In a series of scatter-gather transfers, however, this ! 755: * routine will usually be called with 'this_residual' equal ! 756: * to 0 and 'buffers_residual' non-zero. This means that a ! 757: * previous transfer completed, clearing 'this_residual', and ! 758: * now we need to setup the next scatter-gather buffer as the ! 759: * source or destination for THIS transfer. ! 760: */ ! 761: if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { ! 762: ++cmd->SCp.buffer; ! 763: --cmd->SCp.buffers_residual; ! 764: cmd->SCp.this_residual = cmd->SCp.buffer->length; ! 765: cmd->SCp.ptr = cmd->SCp.buffer->address; ! 766: } ! 767: ! 768: /* Set up hardware registers */ ! 769: ! 770: write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]); ! 771: write_3393_count(hostdata,cmd->SCp.this_residual); ! 772: write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); ! 773: write1_io(0,IO_FIFO_WRITE); /* zero counter, assume write */ ! 774: ! 775: /* Reading is easy. Just issue the command and return - we'll ! 776: * get an interrupt later when we have actual data to worry about. ! 777: */ ! 778: ! 779: if (data_in_dir) { ! 780: write1_io(0,IO_FIFO_READ); ! 781: if ((hostdata->level2 >= L2_DATA) || ! 782: (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { ! 783: write_3393(hostdata,WD_COMMAND_PHASE,0x45); ! 784: write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); ! 785: hostdata->state = S_RUNNING_LEVEL2; ! 786: } ! 787: else ! 788: write_3393_cmd(hostdata,WD_CMD_TRANS_INFO); ! 789: hostdata->fifo = FI_FIFO_READING; ! 790: cmd->SCp.have_data_in = 0; ! 791: return; ! 792: } ! 793: ! 794: /* Writing is more involved - we'll start the WD chip and write as ! 795: * much data to the fifo as we can right now. Later interrupts will ! 796: * write any bytes that don't make it at this stage. ! 797: */ ! 798: ! 799: if ((hostdata->level2 >= L2_DATA) || ! 800: (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { ! 801: write_3393(hostdata,WD_COMMAND_PHASE,0x45); ! 802: write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); ! 803: hostdata->state = S_RUNNING_LEVEL2; ! 804: } ! 805: else ! 806: write_3393_cmd(hostdata,WD_CMD_TRANS_INFO); ! 807: hostdata->fifo = FI_FIFO_WRITING; ! 808: sp = (unsigned short *)cmd->SCp.ptr; ! 809: ! 810: if ((i = cmd->SCp.this_residual) > IN2000_FIFO_SIZE) ! 811: i = IN2000_FIFO_SIZE; ! 812: cmd->SCp.have_data_in = i; ! 813: i >>= 1; /* Gulp. We assume this_residual is modulo 2 */ ! 814: f = hostdata->io_base + IO_FIFO; ! 815: ! 816: #ifdef FAST_WRITE_IO ! 817: ! 818: FAST_WRITE2_IO(); ! 819: #else ! 820: while (i--) ! 821: write2_io(*sp++,IO_FIFO); ! 822: ! 823: #endif ! 824: ! 825: } ! 826: ! 827: ! 828: /* We need to use spin_lock_irqsave() & spin_unlock_irqrestore() in this ! 829: * function in order to work in an SMP environment. (I'd be surprised ! 830: * if the driver is ever used by anyone on a real multi-CPU motherboard, ! 831: * but it _does_ need to be able to compile and run in an SMP kernel.) ! 832: */ ! 833: ! 834: static void in2000_intr (int irqnum, void * dev_id, struct pt_regs *ptregs) ! 835: { ! 836: struct Scsi_Host *instance; ! 837: struct IN2000_hostdata *hostdata; ! 838: Scsi_Cmnd *patch, *cmd; ! 839: uchar asr, sr, phs, id, lun, *ucp, msg; ! 840: int i,j; ! 841: unsigned long length; ! 842: unsigned short *sp; ! 843: unsigned short f; ! 844: unsigned long flags; ! 845: ! 846: for (instance = instance_list; instance; instance = instance->next) { ! 847: if (instance->irq == irqnum) ! 848: break; ! 849: } ! 850: if (!instance) { ! 851: printk("*** Hmm... interrupts are screwed up! ***\n"); ! 852: return; ! 853: } ! 854: hostdata = (struct IN2000_hostdata *)instance->hostdata; ! 855: ! 856: /* Get the spin_lock and disable further ints, for SMP */ ! 857: ! 858: CLISPIN_LOCK(flags); ! 859: ! 860: #ifdef PROC_STATISTICS ! 861: hostdata->int_cnt++; ! 862: #endif ! 863: ! 864: /* The IN2000 card has 2 interrupt sources OR'ed onto its IRQ line - the ! 865: * WD3393 chip and the 2k fifo (which is actually a dual-port RAM combined ! 866: * with a big logic array, so it's a little different than what you might ! 867: * expect). As far as I know, there's no reason that BOTH can't be active ! 868: * at the same time, but there's a problem: while we can read the 3393 ! 869: * to tell if _it_ wants an interrupt, I don't know of a way to ask the ! 870: * fifo the same question. The best we can do is check the 3393 and if ! 871: * it _isn't_ the source of the interrupt, then we can be pretty sure ! 872: * that the fifo is the culprit. ! 873: * UPDATE: I have it on good authority (Bill Earnest) that bit 0 of the ! 874: * IO_FIFO_COUNT register mirrors the fifo interrupt state. I ! 875: * assume that bit clear means interrupt active. As it turns ! 876: * out, the driver really doesn't need to check for this after ! 877: * all, so my remarks above about a 'problem' can safely be ! 878: * ignored. The way the logic is set up, there's no advantage ! 879: * (that I can see) to worrying about it. ! 880: * ! 881: * It seems that the fifo interrupt signal is negated when we extract ! 882: * bytes during read or write bytes during write. ! 883: * - fifo will interrupt when data is moving from it to the 3393, and ! 884: * there are 31 (or less?) bytes left to go. This is sort of short- ! 885: * sighted: what if you don't WANT to do more? In any case, our ! 886: * response is to push more into the fifo - either actual data or ! 887: * dummy bytes if need be. Note that we apparently have to write at ! 888: * least 32 additional bytes to the fifo after an interrupt in order ! 889: * to get it to release the ones it was holding on to - writing fewer ! 890: * than 32 will result in another fifo int. ! 891: * UPDATE: Again, info from Bill Earnest makes this more understandable: ! 892: * 32 bytes = two counts of the fifo counter register. He tells ! 893: * me that the fifo interrupt is a non-latching signal derived ! 894: * from a straightforward boolean interpretation of the 7 ! 895: * highest bits of the fifo counter and the fifo-read/fifo-write ! 896: * state. Who'd a thought? ! 897: */ ! 898: ! 899: write1_io(0, IO_LED_ON); ! 900: asr = READ_AUX_STAT(); ! 901: if (!(asr & ASR_INT)) { /* no WD33c93 interrupt? */ ! 902: ! 903: /* Ok. This is definitely a FIFO-only interrupt. ! 904: * ! 905: * If FI_FIFO_READING is set, there are up to 2048 bytes waiting to be read, ! 906: * maybe more to come from the SCSI bus. Read as many as we can out of the ! 907: * fifo and into memory at the location of SCp.ptr[SCp.have_data_in], and ! 908: * update have_data_in afterwards. ! 909: * ! 910: * If we have FI_FIFO_WRITING, the FIFO has almost run out of bytes to move ! 911: * into the WD3393 chip (I think the interrupt happens when there are 31 ! 912: * bytes left, but it may be fewer...). The 3393 is still waiting, so we ! 913: * shove some more into the fifo, which gets things moving again. If the ! 914: * original SCSI command specified more than 2048 bytes, there may still ! 915: * be some of that data left: fine - use it (from SCp.ptr[SCp.have_data_in]). ! 916: * Don't forget to update have_data_in. If we've already written out the ! 917: * entire buffer, feed 32 dummy bytes to the fifo - they're needed to ! 918: * push out the remaining real data. ! 919: * (Big thanks to Bill Earnest for getting me out of the mud in here.) ! 920: */ ! 921: ! 922: cmd = (Scsi_Cmnd *)hostdata->connected; /* assume we're connected */ ! 923: CHECK_NULL(cmd,"fifo_int") ! 924: ! 925: if (hostdata->fifo == FI_FIFO_READING) { ! 926: ! 927: DB(DB_FIFO,printk("{R:%02x} ",read1_io(IO_FIFO_COUNT))) ! 928: ! 929: sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); ! 930: i = read1_io(IO_FIFO_COUNT) & 0xfe; ! 931: i <<= 2; /* # of words waiting in the fifo */ ! 932: f = hostdata->io_base + IO_FIFO; ! 933: ! 934: #ifdef FAST_READ_IO ! 935: ! 936: FAST_READ2_IO(); ! 937: #else ! 938: while (i--) ! 939: *sp++ = read2_io(IO_FIFO); ! 940: ! 941: #endif ! 942: ! 943: i = sp - (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); ! 944: i <<= 1; ! 945: cmd->SCp.have_data_in += i; ! 946: } ! 947: ! 948: else if (hostdata->fifo == FI_FIFO_WRITING) { ! 949: ! 950: DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT))) ! 951: ! 952: /* If all bytes have been written to the fifo, flush out the stragglers. ! 953: * Note that while writing 16 dummy words seems arbitrary, we don't ! 954: * have another choice that I can see. What we really want is to read ! 955: * the 3393 transfer count register (that would tell us how many bytes ! 956: * needed flushing), but the TRANSFER_INFO command hasn't completed ! 957: * yet (not enough bytes!) and that register won't be accessible. So, ! 958: * we use 16 words - a number obtained through trial and error. ! 959: * UPDATE: Bill says this is exactly what Always does, so there. ! 960: * More thanks due him for help in this section. ! 961: */ ! 962: ! 963: if (cmd->SCp.this_residual == cmd->SCp.have_data_in) { ! 964: i = 16; ! 965: while (i--) /* write 32 dummy bytes */ ! 966: write2_io(0,IO_FIFO); ! 967: } ! 968: ! 969: /* If there are still bytes left in the SCSI buffer, write as many as we ! 970: * can out to the fifo. ! 971: */ ! 972: ! 973: else { ! 974: sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); ! 975: i = cmd->SCp.this_residual - cmd->SCp.have_data_in; /* bytes yet to go */ ! 976: j = read1_io(IO_FIFO_COUNT) & 0xfe; ! 977: j <<= 2; /* how many words the fifo has room for */ ! 978: if ((j << 1) > i) ! 979: j = (i >> 1); ! 980: while (j--) ! 981: write2_io(*sp++,IO_FIFO); ! 982: ! 983: i = sp - (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); ! 984: i <<= 1; ! 985: cmd->SCp.have_data_in += i; ! 986: } ! 987: } ! 988: ! 989: else { ! 990: printk("*** Spurious FIFO interrupt ***"); ! 991: } ! 992: ! 993: write1_io(0, IO_LED_OFF); ! 994: ! 995: /* release the SMP spin_lock and restore irq state */ ! 996: CLISPIN_UNLOCK(flags); ! 997: return; ! 998: } ! 999: ! 1000: /* This interrupt was triggered by the WD33c93 chip. The fifo interrupt ! 1001: * may also be asserted, but we don't bother to check it: we get more ! 1002: * detailed info from FIFO_READING and FIFO_WRITING (see below). ! 1003: */ ! 1004: ! 1005: cmd = (Scsi_Cmnd *)hostdata->connected; /* assume we're connected */ ! 1006: sr = read_3393(hostdata,WD_SCSI_STATUS); /* clear the interrupt */ ! 1007: phs = read_3393(hostdata,WD_COMMAND_PHASE); ! 1008: ! 1009: if (!cmd && (sr != CSR_RESEL_AM && sr != CSR_TIMEOUT && sr != CSR_SELECT)) { ! 1010: printk("\nNR:wd-intr-1\n"); ! 1011: write1_io(0, IO_LED_OFF); ! 1012: ! 1013: /* release the SMP spin_lock and restore irq state */ ! 1014: CLISPIN_UNLOCK(flags); ! 1015: return; ! 1016: } ! 1017: ! 1018: DB(DB_INTR,printk("{%02x:%02x-",asr,sr)) ! 1019: ! 1020: /* After starting a FIFO-based transfer, the next _WD3393_ interrupt is ! 1021: * guaranteed to be in response to the completion of the transfer. ! 1022: * If we were reading, there's probably data in the fifo that needs ! 1023: * to be copied into RAM - do that here. Also, we have to update ! 1024: * 'this_residual' and 'ptr' based on the contents of the ! 1025: * TRANSFER_COUNT register, in case the device decided to do an ! 1026: * intermediate disconnect (a device may do this if it has to ! 1027: * do a seek, or just to be nice and let other devices have ! 1028: * some bus time during long transfers). ! 1029: * After doing whatever is necessary with the fifo, we go on and ! 1030: * service the WD3393 interrupt normally. ! 1031: */ ! 1032: ! 1033: if (hostdata->fifo == FI_FIFO_READING) { ! 1034: ! 1035: /* buffer index = start-of-buffer + #-of-bytes-already-read */ ! 1036: ! 1037: sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); ! 1038: ! 1039: /* bytes remaining in fifo = (total-wanted - #-not-got) - #-already-read */ ! 1040: ! 1041: i = (cmd->SCp.this_residual - read_3393_count(hostdata)) - cmd->SCp.have_data_in; ! 1042: i >>= 1; /* Gulp. We assume this will always be modulo 2 */ ! 1043: f = hostdata->io_base + IO_FIFO; ! 1044: ! 1045: #ifdef FAST_READ_IO ! 1046: ! 1047: FAST_READ2_IO(); ! 1048: #else ! 1049: while (i--) ! 1050: *sp++ = read2_io(IO_FIFO); ! 1051: ! 1052: #endif ! 1053: ! 1054: hostdata->fifo = FI_FIFO_UNUSED; ! 1055: length = cmd->SCp.this_residual; ! 1056: cmd->SCp.this_residual = read_3393_count(hostdata); ! 1057: cmd->SCp.ptr += (length - cmd->SCp.this_residual); ! 1058: ! 1059: DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual)) ! 1060: ! 1061: } ! 1062: ! 1063: else if (hostdata->fifo == FI_FIFO_WRITING) { ! 1064: hostdata->fifo = FI_FIFO_UNUSED; ! 1065: length = cmd->SCp.this_residual; ! 1066: cmd->SCp.this_residual = read_3393_count(hostdata); ! 1067: cmd->SCp.ptr += (length - cmd->SCp.this_residual); ! 1068: ! 1069: DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual)) ! 1070: ! 1071: } ! 1072: ! 1073: /* Respond to the specific WD3393 interrupt - there are quite a few! */ ! 1074: ! 1075: switch (sr) { ! 1076: ! 1077: case CSR_TIMEOUT: ! 1078: DB(DB_INTR,printk("TIMEOUT")) ! 1079: ! 1080: if (hostdata->state == S_RUNNING_LEVEL2) ! 1081: hostdata->connected = NULL; ! 1082: else { ! 1083: cmd = (Scsi_Cmnd *)hostdata->selecting; /* get a valid cmd */ ! 1084: CHECK_NULL(cmd,"csr_timeout") ! 1085: hostdata->selecting = NULL; ! 1086: } ! 1087: ! 1088: cmd->result = DID_NO_CONNECT << 16; ! 1089: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1090: hostdata->state = S_UNCONNECTED; ! 1091: cmd->scsi_done(cmd); ! 1092: ! 1093: /* We are not connected to a target - check to see if there ! 1094: * are commands waiting to be executed. ! 1095: */ ! 1096: ! 1097: in2000_execute(instance); ! 1098: break; ! 1099: ! 1100: ! 1101: /* Note: this interrupt should not occur in a LEVEL2 command */ ! 1102: ! 1103: case CSR_SELECT: ! 1104: DB(DB_INTR,printk("SELECT")) ! 1105: hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting; ! 1106: CHECK_NULL(cmd,"csr_select") ! 1107: hostdata->selecting = NULL; ! 1108: ! 1109: /* construct an IDENTIFY message with correct disconnect bit */ ! 1110: ! 1111: hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun); ! 1112: if (cmd->SCp.phase) ! 1113: hostdata->outgoing_msg[0] |= 0x40; ! 1114: ! 1115: if (hostdata->sync_stat[cmd->target] == SS_FIRST) { ! 1116: #ifdef SYNC_DEBUG ! 1117: printk(" sending SDTR "); ! 1118: #endif ! 1119: ! 1120: hostdata->sync_stat[cmd->target] = SS_WAITING; ! 1121: ! 1122: /* tack on a 2nd message to ask about synchronous transfers */ ! 1123: ! 1124: hostdata->outgoing_msg[1] = EXTENDED_MESSAGE; ! 1125: hostdata->outgoing_msg[2] = 3; ! 1126: hostdata->outgoing_msg[3] = EXTENDED_SDTR; ! 1127: hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4; ! 1128: hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF; ! 1129: hostdata->outgoing_len = 6; ! 1130: } ! 1131: else ! 1132: hostdata->outgoing_len = 1; ! 1133: ! 1134: hostdata->state = S_CONNECTED; ! 1135: break; ! 1136: ! 1137: ! 1138: case CSR_XFER_DONE|PHS_DATA_IN: ! 1139: case CSR_UNEXP |PHS_DATA_IN: ! 1140: case CSR_SRV_REQ |PHS_DATA_IN: ! 1141: DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual)) ! 1142: transfer_bytes(cmd, DATA_IN_DIR); ! 1143: if (hostdata->state != S_RUNNING_LEVEL2) ! 1144: hostdata->state = S_CONNECTED; ! 1145: break; ! 1146: ! 1147: ! 1148: case CSR_XFER_DONE|PHS_DATA_OUT: ! 1149: case CSR_UNEXP |PHS_DATA_OUT: ! 1150: case CSR_SRV_REQ |PHS_DATA_OUT: ! 1151: DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual)) ! 1152: transfer_bytes(cmd, DATA_OUT_DIR); ! 1153: if (hostdata->state != S_RUNNING_LEVEL2) ! 1154: hostdata->state = S_CONNECTED; ! 1155: break; ! 1156: ! 1157: ! 1158: /* Note: this interrupt should not occur in a LEVEL2 command */ ! 1159: ! 1160: case CSR_XFER_DONE|PHS_COMMAND: ! 1161: case CSR_UNEXP |PHS_COMMAND: ! 1162: case CSR_SRV_REQ |PHS_COMMAND: ! 1163: DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid)) ! 1164: transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); ! 1165: hostdata->state = S_CONNECTED; ! 1166: break; ! 1167: ! 1168: ! 1169: case CSR_XFER_DONE|PHS_STATUS: ! 1170: case CSR_UNEXP |PHS_STATUS: ! 1171: case CSR_SRV_REQ |PHS_STATUS: ! 1172: DB(DB_INTR,printk("STATUS=")) ! 1173: ! 1174: cmd->SCp.Status = read_1_byte(hostdata); ! 1175: DB(DB_INTR,printk("%02x",cmd->SCp.Status)) ! 1176: if (hostdata->level2 >= L2_BASIC) { ! 1177: sr = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ ! 1178: hostdata->state = S_RUNNING_LEVEL2; ! 1179: write_3393(hostdata,WD_COMMAND_PHASE, 0x50); ! 1180: write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); ! 1181: } ! 1182: else { ! 1183: hostdata->state = S_CONNECTED; ! 1184: } ! 1185: break; ! 1186: ! 1187: ! 1188: case CSR_XFER_DONE|PHS_MESS_IN: ! 1189: case CSR_UNEXP |PHS_MESS_IN: ! 1190: case CSR_SRV_REQ |PHS_MESS_IN: ! 1191: DB(DB_INTR,printk("MSG_IN=")) ! 1192: ! 1193: msg = read_1_byte(hostdata); ! 1194: sr = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ ! 1195: ! 1196: hostdata->incoming_msg[hostdata->incoming_ptr] = msg; ! 1197: if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE) ! 1198: msg = EXTENDED_MESSAGE; ! 1199: else ! 1200: hostdata->incoming_ptr = 0; ! 1201: ! 1202: cmd->SCp.Message = msg; ! 1203: switch (msg) { ! 1204: ! 1205: case COMMAND_COMPLETE: ! 1206: DB(DB_INTR,printk("CCMP-%ld",cmd->pid)) ! 1207: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1208: hostdata->state = S_PRE_CMP_DISC; ! 1209: break; ! 1210: ! 1211: case SAVE_POINTERS: ! 1212: DB(DB_INTR,printk("SDP")) ! 1213: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1214: hostdata->state = S_CONNECTED; ! 1215: break; ! 1216: ! 1217: case RESTORE_POINTERS: ! 1218: DB(DB_INTR,printk("RDP")) ! 1219: if (hostdata->level2 >= L2_BASIC) { ! 1220: write_3393(hostdata,WD_COMMAND_PHASE, 0x45); ! 1221: write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); ! 1222: hostdata->state = S_RUNNING_LEVEL2; ! 1223: } ! 1224: else { ! 1225: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1226: hostdata->state = S_CONNECTED; ! 1227: } ! 1228: break; ! 1229: ! 1230: case DISCONNECT: ! 1231: DB(DB_INTR,printk("DIS")) ! 1232: cmd->device->disconnect = 1; ! 1233: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1234: hostdata->state = S_PRE_TMP_DISC; ! 1235: break; ! 1236: ! 1237: case MESSAGE_REJECT: ! 1238: DB(DB_INTR,printk("REJ")) ! 1239: #ifdef SYNC_DEBUG ! 1240: printk("-REJ-"); ! 1241: #endif ! 1242: if (hostdata->sync_stat[cmd->target] == SS_WAITING) ! 1243: hostdata->sync_stat[cmd->target] = SS_SET; ! 1244: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1245: hostdata->state = S_CONNECTED; ! 1246: break; ! 1247: ! 1248: case EXTENDED_MESSAGE: ! 1249: DB(DB_INTR,printk("EXT")) ! 1250: ! 1251: ucp = hostdata->incoming_msg; ! 1252: ! 1253: #ifdef SYNC_DEBUG ! 1254: printk("%02x",ucp[hostdata->incoming_ptr]); ! 1255: #endif ! 1256: /* Is this the last byte of the extended message? */ ! 1257: ! 1258: if ((hostdata->incoming_ptr >= 2) && ! 1259: (hostdata->incoming_ptr == (ucp[1] + 1))) { ! 1260: ! 1261: switch (ucp[2]) { /* what's the EXTENDED code? */ ! 1262: case EXTENDED_SDTR: ! 1263: id = calc_sync_xfer(ucp[3],ucp[4]); ! 1264: if (hostdata->sync_stat[cmd->target] != SS_WAITING) { ! 1265: ! 1266: /* A device has sent an unsolicited SDTR message; rather than go ! 1267: * through the effort of decoding it and then figuring out what ! 1268: * our reply should be, we're just gonna say that we have a ! 1269: * synchronous fifo depth of 0. This will result in asynchronous ! 1270: * transfers - not ideal but so much easier. ! 1271: * Actually, this is OK because it assures us that if we don't ! 1272: * specifically ask for sync transfers, we won't do any. ! 1273: */ ! 1274: ! 1275: write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ ! 1276: hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; ! 1277: hostdata->outgoing_msg[1] = 3; ! 1278: hostdata->outgoing_msg[2] = EXTENDED_SDTR; ! 1279: hostdata->outgoing_msg[3] = hostdata->default_sx_per/4; ! 1280: hostdata->outgoing_msg[4] = 0; ! 1281: hostdata->outgoing_len = 5; ! 1282: hostdata->sync_xfer[cmd->target] = ! 1283: calc_sync_xfer(hostdata->default_sx_per/4,0); ! 1284: } ! 1285: else { ! 1286: hostdata->sync_xfer[cmd->target] = id; ! 1287: } ! 1288: #ifdef SYNC_DEBUG ! 1289: printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]); ! 1290: #endif ! 1291: hostdata->sync_stat[cmd->target] = SS_SET; ! 1292: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1293: hostdata->state = S_CONNECTED; ! 1294: break; ! 1295: case EXTENDED_WDTR: ! 1296: write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ ! 1297: printk("sending WDTR "); ! 1298: hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; ! 1299: hostdata->outgoing_msg[1] = 2; ! 1300: hostdata->outgoing_msg[2] = EXTENDED_WDTR; ! 1301: hostdata->outgoing_msg[3] = 0; /* 8 bit transfer width */ ! 1302: hostdata->outgoing_len = 4; ! 1303: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1304: hostdata->state = S_CONNECTED; ! 1305: break; ! 1306: default: ! 1307: write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ ! 1308: printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]); ! 1309: hostdata->outgoing_msg[0] = MESSAGE_REJECT; ! 1310: hostdata->outgoing_len = 1; ! 1311: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1312: hostdata->state = S_CONNECTED; ! 1313: break; ! 1314: } ! 1315: hostdata->incoming_ptr = 0; ! 1316: } ! 1317: ! 1318: /* We need to read more MESS_IN bytes for the extended message */ ! 1319: ! 1320: else { ! 1321: hostdata->incoming_ptr++; ! 1322: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1323: hostdata->state = S_CONNECTED; ! 1324: } ! 1325: break; ! 1326: ! 1327: default: ! 1328: printk("Rejecting Unknown Message(%02x) ",msg); ! 1329: write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ ! 1330: hostdata->outgoing_msg[0] = MESSAGE_REJECT; ! 1331: hostdata->outgoing_len = 1; ! 1332: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1333: hostdata->state = S_CONNECTED; ! 1334: } ! 1335: break; ! 1336: ! 1337: ! 1338: /* Note: this interrupt will occur only after a LEVEL2 command */ ! 1339: ! 1340: case CSR_SEL_XFER_DONE: ! 1341: ! 1342: /* Make sure that reselection is enabled at this point - it may ! 1343: * have been turned off for the command that just completed. ! 1344: */ ! 1345: ! 1346: write_3393(hostdata,WD_SOURCE_ID, SRCID_ER); ! 1347: if (phs == 0x60) { ! 1348: DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid)) ! 1349: cmd->SCp.Message = COMMAND_COMPLETE; ! 1350: lun = read_3393(hostdata,WD_TARGET_LUN); ! 1351: DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun)) ! 1352: hostdata->connected = NULL; ! 1353: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1354: hostdata->state = S_UNCONNECTED; ! 1355: if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE) ! 1356: cmd->SCp.Status = lun; ! 1357: if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) ! 1358: cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); ! 1359: else ! 1360: cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); ! 1361: cmd->scsi_done(cmd); ! 1362: ! 1363: /* We are no longer connected to a target - check to see if ! 1364: * there are commands waiting to be executed. ! 1365: */ ! 1366: ! 1367: in2000_execute(instance); ! 1368: } ! 1369: else { ! 1370: printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid); ! 1371: } ! 1372: break; ! 1373: ! 1374: ! 1375: /* Note: this interrupt will occur only after a LEVEL2 command */ ! 1376: ! 1377: case CSR_SDP: ! 1378: DB(DB_INTR,printk("SDP")) ! 1379: hostdata->state = S_RUNNING_LEVEL2; ! 1380: write_3393(hostdata,WD_COMMAND_PHASE, 0x41); ! 1381: write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); ! 1382: break; ! 1383: ! 1384: ! 1385: case CSR_XFER_DONE|PHS_MESS_OUT: ! 1386: case CSR_UNEXP |PHS_MESS_OUT: ! 1387: case CSR_SRV_REQ |PHS_MESS_OUT: ! 1388: DB(DB_INTR,printk("MSG_OUT=")) ! 1389: ! 1390: /* To get here, we've probably requested MESSAGE_OUT and have ! 1391: * already put the correct bytes in outgoing_msg[] and filled ! 1392: * in outgoing_len. We simply send them out to the SCSI bus. ! 1393: * Sometimes we get MESSAGE_OUT phase when we're not expecting ! 1394: * it - like when our SDTR message is rejected by a target. Some ! 1395: * targets send the REJECT before receiving all of the extended ! 1396: * message, and then seem to go back to MESSAGE_OUT for a byte ! 1397: * or two. Not sure why, or if I'm doing something wrong to ! 1398: * cause this to happen. Regardless, it seems that sending ! 1399: * NOP messages in these situations results in no harm and ! 1400: * makes everyone happy. ! 1401: */ ! 1402: ! 1403: if (hostdata->outgoing_len == 0) { ! 1404: hostdata->outgoing_len = 1; ! 1405: hostdata->outgoing_msg[0] = NOP; ! 1406: } ! 1407: transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len, ! 1408: DATA_OUT_DIR, hostdata); ! 1409: DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0])) ! 1410: hostdata->outgoing_len = 0; ! 1411: hostdata->state = S_CONNECTED; ! 1412: break; ! 1413: ! 1414: ! 1415: case CSR_UNEXP_DISC: ! 1416: ! 1417: /* I think I've seen this after a request-sense that was in response ! 1418: * to an error condition, but not sure. We certainly need to do ! 1419: * something when we get this interrupt - the question is 'what?'. ! 1420: * Let's think positively, and assume some command has finished ! 1421: * in a legal manner (like a command that provokes a request-sense), ! 1422: * so we treat it as a normal command-complete-disconnect. ! 1423: */ ! 1424: ! 1425: ! 1426: /* Make sure that reselection is enabled at this point - it may ! 1427: * have been turned off for the command that just completed. ! 1428: */ ! 1429: ! 1430: write_3393(hostdata,WD_SOURCE_ID, SRCID_ER); ! 1431: if (cmd == NULL) { ! 1432: printk(" - Already disconnected! "); ! 1433: hostdata->state = S_UNCONNECTED; ! 1434: ! 1435: /* release the SMP spin_lock and restore irq state */ ! 1436: CLISPIN_UNLOCK(flags); ! 1437: return; ! 1438: } ! 1439: DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid)) ! 1440: hostdata->connected = NULL; ! 1441: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1442: hostdata->state = S_UNCONNECTED; ! 1443: if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) ! 1444: cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); ! 1445: else ! 1446: cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); ! 1447: cmd->scsi_done(cmd); ! 1448: ! 1449: /* We are no longer connected to a target - check to see if ! 1450: * there are commands waiting to be executed. ! 1451: */ ! 1452: ! 1453: in2000_execute(instance); ! 1454: break; ! 1455: ! 1456: ! 1457: case CSR_DISC: ! 1458: ! 1459: /* Make sure that reselection is enabled at this point - it may ! 1460: * have been turned off for the command that just completed. ! 1461: */ ! 1462: ! 1463: write_3393(hostdata,WD_SOURCE_ID, SRCID_ER); ! 1464: DB(DB_INTR,printk("DISC-%ld",cmd->pid)) ! 1465: if (cmd == NULL) { ! 1466: printk(" - Already disconnected! "); ! 1467: hostdata->state = S_UNCONNECTED; ! 1468: } ! 1469: switch (hostdata->state) { ! 1470: case S_PRE_CMP_DISC: ! 1471: hostdata->connected = NULL; ! 1472: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1473: hostdata->state = S_UNCONNECTED; ! 1474: DB(DB_INTR,printk(":%d",cmd->SCp.Status)) ! 1475: if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) ! 1476: cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); ! 1477: else ! 1478: cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); ! 1479: cmd->scsi_done(cmd); ! 1480: break; ! 1481: case S_PRE_TMP_DISC: ! 1482: case S_RUNNING_LEVEL2: ! 1483: cmd->host_scribble = (uchar *)hostdata->disconnected_Q; ! 1484: hostdata->disconnected_Q = cmd; ! 1485: hostdata->connected = NULL; ! 1486: hostdata->state = S_UNCONNECTED; ! 1487: ! 1488: #ifdef PROC_STATISTICS ! 1489: hostdata->disc_done_cnt[cmd->target]++; ! 1490: #endif ! 1491: ! 1492: break; ! 1493: default: ! 1494: printk("*** Unexpected DISCONNECT interrupt! ***"); ! 1495: hostdata->state = S_UNCONNECTED; ! 1496: } ! 1497: ! 1498: /* We are no longer connected to a target - check to see if ! 1499: * there are commands waiting to be executed. ! 1500: */ ! 1501: ! 1502: in2000_execute(instance); ! 1503: break; ! 1504: ! 1505: ! 1506: case CSR_RESEL_AM: ! 1507: DB(DB_INTR,printk("RESEL")) ! 1508: ! 1509: /* First we have to make sure this reselection didn't */ ! 1510: /* happen during Arbitration/Selection of some other device. */ ! 1511: /* If yes, put losing command back on top of input_Q. */ ! 1512: ! 1513: if (hostdata->level2 <= L2_NONE) { ! 1514: ! 1515: if (hostdata->selecting) { ! 1516: cmd = (Scsi_Cmnd *)hostdata->selecting; ! 1517: hostdata->selecting = NULL; ! 1518: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1519: cmd->host_scribble = (uchar *)hostdata->input_Q; ! 1520: hostdata->input_Q = cmd; ! 1521: } ! 1522: } ! 1523: ! 1524: else { ! 1525: ! 1526: if (cmd) { ! 1527: if (phs == 0x00) { ! 1528: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1529: cmd->host_scribble = (uchar *)hostdata->input_Q; ! 1530: hostdata->input_Q = cmd; ! 1531: } ! 1532: else { ! 1533: printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs); ! 1534: while (1) ! 1535: printk("\r"); ! 1536: } ! 1537: } ! 1538: ! 1539: } ! 1540: ! 1541: /* OK - find out which device reselected us. */ ! 1542: ! 1543: id = read_3393(hostdata,WD_SOURCE_ID); ! 1544: id &= SRCID_MASK; ! 1545: ! 1546: /* and extract the lun from the ID message. (Note that we don't ! 1547: * bother to check for a valid message here - I guess this is ! 1548: * not the right way to go, but....) ! 1549: */ ! 1550: ! 1551: lun = read_3393(hostdata,WD_DATA); ! 1552: if (hostdata->level2 < L2_RESELECT) ! 1553: write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); ! 1554: lun &= 7; ! 1555: ! 1556: /* Now we look for the command that's reconnecting. */ ! 1557: ! 1558: cmd = (Scsi_Cmnd *)hostdata->disconnected_Q; ! 1559: patch = NULL; ! 1560: while (cmd) { ! 1561: if (id == cmd->target && lun == cmd->lun) ! 1562: break; ! 1563: patch = cmd; ! 1564: cmd = (Scsi_Cmnd *)cmd->host_scribble; ! 1565: } ! 1566: ! 1567: /* Hmm. Couldn't find a valid command.... What to do? */ ! 1568: ! 1569: if (!cmd) { ! 1570: printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun); ! 1571: break; ! 1572: } ! 1573: ! 1574: /* Ok, found the command - now start it up again. */ ! 1575: ! 1576: if (patch) ! 1577: patch->host_scribble = cmd->host_scribble; ! 1578: else ! 1579: hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble; ! 1580: hostdata->connected = cmd; ! 1581: ! 1582: /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]' ! 1583: * because these things are preserved over a disconnect. ! 1584: * But we DO need to fix the DPD bit so it's correct for this command. ! 1585: */ ! 1586: ! 1587: if (is_dir_out(cmd)) ! 1588: write_3393(hostdata,WD_DESTINATION_ID,cmd->target); ! 1589: else ! 1590: write_3393(hostdata,WD_DESTINATION_ID,cmd->target | DSTID_DPD); ! 1591: if (hostdata->level2 >= L2_RESELECT) { ! 1592: write_3393_count(hostdata,0); /* we want a DATA_PHASE interrupt */ ! 1593: write_3393(hostdata,WD_COMMAND_PHASE, 0x45); ! 1594: write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); ! 1595: hostdata->state = S_RUNNING_LEVEL2; ! 1596: } ! 1597: else ! 1598: hostdata->state = S_CONNECTED; ! 1599: ! 1600: DB(DB_INTR,printk("-%ld",cmd->pid)) ! 1601: break; ! 1602: ! 1603: default: ! 1604: printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs); ! 1605: } ! 1606: ! 1607: write1_io(0, IO_LED_OFF); ! 1608: ! 1609: DB(DB_INTR,printk("} ")) ! 1610: ! 1611: /* release the SMP spin_lock and restore irq state */ ! 1612: CLISPIN_UNLOCK(flags); ! 1613: ! 1614: } ! 1615: ! 1616: ! 1617: ! 1618: #define RESET_CARD 0 ! 1619: #define RESET_CARD_AND_BUS 1 ! 1620: #define B_FLAG 0x80 ! 1621: ! 1622: static int reset_hardware(struct Scsi_Host *instance, int type) ! 1623: { ! 1624: struct IN2000_hostdata *hostdata; ! 1625: int qt,x; ! 1626: unsigned long flags; ! 1627: ! 1628: hostdata = (struct IN2000_hostdata *)instance->hostdata; ! 1629: ! 1630: write1_io(0, IO_LED_ON); ! 1631: if (type == RESET_CARD_AND_BUS) { ! 1632: write1_io(0,IO_CARD_RESET); ! 1633: x = read1_io(IO_HARDWARE); ! 1634: } ! 1635: x = read_3393(hostdata,WD_SCSI_STATUS); /* clear any WD intrpt */ ! 1636: write_3393(hostdata,WD_OWN_ID, instance->this_id | ! 1637: OWNID_EAF | OWNID_RAF | OWNID_FS_8); ! 1638: write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); ! 1639: write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER, ! 1640: calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF)); ! 1641: save_flags(flags); ! 1642: cli(); ! 1643: write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */ ! 1644: write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */ ! 1645: write_3393(hostdata,WD_COMMAND, WD_CMD_RESET); ! 1646: while (!(READ_AUX_STAT() & ASR_INT)) ! 1647: ; /* wait for RESET to complete */ ! 1648: ! 1649: x = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ ! 1650: restore_flags(flags); ! 1651: write_3393(hostdata,WD_QUEUE_TAG,0xa5); /* any random number */ ! 1652: qt = read_3393(hostdata,WD_QUEUE_TAG); ! 1653: if (qt == 0xa5) { ! 1654: x |= B_FLAG; ! 1655: write_3393(hostdata,WD_QUEUE_TAG,0); ! 1656: } ! 1657: write_3393(hostdata,WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE); ! 1658: write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); ! 1659: write1_io(0, IO_LED_OFF); ! 1660: return x; ! 1661: } ! 1662: ! 1663: ! 1664: ! 1665: int in2000_reset(Scsi_Cmnd *cmd, unsigned int reset_flags) ! 1666: { ! 1667: unsigned long flags; ! 1668: struct Scsi_Host *instance; ! 1669: struct IN2000_hostdata *hostdata; ! 1670: int x; ! 1671: ! 1672: instance = cmd->host; ! 1673: hostdata = (struct IN2000_hostdata *)instance->hostdata; ! 1674: ! 1675: printk("scsi%d: Reset. ", instance->host_no); ! 1676: save_flags(flags); ! 1677: cli(); ! 1678: ! 1679: /* do scsi-reset here */ ! 1680: ! 1681: reset_hardware(instance, RESET_CARD_AND_BUS); ! 1682: for (x = 0; x < 8; x++) { ! 1683: hostdata->busy[x] = 0; ! 1684: hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF); ! 1685: hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ ! 1686: } ! 1687: hostdata->input_Q = NULL; ! 1688: hostdata->selecting = NULL; ! 1689: hostdata->connected = NULL; ! 1690: hostdata->disconnected_Q = NULL; ! 1691: hostdata->state = S_UNCONNECTED; ! 1692: hostdata->fifo = FI_FIFO_UNUSED; ! 1693: hostdata->incoming_ptr = 0; ! 1694: hostdata->outgoing_len = 0; ! 1695: ! 1696: cmd->result = DID_RESET << 16; ! 1697: restore_flags(flags); ! 1698: return 0; ! 1699: } ! 1700: ! 1701: ! 1702: ! 1703: int in2000_abort (Scsi_Cmnd *cmd) ! 1704: { ! 1705: struct Scsi_Host *instance; ! 1706: struct IN2000_hostdata *hostdata; ! 1707: Scsi_Cmnd *tmp, *prev; ! 1708: unsigned long flags; ! 1709: uchar sr, asr; ! 1710: unsigned long timeout; ! 1711: ! 1712: save_flags (flags); ! 1713: cli(); ! 1714: ! 1715: instance = cmd->host; ! 1716: hostdata = (struct IN2000_hostdata *)instance->hostdata; ! 1717: ! 1718: printk ("scsi%d: Abort-", instance->host_no); ! 1719: printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ", ! 1720: READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual, ! 1721: cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT)); ! 1722: ! 1723: /* ! 1724: * Case 1 : If the command hasn't been issued yet, we simply remove it ! 1725: * from the inout_Q. ! 1726: */ ! 1727: ! 1728: tmp = (Scsi_Cmnd *)hostdata->input_Q; ! 1729: prev = 0; ! 1730: while (tmp) { ! 1731: if (tmp == cmd) { ! 1732: if (prev) ! 1733: prev->host_scribble = cmd->host_scribble; ! 1734: cmd->host_scribble = NULL; ! 1735: cmd->result = DID_ABORT << 16; ! 1736: printk("scsi%d: Abort - removing command %ld from input_Q. ", ! 1737: instance->host_no, cmd->pid); ! 1738: cmd->scsi_done(cmd); ! 1739: restore_flags(flags); ! 1740: return SCSI_ABORT_SUCCESS; ! 1741: } ! 1742: prev = tmp; ! 1743: tmp = (Scsi_Cmnd *)tmp->host_scribble; ! 1744: } ! 1745: ! 1746: /* ! 1747: * Case 2 : If the command is connected, we're going to fail the abort ! 1748: * and let the high level SCSI driver retry at a later time or ! 1749: * issue a reset. ! 1750: * ! 1751: * Timeouts, and therefore aborted commands, will be highly unlikely ! 1752: * and handling them cleanly in this situation would make the common ! 1753: * case of noresets less efficient, and would pollute our code. So, ! 1754: * we fail. ! 1755: */ ! 1756: ! 1757: if (hostdata->connected == cmd) { ! 1758: ! 1759: printk("scsi%d: Aborting connected command %ld - ", ! 1760: instance->host_no, cmd->pid); ! 1761: ! 1762: printk("sending wd33c93 ABORT command - "); ! 1763: write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); ! 1764: write_3393_cmd(hostdata, WD_CMD_ABORT); ! 1765: ! 1766: /* Now we have to attempt to flush out the FIFO... */ ! 1767: ! 1768: printk("flushing fifo - "); ! 1769: timeout = 1000000; ! 1770: do { ! 1771: asr = READ_AUX_STAT(); ! 1772: if (asr & ASR_DBR) ! 1773: read_3393(hostdata, WD_DATA); ! 1774: } while (!(asr & ASR_INT) && timeout-- > 0); ! 1775: sr = read_3393(hostdata, WD_SCSI_STATUS); ! 1776: printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ", ! 1777: asr, sr, read_3393_count(hostdata), timeout); ! 1778: ! 1779: /* ! 1780: * Abort command processed. ! 1781: * Still connected. ! 1782: * We must disconnect. ! 1783: */ ! 1784: ! 1785: printk("sending wd33c93 DISCONNECT command - "); ! 1786: write_3393_cmd(hostdata, WD_CMD_DISCONNECT); ! 1787: ! 1788: timeout = 1000000; ! 1789: asr = READ_AUX_STAT(); ! 1790: while ((asr & ASR_CIP) && timeout-- > 0) ! 1791: asr = READ_AUX_STAT(); ! 1792: sr = read_3393(hostdata, WD_SCSI_STATUS); ! 1793: printk("asr=%02x, sr=%02x.",asr,sr); ! 1794: ! 1795: hostdata->busy[cmd->target] &= ~(1 << cmd->lun); ! 1796: hostdata->connected = NULL; ! 1797: hostdata->state = S_UNCONNECTED; ! 1798: cmd->result = DID_ABORT << 16; ! 1799: cmd->scsi_done(cmd); ! 1800: ! 1801: in2000_execute (instance); ! 1802: ! 1803: restore_flags(flags); ! 1804: return SCSI_ABORT_SUCCESS; ! 1805: } ! 1806: ! 1807: /* ! 1808: * Case 3: If the command is currently disconnected from the bus, ! 1809: * we're not going to expend much effort here: Let's just return ! 1810: * an ABORT_SNOOZE and hope for the best... ! 1811: */ ! 1812: ! 1813: for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp; ! 1814: tmp=(Scsi_Cmnd *)tmp->host_scribble) ! 1815: if (cmd == tmp) { ! 1816: restore_flags(flags); ! 1817: printk("Sending ABORT_SNOOZE. "); ! 1818: return SCSI_ABORT_SNOOZE; ! 1819: } ! 1820: ! 1821: /* ! 1822: * Case 4 : If we reached this point, the command was not found in any of ! 1823: * the queues. ! 1824: * ! 1825: * We probably reached this point because of an unlikely race condition ! 1826: * between the command completing successfully and the abortion code, ! 1827: * so we won't panic, but we will notify the user in case something really ! 1828: * broke. ! 1829: */ ! 1830: ! 1831: in2000_execute (instance); ! 1832: ! 1833: restore_flags(flags); ! 1834: printk("scsi%d: warning : SCSI command probably completed successfully" ! 1835: " before abortion. ", instance->host_no); ! 1836: return SCSI_ABORT_NOT_RUNNING; ! 1837: } ! 1838: ! 1839: ! 1840: ! 1841: #define MAX_IN2000_HOSTS 3 ! 1842: #define MAX_SETUP_ARGS (sizeof(setup_args) / sizeof(char *)) ! 1843: #define SETUP_BUFFER_SIZE 200 ! 1844: static char setup_buffer[SETUP_BUFFER_SIZE]; ! 1845: static char setup_used[MAX_SETUP_ARGS]; ! 1846: static int done_setup = 0; ! 1847: ! 1848: in2000__INITFUNC( void in2000_setup (char *str, int *ints) ) ! 1849: { ! 1850: int i; ! 1851: char *p1,*p2; ! 1852: ! 1853: strncpy(setup_buffer,str,SETUP_BUFFER_SIZE); ! 1854: setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0'; ! 1855: p1 = setup_buffer; ! 1856: i = 0; ! 1857: while (*p1 && (i < MAX_SETUP_ARGS)) { ! 1858: p2 = strchr(p1, ','); ! 1859: if (p2) { ! 1860: *p2 = '\0'; ! 1861: if (p1 != p2) ! 1862: setup_args[i] = p1; ! 1863: p1 = p2 + 1; ! 1864: i++; ! 1865: } ! 1866: else { ! 1867: setup_args[i] = p1; ! 1868: break; ! 1869: } ! 1870: } ! 1871: for (i=0; i<MAX_SETUP_ARGS; i++) ! 1872: setup_used[i] = 0; ! 1873: done_setup = 1; ! 1874: } ! 1875: ! 1876: ! 1877: /* check_setup_args() returns index if key found, 0 if not ! 1878: */ ! 1879: ! 1880: in2000__INITFUNC( static int check_setup_args(char *key, int *flags, int *val, char *buf) ) ! 1881: { ! 1882: int x; ! 1883: char *cp; ! 1884: ! 1885: for (x=0; x<MAX_SETUP_ARGS; x++) { ! 1886: if (setup_used[x]) ! 1887: continue; ! 1888: if (!strncmp(setup_args[x], key, strlen(key))) ! 1889: break; ! 1890: } ! 1891: if (x == MAX_SETUP_ARGS) ! 1892: return 0; ! 1893: setup_used[x] = 1; ! 1894: cp = setup_args[x] + strlen(key); ! 1895: *val = -1; ! 1896: if (*cp != ':') ! 1897: return ++x; ! 1898: cp++; ! 1899: if ((*cp >= '0') && (*cp <= '9')) { ! 1900: *val = simple_strtoul(cp,NULL,0); ! 1901: } ! 1902: return ++x; ! 1903: } ! 1904: ! 1905: ! 1906: ! 1907: /* The "correct" (ie portable) way to access memory-mapped hardware ! 1908: * such as the IN2000 EPROM and dip switch is through the use of ! 1909: * special macros declared in 'asm/io.h'. We use readb() and readl() ! 1910: * when reading from the card's BIOS area in in2000_detect(). ! 1911: */ ! 1912: static const unsigned int *bios_tab[] in2000__INITDATA = { ! 1913: (unsigned int *)0xc8000, ! 1914: (unsigned int *)0xd0000, ! 1915: (unsigned int *)0xd8000, ! 1916: 0 ! 1917: }; ! 1918: ! 1919: static const unsigned short base_tab[] in2000__INITDATA = { ! 1920: 0x220, ! 1921: 0x200, ! 1922: 0x110, ! 1923: 0x100, ! 1924: }; ! 1925: ! 1926: static const int int_tab[] in2000__INITDATA = { ! 1927: 15, ! 1928: 14, ! 1929: 11, ! 1930: 10 ! 1931: }; ! 1932: ! 1933: ! 1934: in2000__INITFUNC( int in2000_detect(Scsi_Host_Template * tpnt) ) ! 1935: { ! 1936: struct Scsi_Host *instance; ! 1937: struct IN2000_hostdata *hostdata; ! 1938: int detect_count; ! 1939: int bios; ! 1940: int x; ! 1941: unsigned short base; ! 1942: uchar switches; ! 1943: uchar hrev; ! 1944: int flags; ! 1945: int val; ! 1946: char buf[32]; ! 1947: ! 1948: /* Thanks to help from Bill Earnest, probing for IN2000 cards is a ! 1949: * pretty straightforward and fool-proof operation. There are 3 ! 1950: * possible locations for the IN2000 EPROM in memory space - if we ! 1951: * find a BIOS signature, we can read the dip switch settings from ! 1952: * the byte at BIOS+32 (shadowed in by logic on the card). From 2 ! 1953: * of the switch bits we get the card's address in IO space. There's ! 1954: * an image of the dip switch there, also, so we have a way to back- ! 1955: * check that this really is an IN2000 card. Very nifty. Use the ! 1956: * 'ioport:xx' command-line parameter if your BIOS EPROM is absent ! 1957: * or disabled. ! 1958: */ ! 1959: ! 1960: if (!done_setup && setup_strings) ! 1961: in2000_setup(setup_strings,0); ! 1962: ! 1963: detect_count = 0; ! 1964: for (bios = 0; bios_tab[bios]; bios++) { ! 1965: if (check_setup_args("ioport",&flags,&val,buf)) { ! 1966: base = val; ! 1967: switches = ~inb(base + IO_SWITCHES) & 0xff; ! 1968: printk("Forcing IN2000 detection at IOport 0x%x ",base); ! 1969: bios = 2; ! 1970: } ! 1971: /* ! 1972: * There have been a couple of BIOS versions with different layouts ! 1973: * for the obvious ID strings. We look for the 2 most common ones and ! 1974: * hope that they cover all the cases... ! 1975: */ ! 1976: else if (readl(bios_tab[bios]+0x04) == 0x41564f4e || ! 1977: readl(bios_tab[bios]+0x0c) == 0x61776c41) { ! 1978: printk("Found IN2000 BIOS at 0x%x ",(unsigned int)bios_tab[bios]); ! 1979: ! 1980: /* Read the switch image that's mapped into EPROM space */ ! 1981: ! 1982: switches = ~((readb(bios_tab[bios]+0x08) & 0xff)); ! 1983: ! 1984: /* Find out where the IO space is */ ! 1985: ! 1986: x = switches & (SW_ADDR0 | SW_ADDR1); ! 1987: base = base_tab[x]; ! 1988: ! 1989: /* Check for the IN2000 signature in IO space. */ ! 1990: ! 1991: x = ~inb(base + IO_SWITCHES) & 0xff; ! 1992: if (x != switches) { ! 1993: printk("Bad IO signature: %02x vs %02x.\n",x,switches); ! 1994: continue; ! 1995: } ! 1996: } ! 1997: else ! 1998: continue; ! 1999: ! 2000: /* OK. We have a base address for the IO ports - run a few safety checks */ ! 2001: ! 2002: if (!(switches & SW_BIT7)) { /* I _think_ all cards do this */ ! 2003: printk("There is no IN-2000 SCSI card at IOport 0x%03x!\n",base); ! 2004: continue; ! 2005: } ! 2006: ! 2007: /* Let's assume any hardware version will work, although the driver ! 2008: * has only been tested on 0x21, 0x22, 0x25, 0x26, and 0x27. We'll ! 2009: * print out the rev number for reference later, but accept them all. ! 2010: */ ! 2011: ! 2012: hrev = inb(base + IO_HARDWARE); ! 2013: ! 2014: /* Bit 2 tells us if interrupts are disabled */ ! 2015: if (switches & SW_DISINT) { ! 2016: printk("The IN-2000 SCSI card at IOport 0x%03x ",base); ! 2017: printk("is not configured for interrupt operation!\n"); ! 2018: printk("This driver requires an interrupt: cancelling detection.\n"); ! 2019: continue; ! 2020: } ! 2021: ! 2022: /* Ok. We accept that there's an IN2000 at ioaddr 'base'. Now ! 2023: * initialize it. ! 2024: */ ! 2025: ! 2026: tpnt->proc_dir = &proc_scsi_in2000; /* done more than once? harmless. */ ! 2027: detect_count++; ! 2028: instance = scsi_register(tpnt, sizeof(struct IN2000_hostdata)); ! 2029: if (!instance_list) ! 2030: instance_list = instance; ! 2031: hostdata = (struct IN2000_hostdata *)instance->hostdata; ! 2032: instance->io_port = hostdata->io_base = base; ! 2033: hostdata->dip_switch = switches; ! 2034: hostdata->hrev = hrev; ! 2035: ! 2036: write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */ ! 2037: write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */ ! 2038: write1_io(0,IO_INTR_MASK); /* allow all ints */ ! 2039: x = int_tab[(switches & (SW_INT0 | SW_INT1)) >> SW_INT_SHIFT]; ! 2040: if (request_irq(x, in2000_intr, SA_INTERRUPT, "in2000", NULL)) { ! 2041: printk("in2000_detect: Unable to allocate IRQ.\n"); ! 2042: detect_count--; ! 2043: continue; ! 2044: } ! 2045: instance->irq = x; ! 2046: instance->n_io_port = 13; ! 2047: request_region(base, 13, "in2000"); /* lock in this IO space for our use */ ! 2048: ! 2049: for (x = 0; x < 8; x++) { ! 2050: hostdata->busy[x] = 0; ! 2051: hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF); ! 2052: hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ ! 2053: #ifdef PROC_STATISTICS ! 2054: hostdata->cmd_cnt[x] = 0; ! 2055: hostdata->disc_allowed_cnt[x] = 0; ! 2056: hostdata->disc_done_cnt[x] = 0; ! 2057: #endif ! 2058: } ! 2059: hostdata->input_Q = NULL; ! 2060: hostdata->selecting = NULL; ! 2061: hostdata->connected = NULL; ! 2062: hostdata->disconnected_Q = NULL; ! 2063: hostdata->state = S_UNCONNECTED; ! 2064: hostdata->fifo = FI_FIFO_UNUSED; ! 2065: hostdata->level2 = L2_BASIC; ! 2066: hostdata->disconnect = DIS_ADAPTIVE; ! 2067: hostdata->args = DEBUG_DEFAULTS; ! 2068: hostdata->incoming_ptr = 0; ! 2069: hostdata->outgoing_len = 0; ! 2070: hostdata->default_sx_per = DEFAULT_SX_PER; ! 2071: ! 2072: /* Older BIOS's had a 'sync on/off' switch - use its setting */ ! 2073: ! 2074: if (readl(bios_tab[bios]+0x04) == 0x41564f4e && (switches & SW_SYNC_DOS5)) ! 2075: hostdata->sync_off = 0x00; /* sync defaults to on */ ! 2076: else ! 2077: hostdata->sync_off = 0xff; /* sync defaults to off */ ! 2078: ! 2079: #ifdef PROC_INTERFACE ! 2080: hostdata->proc = PR_VERSION|PR_INFO|PR_STATISTICS| ! 2081: PR_CONNECTED|PR_INPUTQ|PR_DISCQ| ! 2082: PR_STOP; ! 2083: #ifdef PROC_STATISTICS ! 2084: hostdata->int_cnt = 0; ! 2085: #endif ! 2086: #endif ! 2087: ! 2088: if (check_setup_args("nosync",&flags,&val,buf)) ! 2089: hostdata->sync_off = val; ! 2090: ! 2091: if (check_setup_args("period",&flags,&val,buf)) ! 2092: hostdata->default_sx_per = sx_table[round_period((unsigned int)val)].period_ns; ! 2093: ! 2094: if (check_setup_args("disconnect",&flags,&val,buf)) { ! 2095: if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) ! 2096: hostdata->disconnect = val; ! 2097: else ! 2098: hostdata->disconnect = DIS_ADAPTIVE; ! 2099: } ! 2100: ! 2101: if (check_setup_args("noreset",&flags,&val,buf)) ! 2102: hostdata->args ^= A_NO_SCSI_RESET; ! 2103: ! 2104: if (check_setup_args("level2",&flags,&val,buf)) ! 2105: hostdata->level2 = val; ! 2106: ! 2107: if (check_setup_args("debug",&flags,&val,buf)) ! 2108: hostdata->args = (val & DB_MASK); ! 2109: ! 2110: #ifdef PROC_INTERFACE ! 2111: if (check_setup_args("proc",&flags,&val,buf)) ! 2112: hostdata->proc = val; ! 2113: #endif ! 2114: ! 2115: ! 2116: x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS); ! 2117: ! 2118: hostdata->microcode = read_3393(hostdata,WD_CDB_1); ! 2119: if (x & 0x01) { ! 2120: if (x & B_FLAG) ! 2121: hostdata->chip = C_WD33C93B; ! 2122: else ! 2123: hostdata->chip = C_WD33C93A; ! 2124: } ! 2125: else ! 2126: hostdata->chip = C_WD33C93; ! 2127: ! 2128: printk("dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ", ! 2129: (switches & 0x7f), ! 2130: instance->irq,hostdata->io_base, ! 2131: (switches & SW_FLOPPY)?"Yes":"No", ! 2132: (switches & SW_SYNC_DOS5)?"Yes":"No"); ! 2133: printk("hardware_ver=%02x chip=%s microcode=%02x\n", ! 2134: hrev, ! 2135: (hostdata->chip==C_WD33C93)?"WD33c93": ! 2136: (hostdata->chip==C_WD33C93A)?"WD33c93A": ! 2137: (hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown", ! 2138: hostdata->microcode); ! 2139: #ifdef DEBUGGING_ON ! 2140: printk("setup_args = "); ! 2141: for (x=0; x<MAX_SETUP_ARGS; x++) ! 2142: printk("%s,",setup_args[x]); ! 2143: printk("\n"); ! 2144: #endif ! 2145: if (hostdata->sync_off == 0xff) ! 2146: printk("Sync-transfer DISABLED on all devices: ENABLE from command-line\n"); ! 2147: printk("IN2000 driver version %s - %s\n",IN2000_VERSION,IN2000_DATE); ! 2148: } ! 2149: ! 2150: return detect_count; ! 2151: } ! 2152: ! 2153: ! 2154: /* NOTE: I lifted this function straight out of the old driver, ! 2155: * and have not tested it. Presumably it does what it's ! 2156: * supposed to do... ! 2157: */ ! 2158: ! 2159: int in2000_biosparam(Disk *disk, kdev_t dev, int *iinfo) ! 2160: { ! 2161: int size; ! 2162: ! 2163: size = disk->capacity; ! 2164: iinfo[0] = 64; ! 2165: iinfo[1] = 32; ! 2166: iinfo[2] = size >> 11; ! 2167: ! 2168: /* This should approximate the large drive handling that the DOS ASPI manager ! 2169: uses. Drives very near the boundaries may not be handled correctly (i.e. ! 2170: near 2.0 Gb and 4.0 Gb) */ ! 2171: ! 2172: if (iinfo[2] > 1024) { ! 2173: iinfo[0] = 64; ! 2174: iinfo[1] = 63; ! 2175: iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]); ! 2176: } ! 2177: if (iinfo[2] > 1024) { ! 2178: iinfo[0] = 128; ! 2179: iinfo[1] = 63; ! 2180: iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]); ! 2181: } ! 2182: if (iinfo[2] > 1024) { ! 2183: iinfo[0] = 255; ! 2184: iinfo[1] = 63; ! 2185: iinfo[2] = disk->capacity / (iinfo[0] * iinfo[1]); ! 2186: } ! 2187: return 0; ! 2188: } ! 2189: ! 2190: ! 2191: ! 2192: struct proc_dir_entry proc_scsi_in2000 = { ! 2193: PROC_SCSI_IN2000, 6, "in2000", ! 2194: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 2195: }; ! 2196: ! 2197: ! 2198: int in2000_proc_info(char *buf, char **start, off_t off, int len, int hn, int in) ! 2199: { ! 2200: ! 2201: #ifdef PROC_INTERFACE ! 2202: ! 2203: char *bp; ! 2204: char tbuf[128]; ! 2205: unsigned long flags; ! 2206: struct Scsi_Host *instance; ! 2207: struct IN2000_hostdata *hd; ! 2208: Scsi_Cmnd *cmd; ! 2209: int x,i; ! 2210: static int stop = 0; ! 2211: ! 2212: for (instance=instance_list; instance; instance=instance->next) { ! 2213: if (instance->host_no == hn) ! 2214: break; ! 2215: } ! 2216: if (!instance) { ! 2217: printk("*** Hmm... Can't find host #%d!\n",hn); ! 2218: return (-ESRCH); ! 2219: } ! 2220: hd = (struct IN2000_hostdata *)instance->hostdata; ! 2221: ! 2222: /* If 'in' is TRUE we need to _read_ the proc file. We accept the following ! 2223: * keywords (same format as command-line, but only ONE per read): ! 2224: * debug ! 2225: * disconnect ! 2226: * period ! 2227: * resync ! 2228: * proc ! 2229: */ ! 2230: ! 2231: if (in) { ! 2232: buf[len] = '\0'; ! 2233: bp = buf; ! 2234: if (!strncmp(bp,"debug:",6)) { ! 2235: bp += 6; ! 2236: hd->args = simple_strtoul(bp,NULL,0) & DB_MASK; ! 2237: } ! 2238: else if (!strncmp(bp,"disconnect:",11)) { ! 2239: bp += 11; ! 2240: x = simple_strtoul(bp,NULL,0); ! 2241: if (x < DIS_NEVER || x > DIS_ALWAYS) ! 2242: x = DIS_ADAPTIVE; ! 2243: hd->disconnect = x; ! 2244: } ! 2245: else if (!strncmp(bp,"period:",7)) { ! 2246: bp += 7; ! 2247: x = simple_strtoul(bp,NULL,0); ! 2248: hd->default_sx_per = sx_table[round_period((unsigned int)x)].period_ns; ! 2249: } ! 2250: else if (!strncmp(bp,"resync:",7)) { ! 2251: bp += 7; ! 2252: x = simple_strtoul(bp,NULL,0); ! 2253: for (i=0; i<7; i++) ! 2254: if (x & (1<<i)) ! 2255: hd->sync_stat[i] = SS_UNSET; ! 2256: } ! 2257: else if (!strncmp(bp,"proc:",5)) { ! 2258: bp += 5; ! 2259: hd->proc = simple_strtoul(bp,NULL,0); ! 2260: } ! 2261: else if (!strncmp(bp,"level2:",7)) { ! 2262: bp += 7; ! 2263: hd->level2 = simple_strtoul(bp,NULL,0); ! 2264: } ! 2265: return len; ! 2266: } ! 2267: ! 2268: save_flags(flags); ! 2269: cli(); ! 2270: bp = buf; ! 2271: *bp = '\0'; ! 2272: if (hd->proc & PR_VERSION) { ! 2273: sprintf(tbuf,"\nVersion %s - %s. Compiled %s %s", ! 2274: IN2000_VERSION,IN2000_DATE,__DATE__,__TIME__); ! 2275: strcat(bp,tbuf); ! 2276: } ! 2277: if (hd->proc & PR_INFO) { ! 2278: sprintf(tbuf,"\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", ! 2279: (hd->dip_switch & 0x7f), instance->irq, hd->io_base, ! 2280: (hd->dip_switch & 0x40)?"Yes":"No", ! 2281: (hd->dip_switch & 0x20)?"Yes":"No"); ! 2282: strcat(bp,tbuf); ! 2283: strcat(bp,"\nsync_xfer[] = "); ! 2284: for (x=0; x<7; x++) { ! 2285: sprintf(tbuf,"\t%02x",hd->sync_xfer[x]); ! 2286: strcat(bp,tbuf); ! 2287: } ! 2288: strcat(bp,"\nsync_stat[] = "); ! 2289: for (x=0; x<7; x++) { ! 2290: sprintf(tbuf,"\t%02x",hd->sync_stat[x]); ! 2291: strcat(bp,tbuf); ! 2292: } ! 2293: } ! 2294: #ifdef PROC_STATISTICS ! 2295: if (hd->proc & PR_STATISTICS) { ! 2296: strcat(bp,"\ncommands issued: "); ! 2297: for (x=0; x<7; x++) { ! 2298: sprintf(tbuf,"\t%ld",hd->cmd_cnt[x]); ! 2299: strcat(bp,tbuf); ! 2300: } ! 2301: strcat(bp,"\ndisconnects allowed:"); ! 2302: for (x=0; x<7; x++) { ! 2303: sprintf(tbuf,"\t%ld",hd->disc_allowed_cnt[x]); ! 2304: strcat(bp,tbuf); ! 2305: } ! 2306: strcat(bp,"\ndisconnects done: "); ! 2307: for (x=0; x<7; x++) { ! 2308: sprintf(tbuf,"\t%ld",hd->disc_done_cnt[x]); ! 2309: strcat(bp,tbuf); ! 2310: } ! 2311: sprintf(tbuf,"\ninterrupts: \t%ld",hd->int_cnt); ! 2312: strcat(bp,tbuf); ! 2313: } ! 2314: #endif ! 2315: if (hd->proc & PR_CONNECTED) { ! 2316: strcat(bp,"\nconnected: "); ! 2317: if (hd->connected) { ! 2318: cmd = (Scsi_Cmnd *)hd->connected; ! 2319: sprintf(tbuf," %ld-%d:%d(%02x)", ! 2320: cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); ! 2321: strcat(bp,tbuf); ! 2322: } ! 2323: } ! 2324: if (hd->proc & PR_INPUTQ) { ! 2325: strcat(bp,"\ninput_Q: "); ! 2326: cmd = (Scsi_Cmnd *)hd->input_Q; ! 2327: while (cmd) { ! 2328: sprintf(tbuf," %ld-%d:%d(%02x)", ! 2329: cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); ! 2330: strcat(bp,tbuf); ! 2331: cmd = (Scsi_Cmnd *)cmd->host_scribble; ! 2332: } ! 2333: } ! 2334: if (hd->proc & PR_DISCQ) { ! 2335: strcat(bp,"\ndisconnected_Q:"); ! 2336: cmd = (Scsi_Cmnd *)hd->disconnected_Q; ! 2337: while (cmd) { ! 2338: sprintf(tbuf," %ld-%d:%d(%02x)", ! 2339: cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); ! 2340: strcat(bp,tbuf); ! 2341: cmd = (Scsi_Cmnd *)cmd->host_scribble; ! 2342: } ! 2343: } ! 2344: if (hd->proc & PR_TEST) { ! 2345: ; /* insert your own custom function here */ ! 2346: } ! 2347: strcat(bp,"\n"); ! 2348: restore_flags(flags); ! 2349: *start = buf; ! 2350: if (stop) { ! 2351: stop = 0; ! 2352: return 0; /* return 0 to signal end-of-file */ ! 2353: } ! 2354: if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */ ! 2355: stop = 1;; ! 2356: if (hd->proc & PR_STOP) /* stop every other time */ ! 2357: stop = 1; ! 2358: return strlen(bp); ! 2359: ! 2360: #else /* PROC_INTERFACE */ ! 2361: ! 2362: return 0; ! 2363: ! 2364: #endif /* PROC_INTERFACE */ ! 2365: ! 2366: } ! 2367: ! 2368: ! 2369: #ifdef MODULE ! 2370: ! 2371: Scsi_Host_Template driver_template = IN2000; ! 2372: ! 2373: #include "scsi_module.c" ! 2374: ! 2375: #endif ! 2376:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.