linux/drivers/scsi/fd_mcs.c
<<
>>
Prefs
   1/* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver
   2 *
   3 * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net)
   4 *
   5 * This driver is cloned from fdomain.* to specifically support
   6 * the Future Domain MCS 600/700 MCA SCSI adapters. Some PS/2s
   7 * also equipped with IBM Fast SCSI Adapter/A which is an OEM
   8 * of MCS 700.
   9 *
  10 * This driver also supports Reply SB16/SCSI card (the SCSI part).
  11 *
  12 * What makes this driver different is that this driver is MCA only
  13 * and it supports multiple adapters in the same system, IRQ 
  14 * sharing, some driver statistics, and maps highest SCSI id to sda.
  15 * All cards are auto-detected.
  16 *
  17 * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4
  18 *
  19 * LILO command-line options:
  20 *   fd_mcs=<FIFO_COUNT>[,<FIFO_SIZE>]
  21 *
  22 * ********************************************************
  23 * Please see Copyrights/Comments in fdomain.* for credits.
  24 * Following is from fdomain.c for acknowledgement:
  25 *
  26 * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
  27 * Revised: Wed Oct  2 11:10:55 1996 by r.faith@ieee.org
  28 * Author: Rickard E. Faith, faith@cs.unc.edu
  29 * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
  30 *
  31 * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $
  32
  33 * This program is free software; you can redistribute it and/or modify it
  34 * under the terms of the GNU General Public License as published by the
  35 * Free Software Foundation; either version 2, or (at your option) any
  36 * later version.
  37
  38 * This program is distributed in the hope that it will be useful, but
  39 * WITHOUT ANY WARRANTY; without even the implied warranty of
  40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  41 * General Public License for more details.
  42
  43 * You should have received a copy of the GNU General Public License along
  44 * with this program; if not, write to the Free Software Foundation, Inc.,
  45 * 675 Mass Ave, Cambridge, MA 02139, USA.
  46
  47 **************************************************************************
  48
  49 NOTES ON USER DEFINABLE OPTIONS:
  50
  51 DEBUG: This turns on the printing of various debug information.
  52
  53 ENABLE_PARITY: This turns on SCSI parity checking.  With the current
  54 driver, all attached devices must support SCSI parity.  If none of your
  55 devices support parity, then you can probably get the driver to work by
  56 turning this option off.  I have no way of testing this, however, and it
  57 would appear that no one ever uses this option.
  58
  59 FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the
  60 18C30 chip have a 2k cache).  When this many 512 byte blocks are filled by
  61 the SCSI device, an interrupt will be raised.  Therefore, this could be as
  62 low as 0, or as high as 16.  Note, however, that values which are too high
  63 or too low seem to prevent any interrupts from occurring, and thereby lock
  64 up the machine.  I have found that 2 is a good number, but throughput may
  65 be increased by changing this value to values which are close to 2.
  66 Please let me know if you try any different values.
  67 [*****Now a runtime option*****]
  68
  69 RESELECTION: This is no longer an option, since I gave up trying to
  70 implement it in version 4.x of this driver.  It did not improve
  71 performance at all and made the driver unstable (because I never found one
  72 of the two race conditions which were introduced by the multiple
  73 outstanding command code).  The instability seems a very high price to pay
  74 just so that you don't have to wait for the tape to rewind.  If you want
  75 this feature implemented, send me patches.  I'll be happy to send a copy
  76 of my (broken) driver to anyone who would like to see a copy.
  77
  78 **************************************************************************/
  79
  80#include <linux/module.h>
  81#include <linux/init.h>
  82#include <linux/interrupt.h>
  83#include <linux/blkdev.h>
  84#include <linux/errno.h>
  85#include <linux/string.h>
  86#include <linux/ioport.h>
  87#include <linux/proc_fs.h>
  88#include <linux/delay.h>
  89#include <linux/mca.h>
  90#include <linux/spinlock.h>
  91#include <linux/slab.h>
  92#include <scsi/scsicam.h>
  93#include <linux/mca-legacy.h>
  94
  95#include <asm/io.h>
  96#include <asm/system.h>
  97
  98#include "scsi.h"
  99#include <scsi/scsi_host.h>
 100
 101#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
 102
 103/* START OF USER DEFINABLE OPTIONS */
 104
 105#define DEBUG            0      /* Enable debugging output */
 106#define ENABLE_PARITY    1      /* Enable SCSI Parity */
 107
 108/* END OF USER DEFINABLE OPTIONS */
 109
 110#if DEBUG
 111#define EVERY_ACCESS     0      /* Write a line on every scsi access */
 112#define ERRORS_ONLY      1      /* Only write a line if there is an error */
 113#define DEBUG_MESSAGES   1      /* Debug MESSAGE IN phase */
 114#define DEBUG_ABORT      1      /* Debug abort() routine */
 115#define DEBUG_RESET      1      /* Debug reset() routine */
 116#define DEBUG_RACE       1      /* Debug interrupt-driven race condition */
 117#else
 118#define EVERY_ACCESS     0      /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
 119#define ERRORS_ONLY      0
 120#define DEBUG_MESSAGES   0
 121#define DEBUG_ABORT      0
 122#define DEBUG_RESET      0
 123#define DEBUG_RACE       0
 124#endif
 125
 126/* Errors are reported on the line, so we don't need to report them again */
 127#if EVERY_ACCESS
 128#undef ERRORS_ONLY
 129#define ERRORS_ONLY      0
 130#endif
 131
 132#if ENABLE_PARITY
 133#define PARITY_MASK      0x08
 134#else
 135#define PARITY_MASK      0x00
 136#endif
 137
 138enum chip_type {
 139        unknown = 0x00,
 140        tmc1800 = 0x01,
 141        tmc18c50 = 0x02,
 142        tmc18c30 = 0x03,
 143};
 144
 145enum {
 146        in_arbitration = 0x02,
 147        in_selection = 0x04,
 148        in_other = 0x08,
 149        disconnect = 0x10,
 150        aborted = 0x20,
 151        sent_ident = 0x40,
 152};
 153
 154enum in_port_type {
 155        Read_SCSI_Data = 0,
 156        SCSI_Status = 1,
 157        TMC_Status = 2,
 158        FIFO_Status = 3,        /* tmc18c50/tmc18c30 only */
 159        Interrupt_Cond = 4,     /* tmc18c50/tmc18c30 only */
 160        LSB_ID_Code = 5,
 161        MSB_ID_Code = 6,
 162        Read_Loopback = 7,
 163        SCSI_Data_NoACK = 8,
 164        Interrupt_Status = 9,
 165        Configuration1 = 10,
 166        Configuration2 = 11,    /* tmc18c50/tmc18c30 only */
 167        Read_FIFO = 12,
 168        FIFO_Data_Count = 14
 169};
 170
 171enum out_port_type {
 172        Write_SCSI_Data = 0,
 173        SCSI_Cntl = 1,
 174        Interrupt_Cntl = 2,
 175        SCSI_Mode_Cntl = 3,
 176        TMC_Cntl = 4,
 177        Memory_Cntl = 5,        /* tmc18c50/tmc18c30 only */
 178        Write_Loopback = 7,
 179        IO_Control = 11,        /* tmc18c30 only */
 180        Write_FIFO = 12
 181};
 182
 183struct fd_hostdata {
 184        unsigned long _bios_base;
 185        int _bios_major;
 186        int _bios_minor;
 187        volatile int _in_command;
 188        Scsi_Cmnd *_current_SC;
 189        enum chip_type _chip;
 190        int _adapter_mask;
 191        int _fifo_count;        /* Number of 512 byte blocks before INTR */
 192
 193        char _adapter_name[64];
 194#if DEBUG_RACE
 195        volatile int _in_interrupt_flag;
 196#endif
 197
 198        int _SCSI_Mode_Cntl_port;
 199        int _FIFO_Data_Count_port;
 200        int _Interrupt_Cntl_port;
 201        int _Interrupt_Status_port;
 202        int _Interrupt_Cond_port;
 203        int _Read_FIFO_port;
 204        int _Read_SCSI_Data_port;
 205        int _SCSI_Cntl_port;
 206        int _SCSI_Data_NoACK_port;
 207        int _SCSI_Status_port;
 208        int _TMC_Cntl_port;
 209        int _TMC_Status_port;
 210        int _Write_FIFO_port;
 211        int _Write_SCSI_Data_port;
 212
 213        int _FIFO_Size;         /* = 0x2000;  8k FIFO for
 214                                   pre-tmc18c30 chips */
 215        /* simple stats */
 216        int _Bytes_Read;
 217        int _Bytes_Written;
 218        int _INTR_Processed;
 219};
 220
 221#define FD_MAX_HOSTS 3          /* enough? */
 222
 223#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata)
 224#define bios_base             (HOSTDATA(shpnt)->_bios_base)
 225#define bios_major            (HOSTDATA(shpnt)->_bios_major)
 226#define bios_minor            (HOSTDATA(shpnt)->_bios_minor)
 227#define in_command            (HOSTDATA(shpnt)->_in_command)
 228#define current_SC            (HOSTDATA(shpnt)->_current_SC)
 229#define chip                  (HOSTDATA(shpnt)->_chip)
 230#define adapter_mask          (HOSTDATA(shpnt)->_adapter_mask)
 231#define FIFO_COUNT            (HOSTDATA(shpnt)->_fifo_count)
 232#define adapter_name          (HOSTDATA(shpnt)->_adapter_name)
 233#if DEBUG_RACE
 234#define in_interrupt_flag     (HOSTDATA(shpnt)->_in_interrupt_flag)
 235#endif
 236#define SCSI_Mode_Cntl_port   (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port)
 237#define FIFO_Data_Count_port  (HOSTDATA(shpnt)->_FIFO_Data_Count_port)
 238#define Interrupt_Cntl_port   (HOSTDATA(shpnt)->_Interrupt_Cntl_port)
 239#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port)
 240#define Interrupt_Cond_port   (HOSTDATA(shpnt)->_Interrupt_Cond_port)
 241#define Read_FIFO_port        (HOSTDATA(shpnt)->_Read_FIFO_port)
 242#define Read_SCSI_Data_port   (HOSTDATA(shpnt)->_Read_SCSI_Data_port)
 243#define SCSI_Cntl_port        (HOSTDATA(shpnt)->_SCSI_Cntl_port)
 244#define SCSI_Data_NoACK_port  (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port)
 245#define SCSI_Status_port      (HOSTDATA(shpnt)->_SCSI_Status_port)
 246#define TMC_Cntl_port         (HOSTDATA(shpnt)->_TMC_Cntl_port)
 247#define TMC_Status_port       (HOSTDATA(shpnt)->_TMC_Status_port)
 248#define Write_FIFO_port       (HOSTDATA(shpnt)->_Write_FIFO_port)
 249#define Write_SCSI_Data_port  (HOSTDATA(shpnt)->_Write_SCSI_Data_port)
 250#define FIFO_Size             (HOSTDATA(shpnt)->_FIFO_Size)
 251#define Bytes_Read            (HOSTDATA(shpnt)->_Bytes_Read)
 252#define Bytes_Written         (HOSTDATA(shpnt)->_Bytes_Written)
 253#define INTR_Processed        (HOSTDATA(shpnt)->_INTR_Processed)
 254
 255struct fd_mcs_adapters_struct {
 256        char *name;
 257        int id;
 258        enum chip_type fd_chip;
 259        int fifo_size;
 260        int fifo_count;
 261};
 262
 263#define REPLY_ID 0x5137
 264
 265static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
 266        {"Future Domain SCSI Adapter MCS-700(18C50)",
 267         0x60e9,
 268         tmc18c50,
 269         0x2000,
 270         4},
 271        {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
 272         0x6127,
 273         tmc1800,
 274         0x2000,
 275         4},
 276        {"Reply Sound Blaster/SCSI Adapter",
 277         REPLY_ID,
 278         tmc18c30,
 279         0x800,
 280         2},
 281};
 282
 283#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
 284
 285static irqreturn_t fd_mcs_intr(int irq, void *dev_id);
 286
 287static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
 288static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
 289static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 290
 291/* host information */
 292static int found = 0;
 293static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
 294
 295static int user_fifo_count = 0;
 296static int user_fifo_size = 0;
 297
 298#ifndef MODULE
 299static int __init fd_mcs_setup(char *str)
 300{
 301        static int done_setup = 0;
 302        int ints[3];
 303
 304        get_options(str, 3, ints);
 305        if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
 306                printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
 307                return 0;
 308        }
 309
 310        user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
 311        user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
 312        return 1;
 313}
 314
 315__setup("fd_mcs=", fd_mcs_setup);
 316#endif /* !MODULE */
 317
 318static void print_banner(struct Scsi_Host *shpnt)
 319{
 320        printk("scsi%d <fd_mcs>: ", shpnt->host_no);
 321
 322        if (bios_base) {
 323                printk("BIOS at 0x%lX", bios_base);
 324        } else {
 325                printk("No BIOS");
 326        }
 327
 328        printk(", HostID %d, %s Chip, IRQ %d, IO 0x%lX\n", shpnt->this_id, chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? "TMC-18C30" : (chip == tmc1800 ? "TMC-1800" : "Unknown")), shpnt->irq, shpnt->io_port);
 329}
 330
 331
 332static void do_pause(unsigned amount)
 333{                               /* Pause for amount*10 milliseconds */
 334        do {
 335                mdelay(10);
 336        } while (--amount);
 337}
 338
 339static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt)
 340{
 341        outb(0, SCSI_Cntl_port);
 342        outb(0, SCSI_Mode_Cntl_port);
 343        if (chip == tmc18c50 || chip == tmc18c30)
 344                outb(0x21 | PARITY_MASK, TMC_Cntl_port);        /* Clear forced intr. */
 345        else
 346                outb(0x01 | PARITY_MASK, TMC_Cntl_port);
 347}
 348
 349static int fd_mcs_detect(struct scsi_host_template * tpnt)
 350{
 351        int loop;
 352        struct Scsi_Host *shpnt;
 353
 354        /* get id, port, bios, irq */
 355        int slot;
 356        u_char pos2, pos3, pos4;
 357        int id, port, irq;
 358        unsigned long bios;
 359
 360        /* if not MCA machine, return */
 361        if (!MCA_bus)
 362                return 0;
 363
 364        /* changeable? */
 365        id = 7;
 366
 367        for (loop = 0; loop < FD_BRDS; loop++) {
 368                slot = 0;
 369                while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) {
 370
 371                        /* if we get this far, an adapter has been detected and is
 372                           enabled */
 373
 374                        printk(KERN_INFO "scsi  <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1);
 375
 376                        pos2 = mca_read_stored_pos(slot, 2);
 377                        pos3 = mca_read_stored_pos(slot, 3);
 378                        pos4 = mca_read_stored_pos(slot, 4);
 379
 380                        /* ready for next probe */
 381                        slot++;
 382
 383                        if (fd_mcs_adapters[loop].id == REPLY_ID) {     /* reply card */
 384                                static int reply_irq[] = { 10, 11, 14, 15 };
 385
 386                                bios = 0;       /* no bios */
 387
 388                                if (pos2 & 0x2)
 389                                        port = ports[pos4 & 0x3];
 390                                else
 391                                        continue;
 392
 393                                /* can't really disable it, same as irq=10 */
 394                                irq = reply_irq[((pos4 >> 2) & 0x1) + 2 * ((pos4 >> 4) & 0x1)];
 395                        } else {
 396                                bios = addresses[pos2 >> 6];
 397                                port = ports[(pos2 >> 4) & 0x03];
 398                                irq = interrupts[(pos2 >> 1) & 0x07];
 399                        }
 400
 401                        if (irq) {
 402                                /* claim the slot */
 403                                mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name);
 404
 405                                /* check irq/region */
 406                                if (request_irq(irq, fd_mcs_intr, IRQF_SHARED, "fd_mcs", hosts)) {
 407                                        printk(KERN_ERR "fd_mcs: interrupt is not available, skipping...\n");
 408                                        continue;
 409                                }
 410
 411                                /* request I/O region */
 412                                if (request_region(port, 0x10, "fd_mcs")) {
 413                                        printk(KERN_ERR "fd_mcs: I/O region is already in use, skipping...\n");
 414                                        continue;
 415                                }
 416                                /* register */
 417                                if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) {
 418                                        printk(KERN_ERR "fd_mcs: scsi_register() failed\n");
 419                                        release_region(port, 0x10);
 420                                        free_irq(irq, hosts);
 421                                        continue;
 422                                }
 423
 424
 425                                /* save name */
 426                                strcpy(adapter_name, fd_mcs_adapters[loop].name);
 427
 428                                /* chip/fifo */
 429                                chip = fd_mcs_adapters[loop].fd_chip;
 430                                /* use boot time value if available */
 431                                FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
 432                                FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
 433
 434/* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
 435#ifdef NOT_USED
 436                                /* *************************************************** */
 437                                /* Try to toggle 32-bit mode.  This only
 438                                   works on an 18c30 chip.  (User reports
 439                                   say this works, so we should switch to
 440                                   it in the near future.) */
 441                                outb(0x80, port + IO_Control);
 442                                if ((inb(port + Configuration2) & 0x80) == 0x80) {
 443                                        outb(0x00, port + IO_Control);
 444                                        if ((inb(port + Configuration2) & 0x80) == 0x00) {
 445                                                chip = tmc18c30;
 446                                                FIFO_Size = 0x800;      /* 2k FIFO */
 447
 448                                                printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
 449                                        }
 450                                }
 451
 452                                /* That should have worked, but appears to
 453                                   have problems.  Let's assume it is an
 454                                   18c30 if the RAM is disabled. */
 455
 456                                if (inb(port + Configuration2) & 0x02) {
 457                                        chip = tmc18c30;
 458                                        FIFO_Size = 0x800;      /* 2k FIFO */
 459
 460                                        printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
 461                                }
 462                                /* *************************************************** */
 463#endif
 464
 465                                /* IBM/ANSI scsi scan ordering */
 466                                /* Stick this back in when the scsi.c changes are there */
 467                                shpnt->reverse_ordering = 1;
 468
 469
 470                                /* saving info */
 471                                hosts[found++] = shpnt;
 472
 473                                shpnt->this_id = id;
 474                                shpnt->irq = irq;
 475                                shpnt->io_port = port;
 476                                shpnt->n_io_port = 0x10;
 477
 478                                /* save */
 479                                bios_base = bios;
 480                                adapter_mask = (1 << id);
 481
 482                                /* save more */
 483                                SCSI_Mode_Cntl_port = port + SCSI_Mode_Cntl;
 484                                FIFO_Data_Count_port = port + FIFO_Data_Count;
 485                                Interrupt_Cntl_port = port + Interrupt_Cntl;
 486                                Interrupt_Status_port = port + Interrupt_Status;
 487                                Interrupt_Cond_port = port + Interrupt_Cond;
 488                                Read_FIFO_port = port + Read_FIFO;
 489                                Read_SCSI_Data_port = port + Read_SCSI_Data;
 490                                SCSI_Cntl_port = port + SCSI_Cntl;
 491                                SCSI_Data_NoACK_port = port + SCSI_Data_NoACK;
 492                                SCSI_Status_port = port + SCSI_Status;
 493                                TMC_Cntl_port = port + TMC_Cntl;
 494                                TMC_Status_port = port + TMC_Status;
 495                                Write_FIFO_port = port + Write_FIFO;
 496                                Write_SCSI_Data_port = port + Write_SCSI_Data;
 497
 498                                Bytes_Read = 0;
 499                                Bytes_Written = 0;
 500                                INTR_Processed = 0;
 501
 502                                /* say something */
 503                                print_banner(shpnt);
 504
 505                                /* reset */
 506                                outb(1, SCSI_Cntl_port);
 507                                do_pause(2);
 508                                outb(0, SCSI_Cntl_port);
 509                                do_pause(115);
 510                                outb(0, SCSI_Mode_Cntl_port);
 511                                outb(PARITY_MASK, TMC_Cntl_port);
 512                                /* done reset */
 513                        }
 514                }
 515
 516                if (found == FD_MAX_HOSTS) {
 517                        printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
 518                        break;
 519                }
 520        }
 521
 522        return found;
 523}
 524
 525static const char *fd_mcs_info(struct Scsi_Host *shpnt)
 526{
 527        return adapter_name;
 528}
 529
 530static int TOTAL_INTR = 0;
 531
 532/*
 533 * inout : decides on the direction of the dataflow and the meaning of the 
 534 *         variables
 535 * buffer: If inout==FALSE data is being written to it else read from it
 536 * *start: If inout==FALSE start of the valid data in the buffer
 537 * offset: If inout==FALSE offset from the beginning of the imaginary file 
 538 *         from which we start writing into the buffer
 539 * length: If inout==FALSE max number of bytes to be written into the buffer 
 540 *         else number of bytes in the buffer
 541 */
 542static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
 543{
 544        int len = 0;
 545
 546        if (inout)
 547                return (-ENOSYS);
 548
 549        *start = buffer + offset;
 550
 551        len += sprintf(buffer + len, "Future Domain MCS-600/700 Driver %s\n", DRIVER_VERSION);
 552        len += sprintf(buffer + len, "HOST #%d: %s\n", shpnt->host_no, adapter_name);
 553        len += sprintf(buffer + len, "FIFO Size=0x%x, FIFO Count=%d\n", FIFO_Size, FIFO_COUNT);
 554        len += sprintf(buffer + len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
 555
 556        if ((len -= offset) <= 0)
 557                return 0;
 558        if (len > length)
 559                len = length;
 560        return len;
 561}
 562
 563static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
 564{
 565        int status;
 566        unsigned long timeout;
 567
 568        outb(0x82, SCSI_Cntl_port);     /* Bus Enable + Select */
 569        outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port);
 570
 571        /* Stop arbitration and enable parity */
 572        outb(PARITY_MASK, TMC_Cntl_port);
 573
 574        timeout = 350;          /* 350mS -- because of timeouts
 575                                   (was 250mS) */
 576
 577        do {
 578                status = inb(SCSI_Status_port); /* Read adapter status */
 579                if (status & 1) {       /* Busy asserted */
 580                        /* Enable SCSI Bus (on error, should make bus idle with 0) */
 581                        outb(0x80, SCSI_Cntl_port);
 582                        return 0;
 583                }
 584                udelay(1000);   /* wait one msec */
 585        } while (--timeout);
 586
 587        /* Make bus idle */
 588        fd_mcs_make_bus_idle(shpnt);
 589#if EVERY_ACCESS
 590        if (!target)
 591                printk("Selection failed\n");
 592#endif
 593#if ERRORS_ONLY
 594        if (!target) {
 595                static int flag = 0;
 596
 597                if (!flag)      /* Skip first failure for all chips. */
 598                        ++flag;
 599                else
 600                        printk("fd_mcs: Selection failed\n");
 601        }
 602#endif
 603        return 1;
 604}
 605
 606static void my_done(struct Scsi_Host *shpnt, int error)
 607{
 608        if (in_command) {
 609                in_command = 0;
 610                outb(0x00, Interrupt_Cntl_port);
 611                fd_mcs_make_bus_idle(shpnt);
 612                current_SC->result = error;
 613                current_SC->scsi_done(current_SC);
 614        } else {
 615                panic("fd_mcs: my_done() called outside of command\n");
 616        }
 617#if DEBUG_RACE
 618        in_interrupt_flag = 0;
 619#endif
 620}
 621
 622/* only my_done needs to be protected  */
 623static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
 624{
 625        unsigned long flags;
 626        int status;
 627        int done = 0;
 628        unsigned data_count, tmp_count;
 629
 630        int i = 0;
 631        struct Scsi_Host *shpnt;
 632
 633        TOTAL_INTR++;
 634
 635        /* search for one adapter-response on shared interrupt */
 636        while ((shpnt = hosts[i++])) {
 637                if ((inb(TMC_Status_port)) & 1)
 638                        break;
 639        }
 640
 641        /* return if some other device on this IRQ caused the interrupt */
 642        if (!shpnt) {
 643                return IRQ_NONE;
 644        }
 645
 646        INTR_Processed++;
 647
 648        outb(0x00, Interrupt_Cntl_port);
 649
 650        /* Abort calls my_done, so we do nothing here. */
 651        if (current_SC->SCp.phase & aborted) {
 652#if DEBUG_ABORT
 653                printk("Interrupt after abort, ignoring\n");
 654#endif
 655                /* return IRQ_HANDLED; */
 656        }
 657#if DEBUG_RACE
 658        ++in_interrupt_flag;
 659#endif
 660
 661        if (current_SC->SCp.phase & in_arbitration) {
 662                status = inb(TMC_Status_port);  /* Read adapter status */
 663                if (!(status & 0x02)) {
 664#if EVERY_ACCESS
 665                        printk(" AFAIL ");
 666#endif
 667                        spin_lock_irqsave(shpnt->host_lock, flags);
 668                        my_done(shpnt, DID_BUS_BUSY << 16);
 669                        spin_unlock_irqrestore(shpnt->host_lock, flags);
 670                        return IRQ_HANDLED;
 671                }
 672                current_SC->SCp.phase = in_selection;
 673
 674                outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
 675
 676                outb(0x82, SCSI_Cntl_port);     /* Bus Enable + Select */
 677                outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
 678
 679                /* Stop arbitration and enable parity */
 680                outb(0x10 | PARITY_MASK, TMC_Cntl_port);
 681#if DEBUG_RACE
 682                in_interrupt_flag = 0;
 683#endif
 684                return IRQ_HANDLED;
 685        } else if (current_SC->SCp.phase & in_selection) {
 686                status = inb(SCSI_Status_port);
 687                if (!(status & 0x01)) {
 688                        /* Try again, for slow devices */
 689                        if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
 690#if EVERY_ACCESS
 691                                printk(" SFAIL ");
 692#endif
 693                                spin_lock_irqsave(shpnt->host_lock, flags);
 694                                my_done(shpnt, DID_NO_CONNECT << 16);
 695                                spin_unlock_irqrestore(shpnt->host_lock, flags);
 696                                return IRQ_HANDLED;
 697                        } else {
 698#if EVERY_ACCESS
 699                                printk(" AltSel ");
 700#endif
 701                                /* Stop arbitration and enable parity */
 702                                outb(0x10 | PARITY_MASK, TMC_Cntl_port);
 703                        }
 704                }
 705                current_SC->SCp.phase = in_other;
 706                outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
 707                outb(0x80, SCSI_Cntl_port);
 708#if DEBUG_RACE
 709                in_interrupt_flag = 0;
 710#endif
 711                return IRQ_HANDLED;
 712        }
 713
 714        /* current_SC->SCp.phase == in_other: this is the body of the routine */
 715
 716        status = inb(SCSI_Status_port);
 717
 718        if (status & 0x10) {    /* REQ */
 719
 720                switch (status & 0x0e) {
 721
 722                case 0x08:      /* COMMAND OUT */
 723                        outb(current_SC->cmnd[current_SC->SCp.sent_command++], Write_SCSI_Data_port);
 724#if EVERY_ACCESS
 725                        printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]);
 726#endif
 727                        break;
 728                case 0x00:      /* DATA OUT -- tmc18c50/tmc18c30 only */
 729                        if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
 730                                current_SC->SCp.have_data_in = -1;
 731                                outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
 732                        }
 733                        break;
 734                case 0x04:      /* DATA IN -- tmc18c50/tmc18c30 only */
 735                        if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
 736                                current_SC->SCp.have_data_in = 1;
 737                                outb(0x90 | PARITY_MASK, TMC_Cntl_port);
 738                        }
 739                        break;
 740                case 0x0c:      /* STATUS IN */
 741                        current_SC->SCp.Status = inb(Read_SCSI_Data_port);
 742#if EVERY_ACCESS
 743                        printk("Status = %x, ", current_SC->SCp.Status);
 744#endif
 745#if ERRORS_ONLY
 746                        if (current_SC->SCp.Status && current_SC->SCp.Status != 2 && current_SC->SCp.Status != 8) {
 747                                printk("ERROR fd_mcs: target = %d, command = %x, status = %x\n", current_SC->device->id, current_SC->cmnd[0], current_SC->SCp.Status);
 748                        }
 749#endif
 750                        break;
 751                case 0x0a:      /* MESSAGE OUT */
 752                        outb(MESSAGE_REJECT, Write_SCSI_Data_port);     /* Reject */
 753                        break;
 754                case 0x0e:      /* MESSAGE IN */
 755                        current_SC->SCp.Message = inb(Read_SCSI_Data_port);
 756#if EVERY_ACCESS
 757                        printk("Message = %x, ", current_SC->SCp.Message);
 758#endif
 759                        if (!current_SC->SCp.Message)
 760                                ++done;
 761#if DEBUG_MESSAGES || EVERY_ACCESS
 762                        if (current_SC->SCp.Message) {
 763                                printk("fd_mcs: message = %x\n", current_SC->SCp.Message);
 764                        }
 765#endif
 766                        break;
 767                }
 768        }
 769
 770        if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
 771                /* We have to get the FIFO direction
 772                   correct, so I've made a table based
 773                   on the SCSI Standard of which commands
 774                   appear to require a DATA OUT phase.
 775                 */
 776                /*
 777                   p. 94: Command for all device types
 778                   CHANGE DEFINITION            40 DATA OUT
 779                   COMPARE                      39 DATA OUT
 780                   COPY                         18 DATA OUT
 781                   COPY AND VERIFY              3a DATA OUT
 782                   INQUIRY                      12 
 783                   LOG SELECT                   4c DATA OUT
 784                   LOG SENSE                    4d
 785                   MODE SELECT (6)              15 DATA OUT
 786                   MODE SELECT (10)             55 DATA OUT
 787                   MODE SENSE (6)               1a
 788                   MODE SENSE (10)              5a
 789                   READ BUFFER                  3c
 790                   RECEIVE DIAGNOSTIC RESULTS   1c
 791                   REQUEST SENSE                03
 792                   SEND DIAGNOSTIC              1d DATA OUT
 793                   TEST UNIT READY              00
 794                   WRITE BUFFER                 3b DATA OUT
 795
 796                   p.178: Commands for direct-access devices (not listed on p. 94)
 797                   FORMAT UNIT                  04 DATA OUT
 798                   LOCK-UNLOCK CACHE            36
 799                   PRE-FETCH                    34
 800                   PREVENT-ALLOW MEDIUM REMOVAL 1e
 801                   READ (6)/RECEIVE             08
 802                   READ (10)                    3c
 803                   READ CAPACITY                25
 804                   READ DEFECT DATA (10)        37
 805                   READ LONG                    3e
 806                   REASSIGN BLOCKS              07 DATA OUT
 807                   RELEASE                      17
 808                   RESERVE                      16 DATA OUT
 809                   REZERO UNIT/REWIND           01
 810                   SEARCH DATA EQUAL (10)       31 DATA OUT
 811                   SEARCH DATA HIGH (10)        30 DATA OUT
 812                   SEARCH DATA LOW (10)         32 DATA OUT
 813                   SEEK (6)                     0b
 814                   SEEK (10)                    2b
 815                   SET LIMITS (10)              33
 816                   START STOP UNIT              1b
 817                   SYNCHRONIZE CACHE            35
 818                   VERIFY (10)                  2f
 819                   WRITE (6)/PRINT/SEND         0a DATA OUT
 820                   WRITE (10)/SEND              2a DATA OUT
 821                   WRITE AND VERIFY (10)        2e DATA OUT
 822                   WRITE LONG                   3f DATA OUT
 823                   WRITE SAME                   41 DATA OUT ?
 824
 825                   p. 261: Commands for sequential-access devices (not previously listed)
 826                   ERASE                        19
 827                   LOAD UNLOAD                  1b
 828                   LOCATE                       2b
 829                   READ BLOCK LIMITS            05
 830                   READ POSITION                34
 831                   READ REVERSE                 0f
 832                   RECOVER BUFFERED DATA        14
 833                   SPACE                        11
 834                   WRITE FILEMARKS              10 ?
 835
 836                   p. 298: Commands for printer devices (not previously listed)
 837                   ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
 838                   SLEW AND PRINT               0b DATA OUT  -- same as seek
 839                   STOP PRINT                   1b
 840                   SYNCHRONIZE BUFFER           10
 841
 842                   p. 315: Commands for processor devices (not previously listed)
 843
 844                   p. 321: Commands for write-once devices (not previously listed)
 845                   MEDIUM SCAN                  38
 846                   READ (12)                    a8
 847                   SEARCH DATA EQUAL (12)       b1 DATA OUT
 848                   SEARCH DATA HIGH (12)        b0 DATA OUT
 849                   SEARCH DATA LOW (12)         b2 DATA OUT
 850                   SET LIMITS (12)              b3
 851                   VERIFY (12)                  af
 852                   WRITE (12)                   aa DATA OUT
 853                   WRITE AND VERIFY (12)        ae DATA OUT
 854
 855                   p. 332: Commands for CD-ROM devices (not previously listed)
 856                   PAUSE/RESUME                 4b
 857                   PLAY AUDIO (10)              45
 858                   PLAY AUDIO (12)              a5
 859                   PLAY AUDIO MSF               47
 860                   PLAY TRACK RELATIVE (10)     49
 861                   PLAY TRACK RELATIVE (12)     a9
 862                   READ HEADER                  44
 863                   READ SUB-CHANNEL             42
 864                   READ TOC                     43
 865
 866                   p. 370: Commands for scanner devices (not previously listed)
 867                   GET DATA BUFFER STATUS       34
 868                   GET WINDOW                   25
 869                   OBJECT POSITION              31
 870                   SCAN                         1b
 871                   SET WINDOW                   24 DATA OUT
 872
 873                   p. 391: Commands for optical memory devices (not listed)
 874                   ERASE (10)                   2c
 875                   ERASE (12)                   ac
 876                   MEDIUM SCAN                  38 DATA OUT
 877                   READ DEFECT DATA (12)        b7
 878                   READ GENERATION              29
 879                   READ UPDATED BLOCK           2d
 880                   UPDATE BLOCK                 3d DATA OUT
 881
 882                   p. 419: Commands for medium changer devices (not listed)
 883                   EXCHANGE MEDIUM              46
 884                   INITIALIZE ELEMENT STATUS    07
 885                   MOVE MEDIUM                  a5
 886                   POSITION TO ELEMENT          2b
 887                   READ ELEMENT STATUS          b8
 888                   REQUEST VOL. ELEMENT ADDRESS b5
 889                   SEND VOLUME TAG              b6 DATA OUT
 890
 891                   p. 454: Commands for communications devices (not listed previously)
 892                   GET MESSAGE (6)              08
 893                   GET MESSAGE (10)             28
 894                   GET MESSAGE (12)             a8
 895                 */
 896
 897                switch (current_SC->cmnd[0]) {
 898                case CHANGE_DEFINITION:
 899                case COMPARE:
 900                case COPY:
 901                case COPY_VERIFY:
 902                case LOG_SELECT:
 903                case MODE_SELECT:
 904                case MODE_SELECT_10:
 905                case SEND_DIAGNOSTIC:
 906                case WRITE_BUFFER:
 907
 908                case FORMAT_UNIT:
 909                case REASSIGN_BLOCKS:
 910                case RESERVE:
 911                case SEARCH_EQUAL:
 912                case SEARCH_HIGH:
 913                case SEARCH_LOW:
 914                case WRITE_6:
 915                case WRITE_10:
 916                case WRITE_VERIFY:
 917                case 0x3f:
 918                case 0x41:
 919
 920                case 0xb1:
 921                case 0xb0:
 922                case 0xb2:
 923                case 0xaa:
 924                case 0xae:
 925
 926                case 0x24:
 927
 928                case 0x38:
 929                case 0x3d:
 930
 931                case 0xb6:
 932
 933                case 0xea:      /* alternate number for WRITE LONG */
 934
 935                        current_SC->SCp.have_data_in = -1;
 936                        outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
 937                        break;
 938
 939                case 0x00:
 940                default:
 941
 942                        current_SC->SCp.have_data_in = 1;
 943                        outb(0x90 | PARITY_MASK, TMC_Cntl_port);
 944                        break;
 945                }
 946        }
 947
 948        if (current_SC->SCp.have_data_in == -1) {       /* DATA OUT */
 949                while ((data_count = FIFO_Size - inw(FIFO_Data_Count_port)) > 512) {
 950#if EVERY_ACCESS
 951                        printk("DC=%d, ", data_count);
 952#endif
 953                        if (data_count > current_SC->SCp.this_residual)
 954                                data_count = current_SC->SCp.this_residual;
 955                        if (data_count > 0) {
 956#if EVERY_ACCESS
 957                                printk("%d OUT, ", data_count);
 958#endif
 959                                if (data_count == 1) {
 960                                        Bytes_Written++;
 961
 962                                        outb(*current_SC->SCp.ptr++, Write_FIFO_port);
 963                                        --current_SC->SCp.this_residual;
 964                                } else {
 965                                        data_count >>= 1;
 966                                        tmp_count = data_count << 1;
 967                                        outsw(Write_FIFO_port, current_SC->SCp.ptr, data_count);
 968                                        current_SC->SCp.ptr += tmp_count;
 969                                        Bytes_Written += tmp_count;
 970                                        current_SC->SCp.this_residual -= tmp_count;
 971                                }
 972                        }
 973                        if (!current_SC->SCp.this_residual) {
 974                                if (current_SC->SCp.buffers_residual) {
 975                                        --current_SC->SCp.buffers_residual;
 976                                        ++current_SC->SCp.buffer;
 977                                        current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
 978                                        current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
 979                                } else
 980                                        break;
 981                        }
 982                }
 983        } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
 984                while ((data_count = inw(FIFO_Data_Count_port)) > 0) {
 985#if EVERY_ACCESS
 986                        printk("DC=%d, ", data_count);
 987#endif
 988                        if (data_count > current_SC->SCp.this_residual)
 989                                data_count = current_SC->SCp.this_residual;
 990                        if (data_count) {
 991#if EVERY_ACCESS
 992                                printk("%d IN, ", data_count);
 993#endif
 994                                if (data_count == 1) {
 995                                        Bytes_Read++;
 996                                        *current_SC->SCp.ptr++ = inb(Read_FIFO_port);
 997                                        --current_SC->SCp.this_residual;
 998                                } else {
 999                                        data_count >>= 1;       /* Number of words */
1000                                        tmp_count = data_count << 1;
1001                                        insw(Read_FIFO_port, current_SC->SCp.ptr, data_count);
1002                                        current_SC->SCp.ptr += tmp_count;
1003                                        Bytes_Read += tmp_count;
1004                                        current_SC->SCp.this_residual -= tmp_count;
1005                                }
1006                        }
1007                        if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
1008                                --current_SC->SCp.buffers_residual;
1009                                ++current_SC->SCp.buffer;
1010                                current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1011                                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1012                        }
1013                }
1014        }
1015
1016        if (done) {
1017#if EVERY_ACCESS
1018                printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
1019#endif
1020
1021#if EVERY_ACCESS
1022                printk("BEFORE MY_DONE. . .");
1023#endif
1024                spin_lock_irqsave(shpnt->host_lock, flags);
1025                my_done(shpnt, (current_SC->SCp.Status & 0xff)
1026                        | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
1027                spin_unlock_irqrestore(shpnt->host_lock, flags);
1028#if EVERY_ACCESS
1029                printk("RETURNING.\n");
1030#endif
1031
1032        } else {
1033                if (current_SC->SCp.phase & disconnect) {
1034                        outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port);
1035                        outb(0x00, SCSI_Cntl_port);
1036                } else {
1037                        outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
1038                }
1039        }
1040#if DEBUG_RACE
1041        in_interrupt_flag = 0;
1042#endif
1043        return IRQ_HANDLED;
1044}
1045
1046static int fd_mcs_release(struct Scsi_Host *shpnt)
1047{
1048        int i, this_host, irq_usage;
1049
1050        release_region(shpnt->io_port, shpnt->n_io_port);
1051
1052        this_host = -1;
1053        irq_usage = 0;
1054        for (i = 0; i < found; i++) {
1055                if (shpnt == hosts[i])
1056                        this_host = i;
1057                if (shpnt->irq == hosts[i]->irq)
1058                        irq_usage++;
1059        }
1060
1061        /* only for the last one */
1062        if (1 == irq_usage)
1063                free_irq(shpnt->irq, hosts);
1064
1065        found--;
1066
1067        for (i = this_host; i < found; i++)
1068                hosts[i] = hosts[i + 1];
1069
1070        hosts[found] = NULL;
1071
1072        return 0;
1073}
1074
1075static int fd_mcs_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
1076{
1077        struct Scsi_Host *shpnt = SCpnt->device->host;
1078
1079        if (in_command) {
1080                panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
1081        }
1082#if EVERY_ACCESS
1083        printk("queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1084                SCpnt->target, *(unsigned char *) SCpnt->cmnd,
1085                scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
1086#endif
1087
1088        fd_mcs_make_bus_idle(shpnt);
1089
1090        SCpnt->scsi_done = done;        /* Save this for the done function */
1091        current_SC = SCpnt;
1092
1093        /* Initialize static data */
1094
1095        if (scsi_bufflen(current_SC)) {
1096                current_SC->SCp.buffer = scsi_sglist(current_SC);
1097                current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1098                current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1099                current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
1100        } else {
1101                current_SC->SCp.ptr = NULL;
1102                current_SC->SCp.this_residual = 0;
1103                current_SC->SCp.buffer = NULL;
1104                current_SC->SCp.buffers_residual = 0;
1105        }
1106
1107
1108        current_SC->SCp.Status = 0;
1109        current_SC->SCp.Message = 0;
1110        current_SC->SCp.have_data_in = 0;
1111        current_SC->SCp.sent_command = 0;
1112        current_SC->SCp.phase = in_arbitration;
1113
1114        /* Start arbitration */
1115        outb(0x00, Interrupt_Cntl_port);
1116        outb(0x00, SCSI_Cntl_port);     /* Disable data drivers */
1117        outb(adapter_mask, SCSI_Data_NoACK_port);       /* Set our id bit */
1118        in_command = 1;
1119        outb(0x20, Interrupt_Cntl_port);
1120        outb(0x14 | PARITY_MASK, TMC_Cntl_port);        /* Start arbitration */
1121
1122        return 0;
1123}
1124
1125static DEF_SCSI_QCMD(fd_mcs_queue)
1126
1127#if DEBUG_ABORT || DEBUG_RESET
1128static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
1129{
1130        unsigned int imr;
1131        unsigned int irr;
1132        unsigned int isr;
1133        struct Scsi_Host *shpnt = SCpnt->host;
1134
1135        if (!SCpnt || !SCpnt->host) {
1136                printk("fd_mcs: cannot provide detailed information\n");
1137        }
1138
1139        printk("%s\n", fd_mcs_info(SCpnt->host));
1140        print_banner(SCpnt->host);
1141        switch (SCpnt->SCp.phase) {
1142        case in_arbitration:
1143                printk("arbitration ");
1144                break;
1145        case in_selection:
1146                printk("selection ");
1147                break;
1148        case in_other:
1149                printk("other ");
1150                break;
1151        default:
1152                printk("unknown ");
1153                break;
1154        }
1155
1156        printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1157                SCpnt->SCp.phase, SCpnt->device->id, *(unsigned char *) SCpnt->cmnd,
1158                scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
1159        printk("sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, SCpnt->timeout);
1160#if DEBUG_RACE
1161        printk("in_interrupt_flag = %d\n", in_interrupt_flag);
1162#endif
1163
1164        imr = (inb(0x0a1) << 8) + inb(0x21);
1165        outb(0x0a, 0xa0);
1166        irr = inb(0xa0) << 8;
1167        outb(0x0a, 0x20);
1168        irr += inb(0x20);
1169        outb(0x0b, 0xa0);
1170        isr = inb(0xa0) << 8;
1171        outb(0x0b, 0x20);
1172        isr += inb(0x20);
1173
1174        /* Print out interesting information */
1175        printk("IMR = 0x%04x", imr);
1176        if (imr & (1 << shpnt->irq))
1177                printk(" (masked)");
1178        printk(", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr);
1179
1180        printk("SCSI Status      = 0x%02x\n", inb(SCSI_Status_port));
1181        printk("TMC Status       = 0x%02x", inb(TMC_Status_port));
1182        if (inb(TMC_Status_port) & 1)
1183                printk(" (interrupt)");
1184        printk("\n");
1185        printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port));
1186        if (inb(Interrupt_Status_port) & 0x08)
1187                printk(" (enabled)");
1188        printk("\n");
1189        if (chip == tmc18c50 || chip == tmc18c30) {
1190                printk("FIFO Status      = 0x%02x\n", inb(shpnt->io_port + FIFO_Status));
1191                printk("Int. Condition   = 0x%02x\n", inb(shpnt->io_port + Interrupt_Cond));
1192        }
1193        printk("Configuration 1  = 0x%02x\n", inb(shpnt->io_port + Configuration1));
1194        if (chip == tmc18c50 || chip == tmc18c30)
1195                printk("Configuration 2  = 0x%02x\n", inb(shpnt->io_port + Configuration2));
1196}
1197#endif
1198
1199static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
1200{
1201        struct Scsi_Host *shpnt = SCpnt->device->host;
1202
1203        unsigned long flags;
1204#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1205        printk("fd_mcs: abort ");
1206#endif
1207
1208        spin_lock_irqsave(shpnt->host_lock, flags);
1209        if (!in_command) {
1210#if EVERY_ACCESS || ERRORS_ONLY
1211                printk(" (not in command)\n");
1212#endif
1213                spin_unlock_irqrestore(shpnt->host_lock, flags);
1214                return FAILED;
1215        } else
1216                printk("\n");
1217
1218#if DEBUG_ABORT
1219        fd_mcs_print_info(SCpnt);
1220#endif
1221
1222        fd_mcs_make_bus_idle(shpnt);
1223
1224        current_SC->SCp.phase |= aborted;
1225
1226        current_SC->result = DID_ABORT << 16;
1227
1228        /* Aborts are not done well. . . */
1229        my_done(shpnt, DID_ABORT << 16);
1230
1231        spin_unlock_irqrestore(shpnt->host_lock, flags);
1232        return SUCCESS;
1233}
1234
1235static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
1236        struct Scsi_Host *shpnt = SCpnt->device->host;
1237        unsigned long flags;
1238
1239#if DEBUG_RESET
1240        static int called_once = 0;
1241#endif
1242
1243#if ERRORS_ONLY
1244        if (SCpnt)
1245                printk("fd_mcs: SCSI Bus Reset\n");
1246#endif
1247
1248#if DEBUG_RESET
1249        if (called_once)
1250                fd_mcs_print_info(current_SC);
1251        called_once = 1;
1252#endif
1253
1254        spin_lock_irqsave(shpnt->host_lock, flags);
1255
1256        outb(1, SCSI_Cntl_port);
1257        do_pause(2);
1258        outb(0, SCSI_Cntl_port);
1259        do_pause(115);
1260        outb(0, SCSI_Mode_Cntl_port);
1261        outb(PARITY_MASK, TMC_Cntl_port);
1262
1263        spin_unlock_irqrestore(shpnt->host_lock, flags);
1264
1265        /* Unless this is the very first call (i.e., SCPnt == NULL), everything
1266           is probably hosed at this point.  We will, however, try to keep
1267           things going by informing the high-level code that we need help. */
1268                return SUCCESS;
1269}
1270
1271#include <scsi/scsi_ioctl.h>
1272
1273static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
1274                            sector_t capacity, int *info_array) 
1275{
1276        unsigned char *p = scsi_bios_ptable(bdev);
1277        int size = capacity;
1278
1279        /* BIOS >= 3.4 for MCA cards */
1280        /* This algorithm was provided by Future Domain (much thanks!). */
1281
1282        if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
1283            && p[4]) {  /* Partition type */
1284                /* The partition table layout is as follows:
1285
1286                   Start: 0x1b3h
1287                   Offset: 0 = partition status
1288                   1 = starting head
1289                   2 = starting sector and cylinder (word, encoded)
1290                   4 = partition type
1291                   5 = ending head
1292                   6 = ending sector and cylinder (word, encoded)
1293                   8 = starting absolute sector (double word)
1294                   c = number of sectors (double word)
1295                   Signature: 0x1fe = 0x55aa
1296
1297                   So, this algorithm assumes:
1298                   1) the first partition table is in use,
1299                   2) the data in the first entry is correct, and
1300                   3) partitions never divide cylinders
1301
1302                   Note that (1) may be FALSE for NetBSD (and other BSD flavors),
1303                   as well as for Linux.  Note also, that Linux doesn't pay any
1304                   attention to the fields that are used by this algorithm -- it
1305                   only uses the absolute sector data.  Recent versions of Linux's
1306                   fdisk(1) will fill this data in correctly, and forthcoming
1307                   versions will check for consistency.
1308
1309                   Checking for a non-zero partition type is not part of the
1310                   Future Domain algorithm, but it seemed to be a reasonable thing
1311                   to do, especially in the Linux and BSD worlds. */
1312
1313                info_array[0] = p[5] + 1;       /* heads */
1314                info_array[1] = p[6] & 0x3f;    /* sectors */
1315        } else {
1316                /* Note that this new method guarantees that there will always be
1317                   less than 1024 cylinders on a platter.  This is good for drives
1318                   up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
1319                if ((unsigned int) size >= 0x7e0000U) 
1320                {
1321                        info_array[0] = 0xff;   /* heads   = 255 */
1322                        info_array[1] = 0x3f;   /* sectors =  63 */
1323                } else if ((unsigned int) size >= 0x200000U) {
1324                        info_array[0] = 0x80;   /* heads   = 128 */
1325                        info_array[1] = 0x3f;   /* sectors =  63 */
1326                } else {
1327                        info_array[0] = 0x40;   /* heads   =  64 */
1328                        info_array[1] = 0x20;   /* sectors =  32 */
1329                }
1330        }
1331        /* For both methods, compute the cylinders */
1332        info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
1333        kfree(p);
1334        return 0;
1335}
1336
1337static struct scsi_host_template driver_template = {
1338        .proc_name                      = "fd_mcs",
1339        .proc_info                      = fd_mcs_proc_info,
1340        .detect                         = fd_mcs_detect,
1341        .release                        = fd_mcs_release,
1342        .info                           = fd_mcs_info,
1343        .queuecommand                   = fd_mcs_queue, 
1344        .eh_abort_handler               = fd_mcs_abort,
1345        .eh_bus_reset_handler           = fd_mcs_bus_reset,
1346        .bios_param                     = fd_mcs_biosparam,
1347        .can_queue                      = 1,
1348        .this_id                        = 7,
1349        .sg_tablesize                   = 64,
1350        .cmd_per_lun                    = 1,
1351        .use_clustering                 = DISABLE_CLUSTERING,
1352};
1353#include "scsi_module.c"
1354
1355MODULE_LICENSE("GPL");
1356