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