aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/scsi/00-INDEX2
-rw-r--r--Documentation/scsi/ibmmca.txt1402
-rw-r--r--Documentation/scsi/scsi-parameters.txt6
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt2
-rw-r--r--drivers/scsi/Kconfig83
-rw-r--r--drivers/scsi/Makefile2
-rw-r--r--drivers/scsi/aha1542.c66
-rw-r--r--drivers/scsi/fd_mcs.c1354
-rw-r--r--drivers/scsi/ibmmca.c2379
-rw-r--r--drivers/scsi/sim710.c124
10 files changed, 6 insertions, 5414 deletions
diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX
index b7dd650..9b0787f 100644
--- a/Documentation/scsi/00-INDEX
+++ b/Documentation/scsi/00-INDEX
@@ -56,8 +56,6 @@ g_NCR5380.txt
- info on driver for NCR5380 and NCR53c400 based adapters
hptiop.txt
- HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
-ibmmca.txt
- - info on driver for IBM adapters with MCA bus
in2000.txt
- info on in2000 driver
libsas.txt
diff --git a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt
deleted file mode 100644
index ac41a9f..0000000
--- a/Documentation/scsi/ibmmca.txt
+++ /dev/null
@@ -1,1402 +0,0 @@
-
- -=< The IBM Microchannel SCSI-Subsystem >=-
-
- for the IBM PS/2 series
-
- Low Level Software-Driver for Linux
-
- Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU
- General Public License. Originally written by Martin Kolinek, December 1995.
- Officially modified and maintained by Michael Lang since January 1999.
-
- Version 4.0a
-
- Last update: January 3, 2001
-
- Before you Start
- ----------------
- This is the common README.ibmmca file for all driver releases of the
- IBM MCA SCSI driver for Linux. Please note, that driver releases 4.0
- or newer do not work with kernel versions older than 2.4.0, while driver
- versions older than 4.0 do not work with kernels 2.4.0 or later! If you
- try to compile your kernel with the wrong driver source, the
- compilation is aborted and you get a corresponding error message. This is
- no bug in the driver; it prevents you from using the wrong source code
- with the wrong kernel version.
-
- Authors of this Driver
- ----------------------
- - Chris Beauregard (improvement of the SCSI-device mapping by the driver)
- - Martin Kolinek (origin, first release of this driver)
- - Klaus Kudielka (multiple SCSI-host management/detection, adaption to
- Linux Kernel 2.1.x, module support)
- - Michael Lang (assigning original pun/lun mapping, dynamical ldn
- assignment, rewritten adapter detection, this file,
- patches, official driver maintenance and subsequent
- debugging, related with the driver)
-
- Table of Contents
- -----------------
- 1 Abstract
- 2 Driver Description
- 2.1 IBM SCSI-Subsystem Detection
- 2.2 Physical Units, Logical Units, and Logical Devices
- 2.3 SCSI-Device Recognition and dynamical ldn Assignment
- 2.4 SCSI-Device Order
- 2.5 Regular SCSI-Command-Processing
- 2.6 Abort & Reset Commands
- 2.7 Disk Geometry
- 2.8 Kernel Boot Option
- 2.9 Driver Module Support
- 2.10 Multiple Hostadapter Support
- 2.11 /proc/scsi-Filesystem Information
- 2.12 /proc/mca-Filesystem Information
- 2.13 Supported IBM SCSI-Subsystems
- 2.14 Linux Kernel Versions
- 3 Code History
- 4 To do
- 5 Users' Manual
- 5.1 Commandline Parameters
- 5.2 Troubleshooting
- 5.3 Bug reports
- 5.4 Support WWW-page
- 6 References
- 7 Credits to
- 7.1 People
- 7.2 Sponsors & Supporters
- 8 Trademarks
- 9 Disclaimer
-
- * * *
-
- 1 Abstract
- ----------
- This README-file describes the IBM SCSI-subsystem low level driver for
- Linux. The descriptions which were formerly kept in the source code have
- been taken out of this file to simplify the codes readability. The driver
- description has been updated, as most of the former description was already
- quite outdated. The history of the driver development is also kept inside
- here. Multiple historical developments have been summarized to shorten the
- text size a bit. At the end of this file you can find a small manual for
- this driver and hints to get it running on your machine.
-
- 2 Driver Description
- --------------------
- 2.1 IBM SCSI-Subsystem Detection
- --------------------------------
- This is done in the ibmmca_detect() function. It first checks, if the
- Microchannel-bus support is enabled, as the IBM SCSI-subsystem needs the
- Microchannel. In a next step, a free interrupt is chosen and the main
- interrupt handler is connected to it to handle answers of the SCSI-
- subsystem(s). If the F/W SCSI-adapter is forced by the BIOS to use IRQ11
- instead of IRQ14, IRQ11 is used for the IBM SCSI-2 F/W adapter. In a
- further step it is checked, if the adapter gets detected by force from
- the kernel commandline, where the I/O port and the SCSI-subsystem id can
- be specified. The next step checks if there is an integrated SCSI-subsystem
- installed. This register area is fixed through all IBM PS/2 MCA-machines
- and appears as something like a virtual slot 10 of the MCA-bus. On most
- PS/2 machines, the POS registers of slot 10 are set to 0xff or 0x00 if not
- integrated SCSI-controller is available. But on certain PS/2s, like model
- 9595, this slot 10 is used to store other information which at earlier
- stage confused the driver and resulted in the detection of some ghost-SCSI.
- If POS-register 2 and 3 are not 0x00 and not 0xff, but all other POS
- registers are either 0xff or 0x00, there must be an integrated SCSI-
- subsystem present and it will be registered as IBM Integrated SCSI-
- Subsystem. The next step checks, if there is a slot-adapter installed on
- the MCA-bus. To get this, the first two POS-registers, that represent the
- adapter ID are checked. If they fit to one of the ids, stored in the
- adapter list, a SCSI-subsystem is assumed to be found in a slot and will be
- registered. This check is done through all possible MCA-bus slots to allow
- more than one SCSI-adapter to be present in the PS/2-system and this is
- already the first point of problems. Looking into the technical reference
- manual for the IBM PS/2 common interfaces, the POS2 register must have
- different interpretation of its single bits to avoid overlapping I/O
- regions. While one can assume, that the integrated subsystem has a fix
- I/O-address at 0x3540 - 0x3547, further installed IBM SCSI-adapters must
- use a different I/O-address. This is expressed by bit 1 to 3 of POS2
- (multiplied by 8 + 0x3540). Bits 2 and 3 are reserved for the integrated
- subsystem, but not for the adapters! The following list shows, how the
- bits of POS2 and POS3 should be interpreted.
-
- The POS2-register of all PS/2 models' integrated SCSI-subsystems has the
- following interpretation of bits:
- Bit 7 - 4 : Chip Revision ID (Release)
- Bit 3 - 2 : Reserved
- Bit 1 : 8k NVRAM Disabled
- Bit 0 : Chip Enable (EN-Signal)
- The POS3-register is interpreted as follows (for most IBM SCSI-subsys.):
- Bit 7 - 5 : SCSI ID
- Bit 4 - 0 : Reserved = 0
- The slot-adapters have different interpretation of these bits. The IBM SCSI
- adapter (w/Cache) and the IBM SCSI-2 F/W adapter use the following
- interpretation of the POS2 register:
- Bit 7 - 4 : ROM Segment Address Select
- Bit 3 - 1 : Adapter I/O Address Select (*8+0x3540)
- Bit 0 : Adapter Enable (EN-Signal)
- and for the POS3 register:
- Bit 7 - 5 : SCSI ID
- Bit 4 : Fairness Enable (SCSI ID3 f. F/W)
- Bit 3 - 0 : Arbitration Level
- The most modern product of the series is the IBM SCSI-2 F/W adapter, it
- allows dual-bus SCSI and SCSI-wide addressing, which means, PUNs may be
- between 0 and 15. Here, Bit 4 is the high-order bit of the 4-bit wide
- adapter PUN expression. In short words, this means, that IBM PS/2 machines
- can only support 1 single integrated subsystem by default. Additional
- slot-adapters get ports assigned by the automatic configuration tool.
-
- One day I found a patch in ibmmca_detect(), forcing the I/O-address to be
- 0x3540 for integrated SCSI-subsystems, there was a remark placed, that on
- integrated IBM SCSI-subsystems of model 56, the POS2 register was showing 5.
- This means, that really for these models, POS2 has to be interpreted
- sticking to the technical reference guide. In this case, the bit 2 (4) is
- a reserved bit and may not be interpreted. These differences between the
- adapters and the integrated controllers are taken into account by the
- detection routine of the driver on from version >3.0g.
-
- Every time, a SCSI-subsystem is discovered, the ibmmca_register() function
- is called. This function checks first, if the requested area for the I/O-
- address of this SCSI-subsystem is still available and assigns this I/O-
- area to the SCSI-subsystem. There are always 8 sequential I/O-addresses
- taken for each individual SCSI-subsystem found, which are:
-
- Offset Type Permissions
- 0 Command Interface Register 1 Read/Write
- 1 Command Interface Register 2 Read/Write
- 2 Command Interface Register 3 Read/Write
- 3 Command Interface Register 4 Read/Write
- 4 Attention Register Read/Write
- 5 Basic Control Register Read/Write
- 6 Interrupt Status Register Read
- 7 Basic Status Register Read
-
- After the I/O-address range is assigned, the host-adapter is assigned
- to a local structure which keeps all adapter information needed for the
- driver itself and the mid- and higher-level SCSI-drivers. The SCSI pun/lun
- and the adapters' ldn tables are initialized and get probed afterwards by
- the check_devices() function. If no further adapters are found,
- ibmmca_detect() quits.
-
- 2.2 Physical Units, Logical Units, and Logical Devices
- ------------------------------------------------------
- There can be up to 56 devices on the SCSI bus (besides the adapter):
- there are up to 7 "physical units" (each identified by physical unit
- number or pun, also called the scsi id, this is the number you select
- with hardware jumpers), and each physical unit can have up to 8
- "logical units" (each identified by logical unit number, or lun,
- between 0 and 7). The IBM SCSI-2 F/W adapter offers this on up to two
- busses and provides support for 30 logical devices at the same time, where
- in wide-addressing mode you can have 16 puns with 32 luns on each device.
- This section describes the handling of devices on non-F/W adapters.
- Just imagine, that you can have 16 * 32 = 512 devices on a F/W adapter
- which means a lot of possible devices for such a small machine.
-
- Typically the adapter has pun=7, so puns of other physical units
- are between 0 and 6(15). On a wide-adapter a pun higher than 7 is
- possible, but is normally not used. Almost all physical units have only
- one logical unit, with lun=0. A CD-ROM jukebox would be an example of a
- physical unit with more than one logical unit.
-
- The embedded microprocessor of the IBM SCSI-subsystem hides the complex
- two-dimensional (pun,lun) organization from the operating system.
- When the machine is powered-up (or rebooted), the embedded microprocessor
- checks, on its own, all 56 possible (pun,lun) combinations, and the first
- 15 devices found are assigned into a one-dimensional array of so-called
- "logical devices", identified by "logical device numbers" or ldn. The last
- ldn=15 is reserved for the subsystem itself. Wide adapters may have
- to check up to 15 * 8 = 120 pun/lun combinations.
-
- 2.3 SCSI-Device Recognition and Dynamical ldn Assignment
- --------------------------------------------------------
- One consequence of information hiding is that the real (pun,lun)
- numbers are also hidden. The two possibilities to get around this problem
- are to offer fake pun/lun combinations to the operating system or to
- delete the whole mapping of the adapter and to reassign the ldns, using
- the immediate assign command of the SCSI-subsystem for probing through
- all possible pun/lun combinations. An ldn is a "logical device number"
- which is used by IBM SCSI-subsystems to access some valid SCSI-device.
- At the beginning of the development of this driver, the following approach
- was used:
-
- First, the driver checked the ldn's (0 to 6) to find out which ldn's
- have devices assigned. This was done by the functions check_devices() and
- device_exists(). The interrupt handler has a special paragraph of code
- (see local_checking_phase_flag) to assist in the checking. Assume, for
- example, that three logical devices were found assigned at ldn 0, 1, 2.
- These are presented to the upper layer of Linux SCSI driver
- as devices with bogus (pun, lun) equal to (0,0), (1,0), (2,0).
- On the other hand, if the upper layer issues a command to device
- say (4,0), this driver returns DID_NO_CONNECT error.
-
- In a second step of the driver development, the following improvement has
- been applied: The first approach limited the number of devices to 7, far
- fewer than the 15 that it could use, then it just mapped ldn ->
- (ldn/8,ldn%8) for pun,lun. We ended up with a real mishmash of puns
- and luns, but it all seemed to work.
-
- The latest development, which is implemented from the driver version 3.0
- and later, realizes the device recognition in the following way:
- The physical SCSI-devices on the SCSI-bus are probed via immediate_assign-
- and device_inquiry-commands, that is all implemented in a completely new
- made check_devices() subroutine. This delivers an exact map of the physical
- SCSI-world that is now stored in the get_scsi[][]-array. This means,
- that the once hidden pun,lun assignment is now known to this driver.
- It no longer believes in default-settings of the subsystem and maps all
- ldns to existing pun,lun "by foot". This assures full control of the ldn
- mapping and allows dynamical remapping of ldns to different pun,lun, if
- there are more SCSI-devices installed than ldns available (n>15). The
- ldns from 0 to 6 get 'hardwired' by this driver to puns 0 to 7 at lun=0,
- excluding the pun of the subsystem. This assures, that at least simple
- SCSI-installations have optimum access-speed and are not touched by
- dynamical remapping. The ldns 7 to 14 are put to existing devices with
- lun>0 or to non-existing devices, in order to satisfy the subsystem, if
- there are less than 15 SCSI-devices connected. In the case of more than 15
- devices, the dynamical mapping goes active. If the get_scsi[][] reports a
- device to be existent, but it has no ldn assigned, it gets an ldn out of 7
- to 14. The numbers are assigned in cyclic order, therefore it takes 8
- dynamical reassignments on the SCSI-devices until a certain device
- loses its ldn again. This assures that dynamical remapping is avoided
- during intense I/O between up to 15 SCSI-devices (means pun,lun
- combinations). A further advantage of this method is that people who
- build their kernel without probing on all luns will get what they expect,
- because the driver just won't assign everything with lun>0 when
- multiple lun probing is inactive.
-
- 2.4 SCSI-Device Order
- ---------------------
- Because of the now correct recognition of physical pun,lun, and
- their report to mid-level- and higher-level-drivers, the new reported puns
- can be different from the old, faked puns. Therefore, Linux will eventually
- change /dev/sdXXX assignments and prompt you for corrupted superblock
- repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
- You have to reboot (CTRL-D) with an old kernel and set the /etc/fstab-file
- entries right. After that, the system should come up as errorfree as before.
- If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
- in a Linux session booted on old kernel and run lilo before reboot. Check
- lilo.conf anyway to get boot on other partitions with foreign OSes right
- again. But there exists a feature of this driver that allows you to change
- the assignment order of the SCSI-devices by flipping the PUN-assignment.
- See the next paragraph for a description.
-
- The problem for this is, that Linux does not assign the SCSI-devices in the
- way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to
- the device with at minimum id 0. But the first drive should be at id 6,
- because for historical reasons, drive at id 6 has, by hardware, the highest
- priority and a drive at id 0 the lowest. IBM was one of the rare producers,
- where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most
- other producers' BIOS does not (I think even Adaptec-BIOS). The
- IBMMCA_SCSI_ORDER_STANDARD flag, which you set while configuring the
- kernel enables to choose the preferred way of SCSI-device-assignment.
- Defining this flag would result in Linux determining the devices in the
- same order as DOS and OS/2 does on your MCA-machine. This is also standard
- on most industrial computers and OSes, like e.g. OS-9. Leaving this flag
- undefined will get your devices ordered in the default way of Linux. See
- also the remarks of Chris Beauregard from Dec 15, 1997 and the followups
- in section 3.
-
- 2.5 Regular SCSI-Command-Processing
- -----------------------------------
- Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
- and interrupt_handler().
-
- The upper layer issues a scsi command by calling function
- ibmmca_queuecommand(). This function fills a "subsystem control block"
- (scb) and calls a local function issue_cmd(), which writes a scb
- command into subsystem I/O ports. Once the scb command is carried out,
- the interrupt_handler() is invoked. If a device is determined to be
- existent and it has not assigned any ldn, it gets one dynamically.
- For this, the whole stuff is done in ibmmca_queuecommand().
-
- 2.6 Abort & Reset Commands
- --------------------------
- These are implemented with busy waiting for interrupt to arrive.
- ibmmca_reset() and ibmmca_abort() do not work sufficiently well
- up to now and need still a lot of development work. This seems
- to be a problem with other low-level SCSI drivers too, however
- this should be no excuse.
-
- 2.7 Disk Geometry
- -----------------
- The ibmmca_biosparams() function should return the same disk geometry
- as the bios. This is needed for fdisk, etc. The returned geometry is
- certainly correct for disks smaller than 1 gigabyte. In the meantime,
- it has been proved, that this works fine even with disks larger than
- 1 gigabyte.
-
- 2.8 Kernel Boot Option
- ----------------------
- The function ibmmca_scsi_setup() is called if option ibmmcascsi=n
- is passed to the kernel. See file linux/init/main.c for details.
-
- 2.9 Driver Module Support
- -------------------------
- Is implemented and tested by K. Kudielka. This could probably not work
- on kernels <2.1.0.
-
- 2.10 Multiple Hostadapter Support
- ---------------------------------
- This driver supports up to eight interfaces of type IBM-SCSI-Subsystem.
- Integrated-, and MCA-adapters are automatically recognized. Unrecognizable
- IBM-SCSI-Subsystem interfaces can be specified as kernel-parameters.
-
- 2.11 /proc/scsi-Filesystem Information
- --------------------------------------
- Information about the driver condition is given in
- /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info() provides this information.
-
- This table is quite informative for interested users. It shows the load
- of commands on the subsystem and whether you are running the bypassed
- (software) or integrated (hardware) SCSI-command set (see below). The
- amount of accesses is shown. Read, write, modeselect is shown separately
- in order to help debugging problems with CD-ROMs or tapedrives.
-
- The following table shows the list of 15 logical device numbers, that are
- used by the SCSI-subsystem. The load on each ldn is shown in the table,
- again, read and write commands are split. The last column shows the amount
- of reassignments, that have been applied to the ldns, if you have more than
- 15 pun/lun combinations available on the SCSI-bus.
-
- The last two tables show the pun/lun map and the positions of the ldns
- on this pun/lun map. This may change during operation, when a ldn is
- reassigned to another pun/lun combination. If the necessity for dynamical
- assignments is set to 'no', the ldn structure keeps static.
-
- 2.12 /proc/mca-Filesystem Information
- -------------------------------------
- The slot-file contains all default entries and in addition chip and I/O-
- address information of the SCSI-subsystem. This information is provided
- by ibmmca_getinfo().
-
- 2.13 Supported IBM SCSI-Subsystems
- ----------------------------------
- The following IBM SCSI-subsystems are supported by this driver:
-
- - IBM Fast/Wide SCSI-2 Adapter
- - IBM 7568 Industrial Computer SCSI Adapter w/Cache
- - IBM Expansion Unit SCSI Controller
- - IBM SCSI Adapter w/Cache
- - IBM SCSI Adapter
- - IBM Integrated SCSI Controller
- - All clones, 100% compatible with the chipset and subsystem command
- system of IBM SCSI-adapters (forced detection)
-
- 2.14 Linux Kernel Versions
- --------------------------
- The IBM SCSI-subsystem low level driver is prepared to be used with
- all versions of Linux between 2.0.x and 2.4.x. The compatibility checks
- are fully implemented up from version 3.1e of the driver. This means, that
- you just need the latest ibmmca.h and ibmmca.c file and copy it in the
- linux/drivers/scsi directory. The code is automatically adapted during
- kernel compilation. This is different from kernel 2.4.0! Here version
- 4.0 or later of the driver must be used for kernel 2.4.0 or later. Version
- 4.0 or later does not work together with older kernels! Driver versions
- older than 4.0 do not work together with kernel 2.4.0 or later. They work
- on all older kernels.
-
- 3 Code History
- --------------
- Jan 15 1996: First public release.
- - Martin Kolinek
-
- Jan 23 1996: Scrapped code which reassigned scsi devices to logical
- device numbers. Instead, the existing assignment (created
- when the machine is powered-up or rebooted) is used.
- A side effect is that the upper layer of Linux SCSI
- device driver gets bogus scsi ids (this is benign),
- and also the hard disks are ordered under Linux the
- same way as they are under dos (i.e., C: disk is sda,
- D: disk is sdb, etc.).
- - Martin Kolinek
-
- I think that the CD-ROM is now detected only if a CD is
- inside CD_ROM while Linux boots. This can be fixed later,
- once the driver works on all types of PS/2's.
- - Martin Kolinek
-
- Feb 7 1996: Modified biosparam function. Fixed the CD-ROM detection.
- For now, devices other than harddisk and CD_ROM are
- ignored. Temporarily modified abort() function
- to behave like reset().
- - Martin Kolinek
-
- Mar 31 1996: The integrated scsi subsystem is correctly found
- in PS/2 models 56,57, but not in model 76. Therefore
- the ibmmca_scsi_setup() function has been added today.
- This function allows the user to force detection of
- scsi subsystem. The kernel option has format
- ibmmcascsi=n
- where n is the scsi_id (pun) of the subsystem. Most likely, n is 7.
- - Martin Kolinek
-
- Aug 21 1996: Modified the code which maps ldns to (pun,0). It was
- insufficient for those of us with CD-ROM changers.
- - Chris Beauregard
-
- Dec 14 1996: More improvements to the ldn mapping. See check_devices
- for details. Did more fiddling with the integrated SCSI detection,
- but I think it's ultimately hopeless without actually testing the
- model of the machine. The 56, 57, 76 and 95 (ultimedia) all have
- different integrated SCSI register configurations. However, the 56
- and 57 are the only ones that have problems with forced detection.
- - Chris Beauregard
-
- Mar 8-16 1997: Modified driver to run as a module and to support
- multiple adapters. A structure, called ibmmca_hostdata, is now
- present, containing all the variables, that were once only
- available for one single adapter. The find_subsystem-routine has vanished.
- The hardware recognition is now done in ibmmca_detect directly.
- This routine checks for presence of MCA-bus, checks the interrupt
- level and continues with checking the installed hardware.
- Certain PS/2-models do not recognize a SCSI-subsystem automatically.
- Hence, the setup defined by command-line-parameters is checked first.
- Thereafter, the routine probes for an integrated SCSI-subsystem.
- Finally, adapters are checked. This method has the advantage to cover all
- possible combinations of multiple SCSI-subsystems on one MCA-board. Up to
- eight SCSI-subsystems can be recognized and announced to the upper-level
- drivers with this improvement. A set of defines made changes to other
- routines as small as possible.
- - Klaus Kudielka
-
- May 30 1997: (v1.5b)
- 1) SCSI-command capability enlarged by the recognition of MODE_SELECT.
- This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which
- allows data to be written from the system to the device. It is a
- necessary step to be allowed to set blocksize of SCSI-tape-drives and
- the tape-speed, without confusing the SCSI-Subsystem.
- 2) The recognition of a tape is included in the check_devices routine.
- This is done by checking for TYPE_TAPE, that is already defined in
- the kernel-scsi-environment. The markup of a tape is done in the
- global ldn_is_tape[] array. If the entry on index ldn
- is 1, there is a tapedrive connected.
- 3) The ldn_is_tape[] array is necessary to distinguish between tape- and
- other devices. Fixed blocklength devices should not cause a problem
- with the SCB-command for read and write in the ibmmca_queuecommand
- subroutine. Therefore, I only derivate the READ_XX, WRITE_XX for
- the tape-devices, as recommended by IBM in this Technical Reference,
- mentioned below. (IBM recommends to avoid using the read/write of the
- subsystem, but the fact was, that read/write causes a command error from
- the subsystem and this causes kernel-panic.)
- 4) In addition, I propose to use the ldn instead of a fix char for the
- display of PS2_DISK_LED_ON(). On 95, one can distinguish between the
- devices that are accessed. It shows activity and easyfies debugging.
- The tape-support has been tested with a SONY SDT-5200 and a HP DDS-2
- (I do not know yet the type). Optimization and CD-ROM audio-support,
- I am working on ...
- - Michael Lang
-
- June 19 1997: (v1.6b)
- 1) Submitting the extra-array ldn_is_tape[] -> to the local ld[]
- device-array.
- 2) CD-ROM Audio-Play seems to work now.
- 3) When using DDS-2 (120M) DAT-Tapes, mtst shows still density-code
- 0x13 for ordinary DDS (61000 BPM) instead 0x24 for DDS-2. This appears
- also on Adaptec 2940 adaptor in a PCI-System. Therefore, I assume that
- the problem is independent of the low-level-driver/bus-architecture.
- 4) Hexadecimal ldn on PS/2-95 LED-display.
- 5) Fixing of the PS/2-LED on/off that it works right with tapedrives and
- does not confuse the disk_rw_in_progress counter.
- - Michael Lang
-
- June 21 1997: (v1.7b)
- 1) Adding of a proc_info routine to inform in /proc/scsi/ibmmca/<host> the
- outer-world about operational load statistics on the different ldns,
- seen by the driver. Everybody that has more than one IBM-SCSI should
- test this, because I only have one and cannot see what happens with more
- than one IBM-SCSI hosts.
- 2) Definition of a driver version-number to have a better recognition of
- the source when there are existing too much releases that may confuse
- the user, when reading about release-specific problems. Up to know,
- I calculated the version-number to be 1.7. Because we are in BETA-test
- yet, it is today 1.7b.
- 3) Sorry for the heavy bug I programmed on June 19 1997! After that, the
- CD-ROM did not work any more! The C7-command was a fake impression
- I got while programming. Now, the READ and WRITE commands for CD-ROM are
- no longer running over the subsystem, but just over
- IM_OTHER_SCSI_CMD_CMD. On my observations (PS/2-95), now CD-ROM mounts
- much faster(!) and hopefully all fancy multimedia-functions, like direct
- digital recording from audio-CDs also work. (I tried it with cdda2wav
- from the cdwtools-package and it filled up the harddisk immediately :-).)
- To easify boolean logics, a further local device-type in ld[], called
- is_cdrom has been included.
- 4) If one uses a SCSI-device of unsupported type/commands, one
- immediately runs into a kernel-panic caused by Command Error. To better
- understand which SCSI-command caused the problem, I extended this
- specific panic-message slightly.
- - Michael Lang
-
- June 25 1997: (v1.8b)
- 1) Some cosmetic changes for the handling of SCSI-device-types.
- Now, also CD-Burners / WORMs and SCSI-scanners should work. For
- MO-drives I have no experience, therefore not yet supported.
- In logical_devices I changed from different type-variables to one
- called 'device_type' where the values, corresponding to scsi.h,
- of a SCSI-device are stored.
- 2) There existed a small bug, that maps a device, coming after a SCSI-tape
- wrong. Therefore, e.g. a CD-ROM changer would have been mapped wrong
- -> problem removed.
- 3) Extension of the logical_device structure. Now it contains also device,
- vendor and revision-level of a SCSI-device for internal usage.
- - Michael Lang
-
- June 26-29 1997: (v2.0b)
- 1) The release number 2.0b is necessary because of the completely new done
- recognition and handling of SCSI-devices with the adapter. As I got
- from Chris the hint, that the subsystem can reassign ldns dynamically,
- I remembered this immediate_assign-command, I found once in the handbook.
- Now, the driver first kills all ldn assignments that are set by default
- on the SCSI-subsystem. After that, it probes on all puns and luns for
- devices by going through all combinations with immediate_assign and
- probing for devices, using device_inquiry. The found physical(!) pun,lun
- structure is stored in get_scsi[][] as device types. This is followed
- by the assignment of all ldns to existing SCSI-devices. If more ldns
- than devices are available, they are assigned to non existing pun,lun
- combinations to satisfy the adapter. With this, the dynamical mapping
- was possible to implement. (For further info see the text in the
- source code and in the description below. Read the description
- below BEFORE installing this driver on your system!)
- 2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
- 3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
- (pun) of the accessed SCSI-device. This is now senseful, because the
- pun known within the driver is exactly the pun of the physical device
- and no longer a fake one.
- 4) The /proc/scsi/ibmmca/<host_no> consists now of the first part, where
- hit-statistics of ldns is shown and a second part, where the maps of
- physical and logical SCSI-devices are displayed. This could be very
- interesting, when one is using more than 15 SCSI-devices in order to
- follow the dynamical remapping of ldns.
- - Michael Lang
-
- June 26-29 1997: (v2.0b-1)
- 1) I forgot to switch the local_checking_phase_flag to 1 and back to 0
- in the dynamical remapping part in ibmmca_queuecommand for the
- device_exist routine. Sorry.
- - Michael Lang
-
- July 1-13 1997: (v3.0b,c)
- 1) Merging of the driver-developments of Klaus Kudielka and Michael Lang
- in order to get a optimum and unified driver-release for the
- IBM-SCSI-Subsystem-Adapter(s).
- For people, using the Kernel-release >=2.1.0, module-support should
- be no problem. For users, running under <2.1.0, module-support may not
- work, because the methods have changed between 2.0.x and 2.1.x.
- 2) Added some more effective statistics for /proc-output.
- 3) Change typecasting at necessary points from (unsigned long) to
- virt_to_bus().
- 4) Included #if... at special points to have specific adaption of the
- driver to kernel 2.0.x and 2.1.x. It should therefore also run with
- later releases.
- 5) Magneto-Optical drives and medium-changers are also recognized, now.
- Therefore, we have a completely gapfree recognition of all SCSI-
- device-types, that are known by Linux up to kernel 2.1.31.
- 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
- the configuration, each connected SCSI-device will get a reset command
- during boottime. This can be necessary for some special SCSI-devices.
- This flag should be included in Config.in.
- (See also the new Config.in file.)
- Probable next improvement: bad disk handler.
- - Michael Lang
-
- Sept 14 1997: (v3.0c)
- 1) Some debugging and speed optimization applied.
- - Michael Lang
-
- Dec 15, 1997
- - chrisb@truespectra.com
- - made the front panel display thingy optional, specified from the
- command-line via ibmmcascsi=display. Along the lines of the /LED
- option for the OS/2 driver.
- - fixed small bug in the LED display that would hang some machines.
- - reversed ordering of the drives (using the
- IBMMCA_SCSI_ORDER_STANDARD define). This is necessary for two main
- reasons:
- - users who've already installed Linux won't be screwed. Keep
- in mind that not everyone is a kernel hacker.
- - be consistent with the BIOS ordering of the drives. In the
- BIOS, id 6 is C:, id 0 might be D:. With this scheme, they'd be
- backwards. This confuses the crap out of those heathens who've
- got a impure Linux installation (which, <wince>, I'm one of).
- This whole problem arises because IBM is actually non-standard with
- the id to BIOS mappings. You'll find, in fdomain.c, a similar
- comment about a few FD BIOS revisions. The Linux (and apparently
- industry) standard is that C: maps to scsi id (0,0). Let's stick
- with that standard.
- - Since this is technically a branch of my own, I changed the
- version number to 3.0e-cpb.
-
- Jan 17, 1998: (v3.0f)
- 1) Addition of some statistical info for /proc in proc_info.
- 2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
- 1997. In fact, IBM is right, concerning the assignment of SCSI-devices
- to driveletters. It is conform to the ANSI-definition of the SCSI-
- standard to assign drive C: to SCSI-id 6, because it is the highest
- hardware priority after the hostadapter (that has still today by
- default everywhere id 7). Also realtime-operating systems that I use,
- like LynxOS and OS9, which are quite industrial systems use top-down
- numbering of the harddisks, that is also starting at id 6. Now, one
- sits a bit between two chairs. On one hand side, using the define
- IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
- the IBM- and ANSI-SCSI-standard and keeps this driver downward
- compatible to older releases, on the other hand side, people is quite
- habituated in believing that C: is assigned to (0,0) and much other
- SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD
- define out of the driver and put it into Config.in as subitem of
- 'IBM SCSI support'. A help, added to Documentation/Configure.help
- explains the differences between saying 'y' or 'n' to the user, when
- IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to
- choose the way of assignment, depending on his own situation and gusto.
- 3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
- now called IBMMCA_SCSI_DEV_RESET.
- 4) Optimization of proc_info and its subroutines.
- 5) Added more in-source-comments and extended the driver description by
- some explanation about the SCSI-device-assignment problem.
- - Michael Lang
-
- Jan 18, 1998: (v3.0g)
- 1) Correcting names to be absolutely conform to the later 2.1.x releases.
- This is necessary for
- IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
- IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- - Michael Lang
-
- Jan 18, 1999: (v3.1 MCA-team internal)
- 1) The multiple hosts structure is accessed from every subroutine, so there
- is no longer the address of the device structure passed from function
- to function, but only the hostindex. A call by value, nothing more. This
- should really be understood by the compiler and the subsystem should get
- the right values and addresses.
- 2) The SCSI-subsystem detection was not complete and quite hugely buggy up
- to now, compared to the technical manual. The interpretation of the pos2
- register is not as assumed by people before, therefore, I dropped a note
- in the ibmmca_detect function to show the registers' interpretation.
- The pos-registers of integrated SCSI-subsystems do not contain any
- information concerning the IO-port offset, really. Instead, they contain
- some info about the adapter, the chip, the NVRAM .... The I/O-port is
- fixed to 0x3540 - 0x3547. There can be more than one adapters in the
- slots and they get an offset for the I/O area in order to get their own
- I/O-address area. See chapter 2 for detailed description. At least, the
- detection should now work right, even on models other than 95. The 95ers
- came happily around the bug, as their pos2 register contains always 0
- in the critical area. Reserved bits are not allowed to be interpreted,
- therefore, IBM is allowed to set those bits as they like and they may
- really vary between different PS/2 models. So, now, no interpretation
- of reserved bits - hopefully no trouble here anymore.
- 3) The command error, which you may get on models 55, 56, 57, 70, 77 and
- P70 may have been caused by the fact, that adapters of older design do
- not like sending commands to non-existing SCSI-devices and will react
- with a command error as a sign of protest. While this error is not
- present on IBM SCSI Adapter w/cache, it appears on IBM Integrated SCSI
- Adapters. Therefore, I implemented a workaround to forgive those
- adapters their protests, but it is marked up in the statistics, so
- after a successful boot, you can see in /proc/scsi/ibmmca/<host_number>
- how often the command errors have been forgiven to the SCSI-subsystem.
- If the number is bigger than 0, you have a SCSI subsystem of older
- design, what should no longer matter.
- 4) ibmmca_getinfo() has been adapted very carefully, so it shows in the
- slotn file really, what is senseful to be presented.
- 5) ibmmca_register() has been extended in its parameter list in order to
- pass the right name of the SCSI-adapter to Linux.
- - Michael Lang
-
- Feb 6, 1999: (v3.1)
- 1) Finally, after some 3.1Beta-releases, the 3.1 release. Sorry, for
- the delayed release, but it was not finished with the release of
- Kernel 2.2.0.
- - Michael Lang
-
- Feb 10, 1999 (v3.1)
- 1) Added a new commandline parameter called 'bypass' in order to bypass
- every integrated subsystem SCSI-command consequently in case of
- troubles.
- 2) Concatenated read_capacity requests to the harddisks. It gave a lot
- of troubles with some controllers and after I wanted to apply some
- extensions, it jumped out in the same situation, on my w/cache, as like
- on D. Weinehalls' Model 56, having integrated SCSI. This gave me the
- decisive hint to move the code-part out and declare it global. Now
- it seems to work far better and more stable. Let us see what
- the world thinks of it...
- 3) By the way, only Sony DAT-drives seem to show density code 0x13. A
- test with a HP drive gave right results, so the problem is vendor-
- specific and not a problem of the OS or the driver.
- - Michael Lang
-
- Feb 18, 1999 (v3.1d)
- 1) The abort command and the reset function have been checked for
- inconsistencies. From the logical point of thinking, they work
- at their optimum, now, but as the subsystem does not answer with an
- interrupt, abort never finishes, sigh...
- 2) Everything, that is accessed by a busmaster request from the adapter
- is now declared as global variable, even the return-buffer in the
- local checking phase. This assures, that no accesses to undefined memory
- areas are performed.
- 3) In ibmmca.h, the line unchecked_isa_dma is added with 1 in order to
- avoid memory-pointers for the areas higher than 16MByte in order to
- be sure, it also works on 16-Bit Microchannel bus systems.
- 4) A lot of small things have been found, but nothing that endangered the
- driver operations. Just it should be more stable, now.
- - Michael Lang
-
- Feb 20, 1999 (v3.1e)
- 1) I took the warning from the Linux Kernel Hackers Guide serious and
- checked the cmd->result return value to the done-function very carefully.
- It is obvious, that the IBM SCSI only delivers the tsb.dev_status, if
- some error appeared, else it is undefined. Now, this is fixed. Before
- any SCB command gets queued, the tsb.dev_status is set to 0, so the
- cmd->result won't screw up Linux higher level drivers.
- 2) The reset-function has slightly improved. This is still planned for
- abort. During the abort and the reset function, no interrupts are
- allowed. This is however quite hard to cope with, so the INT-status
- register is read. When the interrupt gets queued, one can find its
- status immediately on that register and is enabled to continue in the
- reset function. I had no chance to test this really, only in a bogus
- situation, I got this function running, but the situation was too much
- worse for Linux :-(, so tests will continue.
- 3) Buffers got now consistent. No open address mapping, as before and
- therefore no further troubles with the unassigned memory segmentation
- faults that scrambled probes on 95XX series and even on 85XX series,
- when the kernel is done in a not so perfectly fitting way.
- 4) Spontaneous interrupts from the subsystem, appearing without any
- command previously queued are answered with a DID_BAD_INTR result.
- 5) Taken into account ZP Gus' proposals to reverse the SCSI-device
- scan order. As it does not work on Kernel 2.1.x or 2.2.x, as proposed
- by him, I implemented it in a slightly derived way, which offers in
- addition more flexibility.
- - Michael Lang
-
- Apr 23, 2000 (v3.2pre1)
- 1) During a very long time, I collected a huge amount of bug reports from
- various people, trying really quite different things on their SCSI-
- PS/2s. Today, all these bug reports are taken into account and should be
- mostly solved. The major topics were:
- - Driver crashes during boottime by no obvious reason.
- - Driver panics while the midlevel-SCSI-driver is trying to inquire
- the SCSI-device properties, even though hardware is in perfect state.
- - Displayed info for the various slot-cards is interpreted wrong.
- The main reasons for the crashes were two:
- 1) The commands to check for device information like INQUIRY,
- TEST_UNIT_READY, REQUEST_SENSE and MODE_SENSE cause the devices
- to deliver information of up to 255 bytes. Midlevel drivers offer
- 1024 bytes of space for the answer, but the IBM-SCSI-adapters do
- not accept this, as they stick quite near to ANSI-SCSI and report
- a COMMAND_ERROR message which causes the driver to panic. The main
- problem was located around the INQUIRY command. Now, for all the
- mentioned commands, the buffersize sent to the adapter is at
- maximum 255 which seems to be a quite reasonable solution.
- TEST_UNIT_READY gets a buffersize of 0 to make sure that no
- data is transferred in order to avoid any possible command failure.
- 2) On unsuccessful TEST_UNIT_READY, the mid-level driver has to send
- a REQUEST_SENSE in order to see where the problem is located. This
- REQUEST_SENSE may have various length in its answer-buffer. IBM
- SCSI-subsystems report a command failure if the returned buffersize
- is different from the sent buffersize, but this can be suppressed by
- a special bit, which is now done and problems seem to be solved.
- 2) Code adaption to all kernel-releases. Now, the 3.2 code compiles on
- 2.0.x, 2.1.x, 2.2.x and 2.3.x kernel releases without any code-changes.
- 3) Commandline-parameters are recognized again, even under Kernel 2.3.x or
- higher.
- - Michael Lang
-
- April 27, 2000 (v3.2pre2)
- 1) Bypassed commands get read by the adapter by one cycle instead of two.
- This increases SCSI-performance.
- 2) Synchronous datatransfer is provided for sure to be 5 MHz on older
- SCSI and 10 MHz on internal F/W SCSI-adapter.
- 3) New commandline parameters allow to force the adapter to slow down while
- in synchronous transfer. Could be helpful for very old devices.
- - Michael Lang
-
- June 2, 2000 (v3.2pre5)
- 1) Added Jim Shorney's contribution to make the activity indicator
- flashing in addition to the LED-alphanumeric display-panel on
- models 95A. To be enabled to choose this feature freely, a new
- commandline parameter is added, called 'activity'.
- 2) Added the READ_CONTROL bit for test_unit_ready SCSI-command.
- 3) Added some suppress_exception bits to read_device_capacity and
- all device_inquiry occurrences in the driver code.
- 4) Complaints about the various KERNEL_VERSION implementations are
- taken into account. Every local_LinuxKernelVersion occurrence is
- now replaced by KERNEL_VERSION, defined in linux/version.h.
- Corresponding changes were applied to ibmmca.h, too. This was a
- contribution to all kernel-parts by Philipp Hahn.
- - Michael Lang
-
- July 17, 2000 (v3.2pre8)
- A long period of collecting bug reports from all corners of the world
- now lead to the following corrections to the code:
- 1) SCSI-2 F/W support crashed with a COMMAND ERROR. The reason for this
- was that it is possible to disable Fast-SCSI for the external bus.
- The feature-control command, where this crash appeared regularly, tried
- to set the maximum speed of 10MHz synchronous transfer speed and that
- reports a COMMAND ERROR if external bus Fast-SCSI is disabled. Now,
- the feature-command probes down from maximum speed until the adapter
- stops to complain, which is at the same time the maximum possible
- speed selected in the reference program. So, F/W external can run at
- 5 MHz (slow-) or 10 MHz (fast-SCSI). During feature probing, the
- COMMAND ERROR message is used to detect if the adapter does not complain.
- 2) Up to now, only combined busmode is supported, if you use external
- SCSI-devices, attached to the F/W-controller. If dual bus is selected,
- only the internal SCSI-devices get accessed by Linux. For most
- applications, this should do fine.
- 3) Wide-SCSI-addressing (16-Bit) is now possible for the internal F/W
- bus on the F/W adapter. If F/W adapter is detected, the driver
- automatically uses the extended PUN/LUN <-> LDN mapping tables, which
- are now new from 3.2pre8. This allows PUNs between 0 and 15 and should
- provide more fun with the F/W adapter.
- 4) Several machines use the SCSI: POS registers for internal/undocumented
- storage of system relevant info. This confused the driver, mainly on
- models 9595, as it expected no onboard SCSI only, if all POS in
- the integrated SCSI-area are set to 0x00 or 0xff. Now, the mechanism
- to check for integrated SCSI is much more restrictive and these problems
- should be history.
- - Michael Lang
-
- July 18, 2000 (v3.2pre9)
- This develop rather quickly at the moment. Two major things were still
- missing in 3.2pre8:
- 1) The adapter PUN for F/W adapters has 4-bits, while all other adapters
- have 3-bits. This is now taken into account for F/W.
- 2) When you select CONFIG_IBMMCA_SCSI_ORDER_STANDARD, you should
- normally get the inverse probing order of your devices on the SCSI-bus.
- The ANSI device order gets scrambled in version 3.2pre8!! Now, a new
- and tested algorithm inverts the device-order on the SCSI-bus and
- automatically avoids accidental access to whatever SCSI PUN the adapter
- is set and works with SCSI- and Wide-SCSI-addressing.
- - Michael Lang
-
- July 23, 2000 (v3.2pre10 unpublished)
- 1) LED panel display supports wide-addressing in ibmmca=display mode.
- 2) Adapter-information and autoadaption to address-space is done.
- 3) Auto-probing for maximum synchronous SCSI transfer rate is working.
- 4) Optimization to some embedded function calls is applied.
- 5) Added some comment for the user to wait for SCSI-devices being probed.
- 6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but...
- - Michael Lang
-
- July 26, 2000 (v3.2pre11)
- 1) I passed a horrible weekend getting mad with NMIs on kernel 2.2.14 and
- a model 9595. Asking around in the community, nobody except of me has
- seen such errors. Weird, but I am trying to recompile everything on
- the model 9595. Maybe, as I use a specially modified gcc, that could
- cause problems. But, it was not the reason. The true background was,
- that the kernel was compiled for i386 and the 9595 has a 486DX-2.
- Normally, no troubles should appear, but for this special machine,
- only the right processor support is working fine!
- 2) Previous problems with synchronous speed, slowing down from one adapter
- to the next during probing are corrected. Now, local variables store
- the synchronous bitmask for every single adapter found on the MCA bus.
- 3) LED alphanumeric panel support for XX95 systems is now showing some
- alive rotator during boottime. This makes sense, when no monitor is
- connected to the system. You can get rid of all display activity, if
- you do not use any parameter or just ibmmcascsi=activity, for the
- harddrive activity LED, existent on all PS/2, except models 8595-XXX.
- If no monitor is available, please use ibmmcascsi=display, which works
- fine together with the linuxinfo utility for the LED-panel.
- - Michael Lang
-
- July 29, 2000 (v3.2)
- 1) Submission of this driver for kernel 2.4test-XX and 2.2.17.
- - Michael Lang
-
- December 28, 2000 (v3.2d / v4.0)
- 1) The interrupt handler had some wrong statement to wait for. This
- was done due to experimental reasons during 3.2 development but it
- has shown that this is not stable enough. Going back to wait for the
- adapter to be not busy is best.
- 2) Inquiry requests can be shorter than 255 bytes of return buffer. Due
- to a bug in the ibmmca_queuecommand routine, this buffer was forced
- to 255 at minimum. If the memory address, this return buffer is pointing
- to does not offer more space, invalid memory accesses destabilized the
- kernel.
- 3) version 4.0 is only valid for kernel 2.4.0 or later. This is necessary
- to remove old kernel version dependent waste from the driver. 3.2d is
- only distributed with older kernels but keeps compatibility with older
- kernel versions. 4.0 and higher versions cannot be used with older
- kernels anymore!! You must have at least kernel 2.4.0!!
- 4) The commandline argument 'bypass' and all its functionality got removed
- in version 4.0. This was never really necessary, as all troubles were
- based on non-command related reasons up to now, so bypassing commands
- did not help to avoid any bugs. It is kept in 3.2X for debugging reasons.
- 5) Dynamic reassignment of ldns was again verified and analyzed to be
- completely inoperational. This is corrected and should work now.
- 6) All commands that get sent to the SCSI adapter were verified and
- completed in such a way, that they are now completely conform to the
- demands in the technical description of IBM. Main candidates were the
- DEVICE_INQUIRY, REQUEST_SENSE and DEVICE_CAPACITY commands. They must
- be transferred by bypassing the internal command buffer of the adapter
- or else the response can be a random result. GET_POS_INFO would be more
- safe in usage, if one could use the SUPRESS_EXCEPTION_SHORT, but this
- is not allowed by the technical references of IBM. (Sorry, folks, the
- model 80 problem is still a task to be solved in a different way.)
- 7) v3.2d is still hold back for some days for testing, while 4.0 is
- released.
- - Michael Lang
-
- January 3, 2001 (v4.0a)
- 1) A lot of complains after the 2.4.0-prerelease kernel came in about
- the impossibility to compile the driver as a module. This problem is
- solved. In combination with that problem, some unprecise declaration
- of the function option_setup() gave some warnings during compilation.
- This is solved, too by a forward declaration in ibmmca.c.
- 2) #ifdef argument concerning CONFIG_SCSI_IBMMCA is no longer needed and
- was entirely removed.
- 3) Some switch statements got optimized in code, as some minor variables
- in internal SCSI-command handlers.
- - Michael Lang
-
- 4 To do
- -------
- - IBM SCSI-2 F/W external SCSI bus support in separate mode!
- - It seems that the handling of bad disks is really bad -
- non-existent, in fact. However, a low-level driver cannot help
- much, if such things happen.
-
- 5 Users' Manual
- ---------------
- 5.1 Commandline Parameters
- --------------------------
- There exist several features for the IBM SCSI-subsystem driver.
- The commandline parameter format is:
-
- ibmmcascsi=<command1>,<command2>,<command3>,...
-
- where commandN can be one of the following:
-
- display Owners of a model 95 or other PS/2 systems with an
- alphanumeric LED display may set this to have their
- display showing the following output of the 8 digits:
-
- ------DA
-
- where '-' stays dark, 'D' shows the SCSI-device id
- and 'A' shows the SCSI hostindex, being currently
- accessed. During boottime, this will give the message
-
- SCSIini*
-
- on the LED-panel, where the * represents a rotator,
- showing the activity during the probing phase of the
- driver which can take up to two minutes per SCSI-adapter.
- adisplay This works like display, but gives more optical overview
- of the activities on the SCSI-bus. The display will have
- the following output:
-
- 6543210A
-
- where the numbers 0 to 6 light up at the shown position,
- when the SCSI-device is accessed. 'A' shows again the SCSI
- hostindex. If display nor adisplay is set, the internal
- PS/2 harddisk LED is used for media-activities. So, if
- you really do not have a system with a LED-display, you
- should not set display or adisplay. Keep in mind, that
- display and adisplay can only be used alternatively. It
- is not recommended to use this option, if you have some
- wide-addressed devices e.g. at the SCSI-2 F/W adapter in
- your system. In addition, the usage of the display for
- other tasks in parallel, like the linuxinfo-utility makes
- no sense with this option.
- activity This enables the PS/2 harddisk LED activity indicator.
- Most PS/2 have no alphanumeric LED display, but some
- indicator. So you should use this parameter to activate it.
- If you own model 9595 (Server95), you can have both, the
- LED panel and the activity indicator in parallel. However,
- some PS/2s, like the 8595 do not have any harddisk LED
- activity indicator, which means, that you must use the
- alphanumeric LED display if you want to monitor SCSI-
- activity.
- bypass This is obsolete from driver version 4.0, as the adapters
- got that far understood, that the selection between
- integrated and bypassed commands should now work completely
- correct! For historical reasons, the old description is
- kept here:
- This commandline parameter forces the driver never to use
- SCSI-subsystems' integrated SCSI-command set. Except of
- the immediate assign, which is of vital importance for
- every IBM SCSI-subsystem to set its ldns right. Instead,
- the ordinary ANSI-SCSI-commands are used and passed by the
- controller to the SCSI-devices, therefore 'bypass'. The
- effort, done by the subsystem is quite bogus and at a
- minimum and therefore it should work everywhere. This
- could maybe solve troubles with old or integrated SCSI-
- controllers and nasty harddisks. Keep in mind, that using
- this flag will slow-down SCSI-accesses slightly, as the
- software generated commands are always slower than the
- hardware. Non-harddisk devices always get read/write-
- commands in bypass mode. On the most recent releases of
- the Linux IBM-SCSI-driver, the bypass command should be
- no longer a necessary thing, if you are sure about your
- SCSI-hardware!
- normal This is the parameter, introduced on the 2.0.x development
- rail by ZP Gu. This parameter defines the SCSI-device
- scan order in the new industry standard. This means, that
- the first SCSI-device is the one with the lowest pun.
- E.g. harddisk at pun=0 is scanned before harddisk at
- pun=6, which means, that harddisk at pun=0 gets sda
- and the one at pun=6 gets sdb.
- ansi The ANSI-standard for the right scan order, as done by
- IBM, Microware and Microsoft, scans SCSI-devices starting
- at the highest pun, which means, that e.g. harddisk at
- pun=6 gets sda and a harddisk at pun=0 gets sdb. If you
- like to have the same SCSI-device order, as in DOS, OS-9
- or OS/2, just use this parameter.
- fast SCSI-I/O in synchronous mode is done at 5 MHz for IBM-
- SCSI-devices. SCSI-2 Fast/Wide Adapter/A external bus
- should then run at 10 MHz if Fast-SCSI is enabled,
- and at 5 MHz if Fast-SCSI is disabled on the external
- bus. This is the default setting when nothing is
- specified here.
- medium Synchronous rate is at 50% approximately, which means
- 2.5 MHz for IBM SCSI-adapters and 5.0 MHz for F/W ext.
- SCSI-bus (when Fast-SCSI speed enabled on external bus).
- slow The slowest possible synchronous transfer rate is set.
- This means 1.82 MHz for IBM SCSI-adapters and 2.0 MHz
- for F/W external bus at Fast-SCSI speed on the external
- bus.
-
- A further option is that you can force the SCSI-driver to accept a SCSI-
- subsystem at a certain I/O-address with a predefined adapter PUN. This
- is done by entering
-
- commandN = I/O-base
- commandN+1 = adapter PUN
-
- e.g. ibmmcascsi=0x3540,7 will force the driver to detect a SCSI-subsystem
- at I/O-address 0x3540 with adapter PUN 7. Please only use this method, if
- the driver does really not recognize your SCSI-adapter! With driver version
- 3.2, this recognition of various adapters was hugely improved and you
- should try first to remove your commandline arguments of such type with a
- newer driver. I bet, it will be recognized correctly. Even multiple and
- different types of IBM SCSI-adapters should be recognized correctly, too.
- Use the forced detection method only as last solution!
-
- Examples:
-
- ibmmcascsi=adisplay
-
- This will use the advanced display mode for the model 95 LED alphanumeric
- display.
-
- ibmmcascsi=display,0x3558,7
-
- This will activate the default display mode for the model 95 LED display
- and will force the driver to accept a SCSI-subsystem at I/O-base 0x3558
- with adapter PUN 7.
-
- 5.2 Troubleshooting
- -------------------
- The following FAQs should help you to solve some major problems with this
- driver.
-
- Q: "Reset SCSI-devices at boottime" halts the system at boottime, why?
- A: This is only tested with the IBM SCSI Adapter w/cache. It is not
- yet proven to run on other adapters, however you may be lucky.
- In version 3.1d this has been hugely improved and should work better,
- now. Normally you really won't need to activate this flag in the
- kernel configuration, as all post 1989 SCSI-devices should accept
- the reset-signal, when the computer is switched on. The SCSI-
- subsystem generates this reset while being initialized. This flag
- is really reserved for users with very old, very strange or self-made
- SCSI-devices.
- Q: Why is the SCSI-order of my drives mirrored to the device-order
- seen from OS/2 or DOS ?
- A: It depends on the operating system, if it looks at the devices in
- ANSI-SCSI-standard (starting from pun 6 and going down to pun 0) or
- if it just starts at pun 0 and counts up. If you want to be conform
- with OS/2 and DOS, you have to activate this flag in the kernel
- configuration or you should set 'ansi' as parameter for the kernel.
- The parameter 'normal' sets the new industry standard, starting
- from pun 0, scanning up to pun 6. This allows you to change your
- opinion still after having already compiled the kernel.
- Q: Why can't I find IBM MCA SCSI support in the config menu?
- A: You have to activate MCA bus support, first.
- Q: Where can I find the latest info about this driver?
- A: See the file MAINTAINERS for the current WWW-address, which offers
- updates, info and Q/A lists. At this file's origin, the webaddress
- was: http://www.staff.uni-mainz.de/mlang/linux.html
- Q: My SCSI-adapter is not recognized by the driver, what can I do?
- A: Just force it to be recognized by kernel parameters. See section 5.1.
- If this really happens, do also send e-mail to the maintainer, as
- forced detection should be never necessary. Forced detection is in
- principal some flaw of the driver adapter detection and goes into
- bug reports.
- Q: The driver screws up, if it starts to probe SCSI-devices, is there
- some way out of it?
- A: Yes, that was some recognition problem of the correct SCSI-adapter
- and its I/O base addresses. Upgrade your driver to the latest release
- and it should be fine again.
- Q: I get a message: panic IBM MCA SCSI: command error .... , what can
- I do against this?
- A: Previously, I followed the way by ignoring command errors by using
- ibmmcascsi=forgiveall, but this command no longer exists and is
- obsolete. If such a problem appears, it is caused by some segmentation
- fault of the driver, which maps to some unallowed area. The latest
- version of the driver should be ok, as most bugs have been solved.
- Q: There are still kernel panics, even after having set
- ibmmcascsi=forgiveall. Are there other possibilities to prevent
- such panics?
- A: No, get just the latest release of the driver and it should work
- better and better with increasing version number. Forget about this
- ibmmcascsi=forgiveall, as also ignorecmd are obsolete.!
- Q: Linux panics or stops without any comment, but it is probable, that my
- harddisk(s) have bad blocks.
- A: Sorry, the bad-block handling is still a feeble point of this driver,
- but is on the schedule for development in the near future.
- Q: Linux panics while dynamically assigning SCSI-ids or ldns.
- A: If you disconnect a SCSI-device from the machine, while Linux is up
- and the driver uses dynamical reassignment of logical device numbers
- (ldn), it really gets "angry" if it won't find devices, that were still
- present at boottime and stops Linux.
- Q: The system does not recover after an abort-command has been generated.
- A: This is regrettably true, as it is not yet understood, why the
- SCSI-adapter does really NOT generate any interrupt at the end of
- the abort-command. As no interrupt is generated, the abort command
- cannot get finished and the system hangs, sorry, but checks are
- running to hunt down this problem. If there is a real pending command,
- the interrupt MUST get generated after abort. In this case, it
- should finish well.
- Q: The system gets in bad shape after a SCSI-reset, is this known?
- A: Yes, as there are a lot of prescriptions (see the Linux Hackers'
- Guide) what has to be done for reset, we still share the bad shape of
- the reset functions with all other low level SCSI-drivers.
- Astonishingly, reset works in most cases quite ok, but the harddisks
- won't run in synchronous mode anymore after a reset, until you reboot.
- Q: Why does my XXX w/Cache adapter not use read-prefetch?
- A: Ok, that is not completely possible. If a cache is present, the
- adapter tries to use it internally. Explicitly, one can use the cache
- with a read prefetch command, maybe in future, but this requires
- some major overhead of SCSI-commands that risks the performance to
- go down more than it gets improved. Tests with that are running.
- Q: I have a IBM SCSI-2 Fast/Wide adapter, it boots in some way and hangs.
- A: Yes, that is understood, as for sure, your SCSI-2 Fast/Wide adapter
- was in such a case recognized as integrated SCSI-adapter or something
- else, but not as the correct adapter. As the I/O-ports get assigned
- wrongly by that reason, the system should crash in most cases. You
- should upgrade to the latest release of the SCSI-driver. The
- recommended version is 3.2 or later. Here, the F/W support is in
- a stable and reliable condition. Wide-addressing is in addition
- supported.
- Q: I get an Oops message and something like "killing interrupt".
- A: The reason for this is that the IBM SCSI-subsystem only sends a
- termination status back, if some error appeared. In former releases
- of the driver, it was not checked, if the termination status block
- is NULL. From version 3.2, it is taken care of this.
- Q: I have a F/W adapter and the driver sees my internal SCSI-devices,
- but ignores the external ones.
- A: Select combined busmode in the IBM config-program and check for that
- no SCSI-id on the external devices appears on internal devices.
- Reboot afterwards. Dual busmode is supported, but works only for the
- internal bus, yet. External bus is still ignored. Take care for your
- SCSI-ids. If combined bus-mode is activated, on some adapters,
- the wide-addressing is not possible, so devices with ids between 8
- and 15 get ignored by the driver & adapter!
- Q: I have a 9595 and I get a NMI during heavy SCSI I/O e.g. during fsck.
- A COMMAND ERROR is reported and characters on the screen are missing.
- Warm reboot is not possible. Things look like quite weird.
- A: Check the processor type of your 9595. If you have an 80486 or 486DX-2
- processor complex on your mainboard and you compiled a kernel that
- supports 80386 processors, it is possible, that the kernel cannot
- keep track of the PS/2 interrupt handling and stops on an NMI. Just
- compile a kernel for the correct processor type of your PS/2 and
- everything should be fine. This is necessary even if one assumes,
- that some 80486 system should be downward compatible to 80386
- software.
- Q: Some commands hang and interrupts block the machine. After some
- timeout, the syslog reports that it tries to call abort, but the
- machine is frozen.
- A: This can be a busy wait bug in the interrupt handler of driver
- version 3.2. You should at least upgrade to 3.2c if you use
- kernel < 2.4.0 and driver version 4.0 if you use kernel 2.4.0 or
- later (including all test releases).
- Q: I have a PS/2 model 80 and more than 16 MBytes of RAM. The driver
- completely refuses to work, reports NMIs, COMMAND ERRORs or other
- ambiguous stuff. When reducing the RAM size down below 16 MB,
- everything is running smoothly.
- A: No real answer, yet. In any case, one should force the kernel to
- present SCBs only below the 16 MBytes barrier. Maybe this solves the
- problem. Not yet tried, but guessing that it could work. To get this,
- set unchecked_isa_dma argument of ibmmca.h from 0 to 1.
-
- 5.3 Bug reports
- --------------
- If you really find bugs in the source code or the driver will successfully
- refuse to work on your machine, you should send a bug report to me. The
- best for this is to follow the instructions on the WWW-page for this
- driver. Fill out the bug-report form, placed on the WWW-page and ship it,
- so the bugs can be taken into account with maximum efforts. But, please
- do not send bug reports about this driver to Linus Torvalds or Leonard
- Zubkoff, as Linus is buried in E-Mail and Leonard is supervising all
- SCSI-drivers and won't have the time left to look inside every single
- driver to fix a bug and especially DO NOT send modified code to Linus
- Torvalds or Alan J. Cox which has not been checked here!!! They are both
- quite buried in E-mail (as me, sometimes, too) and one should first check
- for problems on my local teststand. Recently, I got a lot of
- bug reports for errors in the ibmmca.c code, which I could not imagine, but
- a look inside some Linux-distribution showed me quite often some modified
- code, which did no longer work on most other machines than the one of the
- modifier. Ok, so now that there is maintenance service available for this
- driver, please use this address first in order to keep the level of
- confusion low. Thank you!
-
- When you get a SCSI-error message that panics your system, a list of
- register-entries of the SCSI-subsystem is shown (from Version 3.1d). With
- this list, it is very easy for the maintainer to localize the problem in
- the driver or in the configuration of the user. Please write down all the
- values from this report and send them to the maintainer. This would really
- help a lot and makes life easier concerning misunderstandings.
-
- Use the bug-report form (see 5.4 for its address) to send all the bug-
- stuff to the maintainer or write e-mail with the values from the table.
-
- 5.4 Support WWW-page
- --------------------
- The address of the IBM SCSI-subsystem supporting WWW-page is:
-
- http://www.staff.uni-mainz.de/mlang/linux.html
-
- Here you can find info about the background of this driver, patches,
- troubleshooting support, news and a bugreport form. Please check that
- WWW-page regularly for latest hints. If ever this URL changes, please
- refer to the MAINTAINERS file in order to get the latest address.
-
- For the bugreport, please fill out the formular on the corresponding
- WWW-page. Read the dedicated instructions and write as much as you
- know about your problem. If you do not like such formulars, please send
- some e-mail directly, but at least with the same information as required by
- the formular.
-
- If you have extensive bug reports, including Oops messages and
- screen-shots, please feel free to send it directly to the address
- of the maintainer, too. The current address of the maintainer is:
-
- Michael Lang <langa2@kph.uni-mainz.de>
-
- 6 References
- ------------
- IBM Corp., "Update for the PS/2 Hardware Interface Technical Reference,
- Common Interfaces", Armonk, September 1991, PN 04G3281,
- (available in the U.S. for $21.75 at 1-800-IBM-PCTB or in Germany for
- around 40,-DM at "Hallo IBM").
-
- IBM Corp., "Personal System/2 Micro Channel SCSI
- Adapter with Cache Technical Reference", Armonk, March 1990, PN 68X2365.
-
- IBM Corp., "Personal System/2 Micro Channel SCSI
- Adapter Technical Reference", Armonk, March 1990, PN 68X2397.
-
- IBM Corp., "SCSI-2 Fast/Wide Adapter/A Technical Reference - Dual Bus",
- Armonk, March 1994, PN 83G7545.
-
- Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
- Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
- Addison Wesley, 1996.
-
- Michael K. Johnson, "The Linux Kernel Hackers' Guide", Version 0.6, Chapel
- Hill - North Carolina, 1995
-
- Andreas Kaiser, "SCSI TAPE BACKUP for OS/2 2.0", Version 2.12, Stuttgart
- 1993
-
- Helmut Rompel, "IBM Computerwelt GUIDE", What is what bei IBM., Systeme *
- Programme * Begriffe, IWT-Verlag GmbH - Muenchen, 1988
-
- 7 Credits to
- ------------
- 7.1 People
- ----------
- Klaus Grimm
- who already a long time ago gave me the old code from the
- SCSI-driver in order to get it running for some old machine
- in our institute.
- Martin Kolinek
- who wrote the first release of the IBM SCSI-subsystem driver.
- Chris Beauregard
- who for a long time maintained MCA-Linux and the SCSI-driver
- in the beginning. Chris, wherever you are: Cheers to you!
- Klaus Kudielka
- with whom in the 2.1.x times, I had a quite fruitful
- cooperation to get the driver running as a module and to get
- it running with multiple SCSI-adapters.
- David Weinehall
- for his excellent maintenance of the MCA-stuff and the quite
- detailed bug reports and ideas for this driver (and his
- patience ;-)).
- Alan J. Cox
- for his bug reports and his bold activities in cross-checking
- the driver-code with his teststand.
-
- 7.2 Sponsors & Supporters
- -------------------------
- "Hallo IBM",
- IBM-Deutschland GmbH
- the service of IBM-Deutschland for customers. Their E-Mail
- service is unbeatable. Whatever old stuff I asked for, I
- always got some helpful answers.
- Karl-Otto Reimers,
- IBM Klub - Sparte IBM Geschichte, Sindelfingen
- for sending me a copy of the w/Cache manual from the
- IBM-Deutschland archives.
- Harald Staiger
- for his extensive hardware donations which allows me today
- still to test the driver in various constellations.
- Erich Fritscher
- for his very kind sponsoring.
- Louis Ohland,
- Charles Lasitter
- for support by shipping me an IBM SCSI-2 Fast/Wide manual.
- In addition, the contribution of various hardware is quite
- decessive and will make it possible to add FWSR (RAID)
- adapter support to the driver in the near future! So,
- complaints about no RAID support won't remain forever.
- Yes, folks, that is no joke, RAID support is going to rise!
- Erik Weber
- for the great deal we made about a model 9595 and the nice
- surrounding equipment and the cool trip to Mannheim
- second-hand computer market. In addition, I would like
- to thank him for his exhaustive SCSI-driver testing on his
- 95er PS/2 park.
- Anthony Hogbin
- for his direct shipment of a SCSI F/W adapter, which allowed
- me immediately on the first stage to try it on model 8557
- together with onboard SCSI adapter and some SCSI w/Cache.
- Andreas Hotz
- for his support by memory and an IBM SCSI-adapter. Collecting
- all this together now allows me to try really things with
- the driver at maximum load and variety on various models in
- a very quick and efficient way.
- Peter Jennewein
- for his model 30, which serves me as part of my teststand
- and his cool remark about how you make an ordinary diskette
- drive working and how to connect it to an IBM-diskette port.
- Johannes Gutenberg-Universitaet, Mainz &
- Institut fuer Kernphysik, Mainz Microtron (MAMI)
- for the offered space, the link, placed on the central
- homepage and the space to store and offer the driver and
- related material and the free working times, which allow
- me to answer all your e-mail.
-
- 8 Trademarks
- ------------
- IBM, PS/2, OS/2, Microchannel are registered trademarks of International
- Business Machines Corporation
-
- MS-DOS is a registered trademark of Microsoft Corporation
-
- Microware, OS-9 are registered trademarks of Microware Systems
-
- 9 Disclaimer
- ------------
- Beside the GNU General Public License and the dependent disclaimers and disclaimers
- concerning the Linux-kernel in special, this SCSI-driver comes without any
- warranty. Its functionality is tested as good as possible on certain
- machines and combinations of computer hardware, which does not exclude,
- that data loss or severe damage of hardware is possible while using this
- part of software on some arbitrary computer hardware or in combination
- with other software packages. It is highly recommended to make backup
- copies of your data before using this software. Furthermore, personal
- injuries by hardware defects, that could be caused by this SCSI-driver are
- not excluded and it is highly recommended to handle this driver with a
- maximum of carefulness.
-
- This driver supports hardware, produced by International Business Machines
- Corporation (IBM).
-
-------
-Michael Lang
-(langa2@kph.uni-mainz.de)
diff --git a/Documentation/scsi/scsi-parameters.txt b/Documentation/scsi/scsi-parameters.txt
index 21e5798..2bfd6f6 100644
--- a/Documentation/scsi/scsi-parameters.txt
+++ b/Documentation/scsi/scsi-parameters.txt
@@ -37,9 +37,6 @@ parameters may be changed at runtime by the command
eata= [HW,SCSI]
- fd_mcs= [HW,SCSI]
- See header of drivers/scsi/fd_mcs.c.
-
fdomain= [HW,SCSI]
See header of drivers/scsi/fdomain.c.
@@ -48,9 +45,6 @@ parameters may be changed at runtime by the command
gvp11= [HW,SCSI]
- ibmmcascsi= [HW,MCA,SCSI] IBM MicroChannel SCSI adapter
- See Documentation/mca.txt.
-
in2000= [HW,SCSI]
See header of drivers/scsi/in2000.c.
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index a340b18..2b06aba 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -30,7 +30,7 @@ the motherboard (or both). Some aic7xxx based HBAs are dual controllers
and thus represent two hosts. Like most modern HBAs, each aic7xxx host
has its own PCI device address. [The one-to-one correspondence between
a SCSI host and a PCI device is common but not required (e.g. with
-ISA or MCA adapters).]
+ISA adapters).]
The SCSI mid level isolates an LLD from other layers such as the SCSI
upper layer drivers and the block layer.
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 29684c8..7a66d0e 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -807,19 +807,6 @@ config SCSI_FUTURE_DOMAIN
To compile this driver as a module, choose M here: the
module will be called fdomain.
-config SCSI_FD_MCS
- tristate "Future Domain MCS-600/700 SCSI support"
- depends on MCA_LEGACY && SCSI
- ---help---
- This is support for Future Domain MCS 600/700 MCA SCSI adapters.
- Some PS/2 computers are equipped with IBM Fast SCSI Adapter/A which
- is identical to the MCS 700 and hence also supported by this driver.
- This driver also supports the Reply SB16/SCSI card (the SCSI part).
- It supports multiple adapters in the same system.
-
- To compile this driver as a module, choose M here: the
- module will be called fd_mcs.
-
config SCSI_GDTH
tristate "Intel/ICP (former GDT SCSI Disk Array) RAID Controller support"
depends on (ISA || EISA || PCI) && SCSI && ISA_DMA_API
@@ -889,76 +876,6 @@ config SCSI_GENERIC_NCR53C400
not detect your card. See the file
<file:Documentation/scsi/g_NCR5380.txt> for details.
-config SCSI_IBMMCA
- tristate "IBMMCA SCSI support"
- depends on MCA && SCSI
- ---help---
- This is support for the IBM SCSI adapter found in many of the PS/2
- series computers. These machines have an MCA bus, so you need to
- answer Y to "MCA support" as well and read
- <file:Documentation/mca.txt>.
-
- If the adapter isn't found during boot (a common problem for models
- 56, 57, 76, and 77) you'll need to use the 'ibmmcascsi=<pun>' kernel
- option, where <pun> is the id of the SCSI subsystem (usually 7, but
- if that doesn't work check your reference diskette). Owners of
- model 95 with a LED-matrix-display can in addition activate some
- activity info like under OS/2, but more informative, by setting
- 'ibmmcascsi=display' as an additional kernel parameter. Try "man
- bootparam" or see the documentation of your boot loader about how to
- pass options to the kernel.
-
- To compile this driver as a module, choose M here: the
- module will be called ibmmca.
-
-config IBMMCA_SCSI_ORDER_STANDARD
- bool "Standard SCSI-order"
- depends on SCSI_IBMMCA
- ---help---
- In the PC-world and in most modern SCSI-BIOS-setups, SCSI-hard disks
- are assigned to the drive letters, starting with the lowest SCSI-id
- (physical number -- pun) to be drive C:, as seen from DOS and
- similar operating systems. When looking into papers describing the
- ANSI-SCSI-standard, this assignment of drives appears to be wrong.
- The SCSI-standard follows a hardware-hierarchy which says that id 7
- has the highest priority and id 0 the lowest. Therefore, the host
- adapters are still today everywhere placed as SCSI-id 7 by default.
- In the SCSI-standard, the drive letters express the priority of the
- disk. C: should be the hard disk, or a partition on it, with the
- highest priority. This must therefore be the disk with the highest
- SCSI-id (e.g. 6) and not the one with the lowest! IBM-BIOS kept the
- original definition of the SCSI-standard as also industrial- and
- process-control-machines, like VME-CPUs running under realtime-OSes
- (e.g. LynxOS, OS9) do.
-
- If you like to run Linux on your MCA-machine with the same
- assignment of hard disks as seen from e.g. DOS or OS/2 on your
- machine, which is in addition conformant to the SCSI-standard, you
- must say Y here. This is also necessary for MCA-Linux users who want
- to keep downward compatibility to older releases of the
- IBM-MCA-SCSI-driver (older than driver-release 2.00 and older than
- June 1997).
-
- If you like to have the lowest SCSI-id assigned as drive C:, as
- modern SCSI-BIOSes do, which does not conform to the standard, but
- is widespread and common in the PC-world of today, you must say N
- here. If unsure, say Y.
-
-config IBMMCA_SCSI_DEV_RESET
- bool "Reset SCSI-devices at boottime"
- depends on SCSI_IBMMCA
- ---help---
- By default, SCSI-devices are reset when the machine is powered on.
- However, some devices exist, like special-control-devices,
- SCSI-CNC-machines, SCSI-printer or scanners of older type, that do
- not reset when switched on. If you say Y here, each device connected
- to your SCSI-bus will be issued a reset-command after it has been
- probed, while the kernel is booting. This may cause problems with
- more modern devices, like hard disks, which do not appreciate these
- reset commands, and can cause your system to hang. So say Y only if
- you know that one of your older devices needs it; N is the safe
- answer.
-
config SCSI_IPS
tristate "IBM ServeRAID support"
depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 8deedea..1a3368b 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -75,7 +75,6 @@ obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/
obj-$(CONFIG_SCSI_PM8001) += pm8001/
obj-$(CONFIG_SCSI_ISCI) += isci/
obj-$(CONFIG_SCSI_IPS) += ips.o
-obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o
obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
obj-$(CONFIG_SCSI_IN2000) += in2000.o
obj-$(CONFIG_SCSI_GENERIC_NCR5380) += g_NCR5380.o
@@ -100,7 +99,6 @@ obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/
obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
-obj-$(CONFIG_SCSI_IBMMCA) += ibmmca.o
obj-$(CONFIG_SCSI_EATA) += eata.o
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index ede91f3..f79c8f9 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -22,7 +22,7 @@
* Added module command-line options
* 19-Jul-99
* Modified by Adam Fritzler
- * Added proper detection of the AHA-1640 (MCA version of AHA-1540)
+ * Added proper detection of the AHA-1640 (MCA, now deleted)
*/
#include <linux/module.h>
@@ -37,8 +37,6 @@
#include <linux/spinlock.h>
#include <linux/isapnp.h>
#include <linux/blkdev.h>
-#include <linux/mca.h>
-#include <linux/mca-legacy.h>
#include <linux/slab.h>
#include <asm/dma.h>
@@ -71,7 +69,7 @@
#define MAXBOARDS 4 /* Increase this and the sizes of the
arrays below, if you need more.. */
-/* Boards 3,4 slots are reserved for ISAPnP/MCA scans */
+/* Boards 3,4 slots are reserved for ISAPnP scans */
static unsigned int bases[MAXBOARDS] __initdata = {0x330, 0x334, 0, 0};
@@ -1009,66 +1007,6 @@ static int __init aha1542_detect(struct scsi_host_template * tpnt)
#endif
/*
- * Find MicroChannel cards (AHA1640)
- */
-#ifdef CONFIG_MCA_LEGACY
- if(MCA_bus) {
- int slot = 0;
- int pos = 0;
-
- for (indx = 0; (slot != MCA_NOTFOUND) && (indx < ARRAY_SIZE(bases)); indx++) {
-
- if (bases[indx])
- continue;
-
- /* Detect only AHA-1640 cards -- MCA ID 0F1F */
- slot = mca_find_unused_adapter(0x0f1f, slot);
- if (slot == MCA_NOTFOUND)
- break;
-
- /* Found one */
- pos = mca_read_stored_pos(slot, 3);
-
- /* Decode address */
- if (pos & 0x80) {
- if (pos & 0x02) {
- if (pos & 0x01)
- bases[indx] = 0x334;
- else
- bases[indx] = 0x234;
- } else {
- if (pos & 0x01)
- bases[indx] = 0x134;
- }
- } else {
- if (pos & 0x02) {
- if (pos & 0x01)
- bases[indx] = 0x330;
- else
- bases[indx] = 0x230;
- } else {
- if (pos & 0x01)
- bases[indx] = 0x130;
- }
- }
-
- /* No need to decode IRQ and Arb level -- those are
- * read off the card later.
- */
- printk(KERN_INFO "Found an AHA-1640 in MCA slot %d, I/O 0x%04x\n", slot, bases[indx]);
-
- mca_set_adapter_name(slot, "Adapter AHA-1640");
- mca_set_adapter_procfn(slot, NULL, NULL);
- mca_mark_as_used(slot);
-
- /* Go on */
- slot++;
- }
-
- }
-#endif
-
- /*
* Hunt for ISA Plug'n'Pray Adaptecs (AHA1535)
*/
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
deleted file mode 100644
index 53bfcaa..0000000
--- a/drivers/scsi/fd_mcs.c
+++ /dev/null
@@ -1,1354 +0,0 @@
-/* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver
- *
- * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net)
- *
- * This driver is cloned from fdomain.* to specifically support
- * the Future Domain MCS 600/700 MCA SCSI adapters. Some PS/2s
- * also equipped with IBM Fast SCSI Adapter/A which is an OEM
- * of MCS 700.
- *
- * This driver also supports Reply SB16/SCSI card (the SCSI part).
- *
- * What makes this driver different is that this driver is MCA only
- * and it supports multiple adapters in the same system, IRQ
- * sharing, some driver statistics, and maps highest SCSI id to sda.
- * All cards are auto-detected.
- *
- * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4
- *
- * LILO command-line options:
- * fd_mcs=<FIFO_COUNT>[,<FIFO_SIZE>]
- *
- * ********************************************************
- * Please see Copyrights/Comments in fdomain.* for credits.
- * Following is from fdomain.c for acknowledgement:
- *
- * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Wed Oct 2 11:10:55 1996 by r.faith@ieee.org
- * Author: Rickard E. Faith, faith@cs.unc.edu
- * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
- *
- * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
-
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
-
- **************************************************************************
-
- NOTES ON USER DEFINABLE OPTIONS:
-
- DEBUG: This turns on the printing of various debug information.
-
- ENABLE_PARITY: This turns on SCSI parity checking. With the current
- driver, all attached devices must support SCSI parity. If none of your
- devices support parity, then you can probably get the driver to work by
- turning this option off. I have no way of testing this, however, and it
- would appear that no one ever uses this option.
-
- FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the
- 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by
- the SCSI device, an interrupt will be raised. Therefore, this could be as
- low as 0, or as high as 16. Note, however, that values which are too high
- or too low seem to prevent any interrupts from occurring, and thereby lock
- up the machine. I have found that 2 is a good number, but throughput may
- be increased by changing this value to values which are close to 2.
- Please let me know if you try any different values.
- [*****Now a runtime option*****]
-
- RESELECTION: This is no longer an option, since I gave up trying to
- implement it in version 4.x of this driver. It did not improve
- performance at all and made the driver unstable (because I never found one
- of the two race conditions which were introduced by the multiple
- outstanding command code). The instability seems a very high price to pay
- just so that you don't have to wait for the tape to rewind. If you want
- this feature implemented, send me patches. I'll be happy to send a copy
- of my (broken) driver to anyone who would like to see a copy.
-
- **************************************************************************/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/proc_fs.h>
-#include <linux/delay.h>
-#include <linux/mca.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <scsi/scsicam.h>
-#include <linux/mca-legacy.h>
-
-#include <asm/io.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-
-#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
-
-/* START OF USER DEFINABLE OPTIONS */
-
-#define DEBUG 0 /* Enable debugging output */
-#define ENABLE_PARITY 1 /* Enable SCSI Parity */
-
-/* END OF USER DEFINABLE OPTIONS */
-
-#if DEBUG
-#define EVERY_ACCESS 0 /* Write a line on every scsi access */
-#define ERRORS_ONLY 1 /* Only write a line if there is an error */
-#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
-#define DEBUG_ABORT 1 /* Debug abort() routine */
-#define DEBUG_RESET 1 /* Debug reset() routine */
-#define DEBUG_RACE 1 /* Debug interrupt-driven race condition */
-#else
-#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
-#define ERRORS_ONLY 0
-#define DEBUG_MESSAGES 0
-#define DEBUG_ABORT 0
-#define DEBUG_RESET 0
-#define DEBUG_RACE 0
-#endif
-
-/* Errors are reported on the line, so we don't need to report them again */
-#if EVERY_ACCESS
-#undef ERRORS_ONLY
-#define ERRORS_ONLY 0
-#endif
-
-#if ENABLE_PARITY
-#define PARITY_MASK 0x08
-#else
-#define PARITY_MASK 0x00
-#endif
-
-enum chip_type {
- unknown = 0x00,
- tmc1800 = 0x01,
- tmc18c50 = 0x02,
- tmc18c30 = 0x03,
-};
-
-enum {
- in_arbitration = 0x02,
- in_selection = 0x04,
- in_other = 0x08,
- disconnect = 0x10,
- aborted = 0x20,
- sent_ident = 0x40,
-};
-
-enum in_port_type {
- Read_SCSI_Data = 0,
- SCSI_Status = 1,
- TMC_Status = 2,
- FIFO_Status = 3, /* tmc18c50/tmc18c30 only */
- Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */
- LSB_ID_Code = 5,
- MSB_ID_Code = 6,
- Read_Loopback = 7,
- SCSI_Data_NoACK = 8,
- Interrupt_Status = 9,
- Configuration1 = 10,
- Configuration2 = 11, /* tmc18c50/tmc18c30 only */
- Read_FIFO = 12,
- FIFO_Data_Count = 14
-};
-
-enum out_port_type {
- Write_SCSI_Data = 0,
- SCSI_Cntl = 1,
- Interrupt_Cntl = 2,
- SCSI_Mode_Cntl = 3,
- TMC_Cntl = 4,
- Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */
- Write_Loopback = 7,
- IO_Control = 11, /* tmc18c30 only */
- Write_FIFO = 12
-};
-
-struct fd_hostdata {
- unsigned long _bios_base;
- int _bios_major;
- int _bios_minor;
- volatile int _in_command;
- Scsi_Cmnd *_current_SC;
- enum chip_type _chip;
- int _adapter_mask;
- int _fifo_count; /* Number of 512 byte blocks before INTR */
-
- char _adapter_name[64];
-#if DEBUG_RACE
- volatile int _in_interrupt_flag;
-#endif
-
- int _SCSI_Mode_Cntl_port;
- int _FIFO_Data_Count_port;
- int _Interrupt_Cntl_port;
- int _Interrupt_Status_port;
- int _Interrupt_Cond_port;
- int _Read_FIFO_port;
- int _Read_SCSI_Data_port;
- int _SCSI_Cntl_port;
- int _SCSI_Data_NoACK_port;
- int _SCSI_Status_port;
- int _TMC_Cntl_port;
- int _TMC_Status_port;
- int _Write_FIFO_port;
- int _Write_SCSI_Data_port;
-
- int _FIFO_Size; /* = 0x2000; 8k FIFO for
- pre-tmc18c30 chips */
- /* simple stats */
- int _Bytes_Read;
- int _Bytes_Written;
- int _INTR_Processed;
-};
-
-#define FD_MAX_HOSTS 3 /* enough? */
-
-#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata)
-#define bios_base (HOSTDATA(shpnt)->_bios_base)
-#define bios_major (HOSTDATA(shpnt)->_bios_major)
-#define bios_minor (HOSTDATA(shpnt)->_bios_minor)
-#define in_command (HOSTDATA(shpnt)->_in_command)
-#define current_SC (HOSTDATA(shpnt)->_current_SC)
-#define chip (HOSTDATA(shpnt)->_chip)
-#define adapter_mask (HOSTDATA(shpnt)->_adapter_mask)
-#define FIFO_COUNT (HOSTDATA(shpnt)->_fifo_count)
-#define adapter_name (HOSTDATA(shpnt)->_adapter_name)
-#if DEBUG_RACE
-#define in_interrupt_flag (HOSTDATA(shpnt)->_in_interrupt_flag)
-#endif
-#define SCSI_Mode_Cntl_port (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port)
-#define FIFO_Data_Count_port (HOSTDATA(shpnt)->_FIFO_Data_Count_port)
-#define Interrupt_Cntl_port (HOSTDATA(shpnt)->_Interrupt_Cntl_port)
-#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port)
-#define Interrupt_Cond_port (HOSTDATA(shpnt)->_Interrupt_Cond_port)
-#define Read_FIFO_port (HOSTDATA(shpnt)->_Read_FIFO_port)
-#define Read_SCSI_Data_port (HOSTDATA(shpnt)->_Read_SCSI_Data_port)
-#define SCSI_Cntl_port (HOSTDATA(shpnt)->_SCSI_Cntl_port)
-#define SCSI_Data_NoACK_port (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port)
-#define SCSI_Status_port (HOSTDATA(shpnt)->_SCSI_Status_port)
-#define TMC_Cntl_port (HOSTDATA(shpnt)->_TMC_Cntl_port)
-#define TMC_Status_port (HOSTDATA(shpnt)->_TMC_Status_port)
-#define Write_FIFO_port (HOSTDATA(shpnt)->_Write_FIFO_port)
-#define Write_SCSI_Data_port (HOSTDATA(shpnt)->_Write_SCSI_Data_port)
-#define FIFO_Size (HOSTDATA(shpnt)->_FIFO_Size)
-#define Bytes_Read (HOSTDATA(shpnt)->_Bytes_Read)
-#define Bytes_Written (HOSTDATA(shpnt)->_Bytes_Written)
-#define INTR_Processed (HOSTDATA(shpnt)->_INTR_Processed)
-
-struct fd_mcs_adapters_struct {
- char *name;
- int id;
- enum chip_type fd_chip;
- int fifo_size;
- int fifo_count;
-};
-
-#define REPLY_ID 0x5137
-
-static struct fd_mcs_adapters_struct fd_mcs_adapters[] = {
- {"Future Domain SCSI Adapter MCS-700(18C50)",
- 0x60e9,
- tmc18c50,
- 0x2000,
- 4},
- {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)",
- 0x6127,
- tmc1800,
- 0x2000,
- 4},
- {"Reply Sound Blaster/SCSI Adapter",
- REPLY_ID,
- tmc18c30,
- 0x800,
- 2},
-};
-
-#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
-
-static irqreturn_t fd_mcs_intr(int irq, void *dev_id);
-
-static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
-static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
-static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
-
-/* host information */
-static int found = 0;
-static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
-
-static int user_fifo_count = 0;
-static int user_fifo_size = 0;
-
-#ifndef MODULE
-static int __init fd_mcs_setup(char *str)
-{
- static int done_setup = 0;
- int ints[3];
-
- get_options(str, 3, ints);
- if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
- printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
- return 0;
- }
-
- user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
- user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
- return 1;
-}
-
-__setup("fd_mcs=", fd_mcs_setup);
-#endif /* !MODULE */
-
-static void print_banner(struct Scsi_Host *shpnt)
-{
- printk("scsi%d <fd_mcs>: ", shpnt->host_no);
-
- if (bios_base) {
- printk("BIOS at 0x%lX", bios_base);
- } else {
- printk("No BIOS");
- }
-
- 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);
-}
-
-
-static void do_pause(unsigned amount)
-{ /* Pause for amount*10 milliseconds */
- do {
- mdelay(10);
- } while (--amount);
-}
-
-static void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt)
-{
- outb(0, SCSI_Cntl_port);
- outb(0, SCSI_Mode_Cntl_port);
- if (chip == tmc18c50 || chip == tmc18c30)
- outb(0x21 | PARITY_MASK, TMC_Cntl_port); /* Clear forced intr. */
- else
- outb(0x01 | PARITY_MASK, TMC_Cntl_port);
-}
-
-static int fd_mcs_detect(struct scsi_host_template * tpnt)
-{
- int loop;
- struct Scsi_Host *shpnt;
-
- /* get id, port, bios, irq */
- int slot;
- u_char pos2, pos3, pos4;
- int id, port, irq;
- unsigned long bios;
-
- /* if not MCA machine, return */
- if (!MCA_bus)
- return 0;
-
- /* changeable? */
- id = 7;
-
- for (loop = 0; loop < FD_BRDS; loop++) {
- slot = 0;
- while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) {
-
- /* if we get this far, an adapter has been detected and is
- enabled */
-
- printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1);
-
- pos2 = mca_read_stored_pos(slot, 2);
- pos3 = mca_read_stored_pos(slot, 3);
- pos4 = mca_read_stored_pos(slot, 4);
-
- /* ready for next probe */
- slot++;
-
- if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */
- static int reply_irq[] = { 10, 11, 14, 15 };
-
- bios = 0; /* no bios */
-
- if (pos2 & 0x2)
- port = ports[pos4 & 0x3];
- else
- continue;
-
- /* can't really disable it, same as irq=10 */
- irq = reply_irq[((pos4 >> 2) & 0x1) + 2 * ((pos4 >> 4) & 0x1)];
- } else {
- bios = addresses[pos2 >> 6];
- port = ports[(pos2 >> 4) & 0x03];
- irq = interrupts[(pos2 >> 1) & 0x07];
- }
-
- if (irq) {
- /* claim the slot */
- mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name);
-
- /* check irq/region */
- if (request_irq(irq, fd_mcs_intr, IRQF_SHARED, "fd_mcs", hosts)) {
- printk(KERN_ERR "fd_mcs: interrupt is not available, skipping...\n");
- continue;
- }
-
- /* request I/O region */
- if (request_region(port, 0x10, "fd_mcs")) {
- printk(KERN_ERR "fd_mcs: I/O region is already in use, skipping...\n");
- continue;
- }
- /* register */
- if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) {
- printk(KERN_ERR "fd_mcs: scsi_register() failed\n");
- release_region(port, 0x10);
- free_irq(irq, hosts);
- continue;
- }
-
-
- /* save name */
- strcpy(adapter_name, fd_mcs_adapters[loop].name);
-
- /* chip/fifo */
- chip = fd_mcs_adapters[loop].fd_chip;
- /* use boot time value if available */
- FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
- FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
-
-/* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
-#ifdef NOT_USED
- /* *************************************************** */
- /* Try to toggle 32-bit mode. This only
- works on an 18c30 chip. (User reports
- say this works, so we should switch to
- it in the near future.) */
- outb(0x80, port + IO_Control);
- if ((inb(port + Configuration2) & 0x80) == 0x80) {
- outb(0x00, port + IO_Control);
- if ((inb(port + Configuration2) & 0x80) == 0x00) {
- chip = tmc18c30;
- FIFO_Size = 0x800; /* 2k FIFO */
-
- printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
- }
- }
-
- /* That should have worked, but appears to
- have problems. Let's assume it is an
- 18c30 if the RAM is disabled. */
-
- if (inb(port + Configuration2) & 0x02) {
- chip = tmc18c30;
- FIFO_Size = 0x800; /* 2k FIFO */
-
- printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size);
- }
- /* *************************************************** */
-#endif
-
- /* IBM/ANSI scsi scan ordering */
- /* Stick this back in when the scsi.c changes are there */
- shpnt->reverse_ordering = 1;
-
-
- /* saving info */
- hosts[found++] = shpnt;
-
- shpnt->this_id = id;
- shpnt->irq = irq;
- shpnt->io_port = port;
- shpnt->n_io_port = 0x10;
-
- /* save */
- bios_base = bios;
- adapter_mask = (1 << id);
-
- /* save more */
- SCSI_Mode_Cntl_port = port + SCSI_Mode_Cntl;
- FIFO_Data_Count_port = port + FIFO_Data_Count;
- Interrupt_Cntl_port = port + Interrupt_Cntl;
- Interrupt_Status_port = port + Interrupt_Status;
- Interrupt_Cond_port = port + Interrupt_Cond;
- Read_FIFO_port = port + Read_FIFO;
- Read_SCSI_Data_port = port + Read_SCSI_Data;
- SCSI_Cntl_port = port + SCSI_Cntl;
- SCSI_Data_NoACK_port = port + SCSI_Data_NoACK;
- SCSI_Status_port = port + SCSI_Status;
- TMC_Cntl_port = port + TMC_Cntl;
- TMC_Status_port = port + TMC_Status;
- Write_FIFO_port = port + Write_FIFO;
- Write_SCSI_Data_port = port + Write_SCSI_Data;
-
- Bytes_Read = 0;
- Bytes_Written = 0;
- INTR_Processed = 0;
-
- /* say something */
- print_banner(shpnt);
-
- /* reset */
- outb(1, SCSI_Cntl_port);
- do_pause(2);
- outb(0, SCSI_Cntl_port);
- do_pause(115);
- outb(0, SCSI_Mode_Cntl_port);
- outb(PARITY_MASK, TMC_Cntl_port);
- /* done reset */
- }
- }
-
- if (found == FD_MAX_HOSTS) {
- printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS);
- break;
- }
- }
-
- return found;
-}
-
-static const char *fd_mcs_info(struct Scsi_Host *shpnt)
-{
- return adapter_name;
-}
-
-static int TOTAL_INTR = 0;
-
-/*
- * inout : decides on the direction of the dataflow and the meaning of the
- * variables
- * buffer: If inout==FALSE data is being written to it else read from it
- * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file
- * from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer
- * else number of bytes in the buffer
- */
-static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
-{
- int len = 0;
-
- if (inout)
- return (-ENOSYS);
-
- *start = buffer + offset;
-
- len += sprintf(buffer + len, "Future Domain MCS-600/700 Driver %s\n", DRIVER_VERSION);
- len += sprintf(buffer + len, "HOST #%d: %s\n", shpnt->host_no, adapter_name);
- len += sprintf(buffer + len, "FIFO Size=0x%x, FIFO Count=%d\n", FIFO_Size, FIFO_COUNT);
- len += sprintf(buffer + len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written);
-
- if ((len -= offset) <= 0)
- return 0;
- if (len > length)
- len = length;
- return len;
-}
-
-static int fd_mcs_select(struct Scsi_Host *shpnt, int target)
-{
- int status;
- unsigned long timeout;
-
- outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
- outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port);
-
- /* Stop arbitration and enable parity */
- outb(PARITY_MASK, TMC_Cntl_port);
-
- timeout = 350; /* 350mS -- because of timeouts
- (was 250mS) */
-
- do {
- status = inb(SCSI_Status_port); /* Read adapter status */
- if (status & 1) { /* Busy asserted */
- /* Enable SCSI Bus (on error, should make bus idle with 0) */
- outb(0x80, SCSI_Cntl_port);
- return 0;
- }
- udelay(1000); /* wait one msec */
- } while (--timeout);
-
- /* Make bus idle */
- fd_mcs_make_bus_idle(shpnt);
-#if EVERY_ACCESS
- if (!target)
- printk("Selection failed\n");
-#endif
-#if ERRORS_ONLY
- if (!target) {
- static int flag = 0;
-
- if (!flag) /* Skip first failure for all chips. */
- ++flag;
- else
- printk("fd_mcs: Selection failed\n");
- }
-#endif
- return 1;
-}
-
-static void my_done(struct Scsi_Host *shpnt, int error)
-{
- if (in_command) {
- in_command = 0;
- outb(0x00, Interrupt_Cntl_port);
- fd_mcs_make_bus_idle(shpnt);
- current_SC->result = error;
- current_SC->scsi_done(current_SC);
- } else {
- panic("fd_mcs: my_done() called outside of command\n");
- }
-#if DEBUG_RACE
- in_interrupt_flag = 0;
-#endif
-}
-
-/* only my_done needs to be protected */
-static irqreturn_t fd_mcs_intr(int irq, void *dev_id)
-{
- unsigned long flags;
- int status;
- int done = 0;
- unsigned data_count, tmp_count;
-
- int i = 0;
- struct Scsi_Host *shpnt;
-
- TOTAL_INTR++;
-
- /* search for one adapter-response on shared interrupt */
- while ((shpnt = hosts[i++])) {
- if ((inb(TMC_Status_port)) & 1)
- break;
- }
-
- /* return if some other device on this IRQ caused the interrupt */
- if (!shpnt) {
- return IRQ_NONE;
- }
-
- INTR_Processed++;
-
- outb(0x00, Interrupt_Cntl_port);
-
- /* Abort calls my_done, so we do nothing here. */
- if (current_SC->SCp.phase & aborted) {
-#if DEBUG_ABORT
- printk("Interrupt after abort, ignoring\n");
-#endif
- /* return IRQ_HANDLED; */
- }
-#if DEBUG_RACE
- ++in_interrupt_flag;
-#endif
-
- if (current_SC->SCp.phase & in_arbitration) {
- status = inb(TMC_Status_port); /* Read adapter status */
- if (!(status & 0x02)) {
-#if EVERY_ACCESS
- printk(" AFAIL ");
-#endif
- spin_lock_irqsave(shpnt->host_lock, flags);
- my_done(shpnt, DID_BUS_BUSY << 16);
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- }
- current_SC->SCp.phase = in_selection;
-
- outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port);
-
- outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */
- outb(adapter_mask | (1 << scmd_id(current_SC)), SCSI_Data_NoACK_port);
-
- /* Stop arbitration and enable parity */
- outb(0x10 | PARITY_MASK, TMC_Cntl_port);
-#if DEBUG_RACE
- in_interrupt_flag = 0;
-#endif
- return IRQ_HANDLED;
- } else if (current_SC->SCp.phase & in_selection) {
- status = inb(SCSI_Status_port);
- if (!(status & 0x01)) {
- /* Try again, for slow devices */
- if (fd_mcs_select(shpnt, scmd_id(current_SC))) {
-#if EVERY_ACCESS
- printk(" SFAIL ");
-#endif
- spin_lock_irqsave(shpnt->host_lock, flags);
- my_done(shpnt, DID_NO_CONNECT << 16);
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- } else {
-#if EVERY_ACCESS
- printk(" AltSel ");
-#endif
- /* Stop arbitration and enable parity */
- outb(0x10 | PARITY_MASK, TMC_Cntl_port);
- }
- }
- current_SC->SCp.phase = in_other;
- outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
- outb(0x80, SCSI_Cntl_port);
-#if DEBUG_RACE
- in_interrupt_flag = 0;
-#endif
- return IRQ_HANDLED;
- }
-
- /* current_SC->SCp.phase == in_other: this is the body of the routine */
-
- status = inb(SCSI_Status_port);
-
- if (status & 0x10) { /* REQ */
-
- switch (status & 0x0e) {
-
- case 0x08: /* COMMAND OUT */
- outb(current_SC->cmnd[current_SC->SCp.sent_command++], Write_SCSI_Data_port);
-#if EVERY_ACCESS
- printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]);
-#endif
- break;
- case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */
- if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
- current_SC->SCp.have_data_in = -1;
- outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
- }
- break;
- case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */
- if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
- current_SC->SCp.have_data_in = 1;
- outb(0x90 | PARITY_MASK, TMC_Cntl_port);
- }
- break;
- case 0x0c: /* STATUS IN */
- current_SC->SCp.Status = inb(Read_SCSI_Data_port);
-#if EVERY_ACCESS
- printk("Status = %x, ", current_SC->SCp.Status);
-#endif
-#if ERRORS_ONLY
- if (current_SC->SCp.Status && current_SC->SCp.Status != 2 && current_SC->SCp.Status != 8) {
- printk("ERROR fd_mcs: target = %d, command = %x, status = %x\n", current_SC->device->id, current_SC->cmnd[0], current_SC->SCp.Status);
- }
-#endif
- break;
- case 0x0a: /* MESSAGE OUT */
- outb(MESSAGE_REJECT, Write_SCSI_Data_port); /* Reject */
- break;
- case 0x0e: /* MESSAGE IN */
- current_SC->SCp.Message = inb(Read_SCSI_Data_port);
-#if EVERY_ACCESS
- printk("Message = %x, ", current_SC->SCp.Message);
-#endif
- if (!current_SC->SCp.Message)
- ++done;
-#if DEBUG_MESSAGES || EVERY_ACCESS
- if (current_SC->SCp.Message) {
- printk("fd_mcs: message = %x\n", current_SC->SCp.Message);
- }
-#endif
- break;
- }
- }
-
- if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
- /* We have to get the FIFO direction
- correct, so I've made a table based
- on the SCSI Standard of which commands
- appear to require a DATA OUT phase.
- */
- /*
- p. 94: Command for all device types
- CHANGE DEFINITION 40 DATA OUT
- COMPARE 39 DATA OUT
- COPY 18 DATA OUT
- COPY AND VERIFY 3a DATA OUT
- INQUIRY 12
- LOG SELECT 4c DATA OUT
- LOG SENSE 4d
- MODE SELECT (6) 15 DATA OUT
- MODE SELECT (10) 55 DATA OUT
- MODE SENSE (6) 1a
- MODE SENSE (10) 5a
- READ BUFFER 3c
- RECEIVE DIAGNOSTIC RESULTS 1c
- REQUEST SENSE 03
- SEND DIAGNOSTIC 1d DATA OUT
- TEST UNIT READY 00
- WRITE BUFFER 3b DATA OUT
-
- p.178: Commands for direct-access devices (not listed on p. 94)
- FORMAT UNIT 04 DATA OUT
- LOCK-UNLOCK CACHE 36
- PRE-FETCH 34
- PREVENT-ALLOW MEDIUM REMOVAL 1e
- READ (6)/RECEIVE 08
- READ (10) 3c
- READ CAPACITY 25
- READ DEFECT DATA (10) 37
- READ LONG 3e
- REASSIGN BLOCKS 07 DATA OUT
- RELEASE 17
- RESERVE 16 DATA OUT
- REZERO UNIT/REWIND 01
- SEARCH DATA EQUAL (10) 31 DATA OUT
- SEARCH DATA HIGH (10) 30 DATA OUT
- SEARCH DATA LOW (10) 32 DATA OUT
- SEEK (6) 0b
- SEEK (10) 2b
- SET LIMITS (10) 33
- START STOP UNIT 1b
- SYNCHRONIZE CACHE 35
- VERIFY (10) 2f
- WRITE (6)/PRINT/SEND 0a DATA OUT
- WRITE (10)/SEND 2a DATA OUT
- WRITE AND VERIFY (10) 2e DATA OUT
- WRITE LONG 3f DATA OUT
- WRITE SAME 41 DATA OUT ?
-
- p. 261: Commands for sequential-access devices (not previously listed)
- ERASE 19
- LOAD UNLOAD 1b
- LOCATE 2b
- READ BLOCK LIMITS 05
- READ POSITION 34
- READ REVERSE 0f
- RECOVER BUFFERED DATA 14
- SPACE 11
- WRITE FILEMARKS 10 ?
-
- p. 298: Commands for printer devices (not previously listed)
- ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) *****
- SLEW AND PRINT 0b DATA OUT -- same as seek
- STOP PRINT 1b
- SYNCHRONIZE BUFFER 10
-
- p. 315: Commands for processor devices (not previously listed)
-
- p. 321: Commands for write-once devices (not previously listed)
- MEDIUM SCAN 38
- READ (12) a8
- SEARCH DATA EQUAL (12) b1 DATA OUT
- SEARCH DATA HIGH (12) b0 DATA OUT
- SEARCH DATA LOW (12) b2 DATA OUT
- SET LIMITS (12) b3
- VERIFY (12) af
- WRITE (12) aa DATA OUT
- WRITE AND VERIFY (12) ae DATA OUT
-
- p. 332: Commands for CD-ROM devices (not previously listed)
- PAUSE/RESUME 4b
- PLAY AUDIO (10) 45
- PLAY AUDIO (12) a5
- PLAY AUDIO MSF 47
- PLAY TRACK RELATIVE (10) 49
- PLAY TRACK RELATIVE (12) a9
- READ HEADER 44
- READ SUB-CHANNEL 42
- READ TOC 43
-
- p. 370: Commands for scanner devices (not previously listed)
- GET DATA BUFFER STATUS 34
- GET WINDOW 25
- OBJECT POSITION 31
- SCAN 1b
- SET WINDOW 24 DATA OUT
-
- p. 391: Commands for optical memory devices (not listed)
- ERASE (10) 2c
- ERASE (12) ac
- MEDIUM SCAN 38 DATA OUT
- READ DEFECT DATA (12) b7
- READ GENERATION 29
- READ UPDATED BLOCK 2d
- UPDATE BLOCK 3d DATA OUT
-
- p. 419: Commands for medium changer devices (not listed)
- EXCHANGE MEDIUM 46
- INITIALIZE ELEMENT STATUS 07
- MOVE MEDIUM a5
- POSITION TO ELEMENT 2b
- READ ELEMENT STATUS b8
- REQUEST VOL. ELEMENT ADDRESS b5
- SEND VOLUME TAG b6 DATA OUT
-
- p. 454: Commands for communications devices (not listed previously)
- GET MESSAGE (6) 08
- GET MESSAGE (10) 28
- GET MESSAGE (12) a8
- */
-
- switch (current_SC->cmnd[0]) {
- case CHANGE_DEFINITION:
- case COMPARE:
- case COPY:
- case COPY_VERIFY:
- case LOG_SELECT:
- case MODE_SELECT:
- case MODE_SELECT_10:
- case SEND_DIAGNOSTIC:
- case WRITE_BUFFER:
-
- case FORMAT_UNIT:
- case REASSIGN_BLOCKS:
- case RESERVE:
- case SEARCH_EQUAL:
- case SEARCH_HIGH:
- case SEARCH_LOW:
- case WRITE_6:
- case WRITE_10:
- case WRITE_VERIFY:
- case 0x3f:
- case 0x41:
-
- case 0xb1:
- case 0xb0:
- case 0xb2:
- case 0xaa:
- case 0xae:
-
- case 0x24:
-
- case 0x38:
- case 0x3d:
-
- case 0xb6:
-
- case 0xea: /* alternate number for WRITE LONG */
-
- current_SC->SCp.have_data_in = -1;
- outb(0xd0 | PARITY_MASK, TMC_Cntl_port);
- break;
-
- case 0x00:
- default:
-
- current_SC->SCp.have_data_in = 1;
- outb(0x90 | PARITY_MASK, TMC_Cntl_port);
- break;
- }
- }
-
- if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */
- while ((data_count = FIFO_Size - inw(FIFO_Data_Count_port)) > 512) {
-#if EVERY_ACCESS
- printk("DC=%d, ", data_count);
-#endif
- if (data_count > current_SC->SCp.this_residual)
- data_count = current_SC->SCp.this_residual;
- if (data_count > 0) {
-#if EVERY_ACCESS
- printk("%d OUT, ", data_count);
-#endif
- if (data_count == 1) {
- Bytes_Written++;
-
- outb(*current_SC->SCp.ptr++, Write_FIFO_port);
- --current_SC->SCp.this_residual;
- } else {
- data_count >>= 1;
- tmp_count = data_count << 1;
- outsw(Write_FIFO_port, current_SC->SCp.ptr, data_count);
- current_SC->SCp.ptr += tmp_count;
- Bytes_Written += tmp_count;
- current_SC->SCp.this_residual -= tmp_count;
- }
- }
- if (!current_SC->SCp.this_residual) {
- if (current_SC->SCp.buffers_residual) {
- --current_SC->SCp.buffers_residual;
- ++current_SC->SCp.buffer;
- current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
- current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
- } else
- break;
- }
- }
- } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */
- while ((data_count = inw(FIFO_Data_Count_port)) > 0) {
-#if EVERY_ACCESS
- printk("DC=%d, ", data_count);
-#endif
- if (data_count > current_SC->SCp.this_residual)
- data_count = current_SC->SCp.this_residual;
- if (data_count) {
-#if EVERY_ACCESS
- printk("%d IN, ", data_count);
-#endif
- if (data_count == 1) {
- Bytes_Read++;
- *current_SC->SCp.ptr++ = inb(Read_FIFO_port);
- --current_SC->SCp.this_residual;
- } else {
- data_count >>= 1; /* Number of words */
- tmp_count = data_count << 1;
- insw(Read_FIFO_port, current_SC->SCp.ptr, data_count);
- current_SC->SCp.ptr += tmp_count;
- Bytes_Read += tmp_count;
- current_SC->SCp.this_residual -= tmp_count;
- }
- }
- if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) {
- --current_SC->SCp.buffers_residual;
- ++current_SC->SCp.buffer;
- current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
- current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
- }
- }
- }
-
- if (done) {
-#if EVERY_ACCESS
- printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in);
-#endif
-
-#if EVERY_ACCESS
- printk("BEFORE MY_DONE. . .");
-#endif
- spin_lock_irqsave(shpnt->host_lock, flags);
- my_done(shpnt, (current_SC->SCp.Status & 0xff)
- | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16));
- spin_unlock_irqrestore(shpnt->host_lock, flags);
-#if EVERY_ACCESS
- printk("RETURNING.\n");
-#endif
-
- } else {
- if (current_SC->SCp.phase & disconnect) {
- outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port);
- outb(0x00, SCSI_Cntl_port);
- } else {
- outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port);
- }
- }
-#if DEBUG_RACE
- in_interrupt_flag = 0;
-#endif
- return IRQ_HANDLED;
-}
-
-static int fd_mcs_release(struct Scsi_Host *shpnt)
-{
- int i, this_host, irq_usage;
-
- release_region(shpnt->io_port, shpnt->n_io_port);
-
- this_host = -1;
- irq_usage = 0;
- for (i = 0; i < found; i++) {
- if (shpnt == hosts[i])
- this_host = i;
- if (shpnt->irq == hosts[i]->irq)
- irq_usage++;
- }
-
- /* only for the last one */
- if (1 == irq_usage)
- free_irq(shpnt->irq, hosts);
-
- found--;
-
- for (i = this_host; i < found; i++)
- hosts[i] = hosts[i + 1];
-
- hosts[found] = NULL;
-
- return 0;
-}
-
-static int fd_mcs_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
-{
- struct Scsi_Host *shpnt = SCpnt->device->host;
-
- if (in_command) {
- panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n");
- }
-#if EVERY_ACCESS
- printk("queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
- SCpnt->target, *(unsigned char *) SCpnt->cmnd,
- scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
-#endif
-
- fd_mcs_make_bus_idle(shpnt);
-
- SCpnt->scsi_done = done; /* Save this for the done function */
- current_SC = SCpnt;
-
- /* Initialize static data */
-
- if (scsi_bufflen(current_SC)) {
- current_SC->SCp.buffer = scsi_sglist(current_SC);
- current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
- current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
- current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
- } else {
- current_SC->SCp.ptr = NULL;
- current_SC->SCp.this_residual = 0;
- current_SC->SCp.buffer = NULL;
- current_SC->SCp.buffers_residual = 0;
- }
-
-
- current_SC->SCp.Status = 0;
- current_SC->SCp.Message = 0;
- current_SC->SCp.have_data_in = 0;
- current_SC->SCp.sent_command = 0;
- current_SC->SCp.phase = in_arbitration;
-
- /* Start arbitration */
- outb(0x00, Interrupt_Cntl_port);
- outb(0x00, SCSI_Cntl_port); /* Disable data drivers */
- outb(adapter_mask, SCSI_Data_NoACK_port); /* Set our id bit */
- in_command = 1;
- outb(0x20, Interrupt_Cntl_port);
- outb(0x14 | PARITY_MASK, TMC_Cntl_port); /* Start arbitration */
-
- return 0;
-}
-
-static DEF_SCSI_QCMD(fd_mcs_queue)
-
-#if DEBUG_ABORT || DEBUG_RESET
-static void fd_mcs_print_info(Scsi_Cmnd * SCpnt)
-{
- unsigned int imr;
- unsigned int irr;
- unsigned int isr;
- struct Scsi_Host *shpnt = SCpnt->host;
-
- if (!SCpnt || !SCpnt->host) {
- printk("fd_mcs: cannot provide detailed information\n");
- }
-
- printk("%s\n", fd_mcs_info(SCpnt->host));
- print_banner(SCpnt->host);
- switch (SCpnt->SCp.phase) {
- case in_arbitration:
- printk("arbitration ");
- break;
- case in_selection:
- printk("selection ");
- break;
- case in_other:
- printk("other ");
- break;
- default:
- printk("unknown ");
- break;
- }
-
- printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
- SCpnt->SCp.phase, SCpnt->device->id, *(unsigned char *) SCpnt->cmnd,
- scsi_sg_count(SCpnt), scsi_bufflen(SCpnt));
- printk("sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, SCpnt->timeout);
-#if DEBUG_RACE
- printk("in_interrupt_flag = %d\n", in_interrupt_flag);
-#endif
-
- imr = (inb(0x0a1) << 8) + inb(0x21);
- outb(0x0a, 0xa0);
- irr = inb(0xa0) << 8;
- outb(0x0a, 0x20);
- irr += inb(0x20);
- outb(0x0b, 0xa0);
- isr = inb(0xa0) << 8;
- outb(0x0b, 0x20);
- isr += inb(0x20);
-
- /* Print out interesting information */
- printk("IMR = 0x%04x", imr);
- if (imr & (1 << shpnt->irq))
- printk(" (masked)");
- printk(", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr);
-
- printk("SCSI Status = 0x%02x\n", inb(SCSI_Status_port));
- printk("TMC Status = 0x%02x", inb(TMC_Status_port));
- if (inb(TMC_Status_port) & 1)
- printk(" (interrupt)");
- printk("\n");
- printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port));
- if (inb(Interrupt_Status_port) & 0x08)
- printk(" (enabled)");
- printk("\n");
- if (chip == tmc18c50 || chip == tmc18c30) {
- printk("FIFO Status = 0x%02x\n", inb(shpnt->io_port + FIFO_Status));
- printk("Int. Condition = 0x%02x\n", inb(shpnt->io_port + Interrupt_Cond));
- }
- printk("Configuration 1 = 0x%02x\n", inb(shpnt->io_port + Configuration1));
- if (chip == tmc18c50 || chip == tmc18c30)
- printk("Configuration 2 = 0x%02x\n", inb(shpnt->io_port + Configuration2));
-}
-#endif
-
-static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
-{
- struct Scsi_Host *shpnt = SCpnt->device->host;
-
- unsigned long flags;
-#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
- printk("fd_mcs: abort ");
-#endif
-
- spin_lock_irqsave(shpnt->host_lock, flags);
- if (!in_command) {
-#if EVERY_ACCESS || ERRORS_ONLY
- printk(" (not in command)\n");
-#endif
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return FAILED;
- } else
- printk("\n");
-
-#if DEBUG_ABORT
- fd_mcs_print_info(SCpnt);
-#endif
-
- fd_mcs_make_bus_idle(shpnt);
-
- current_SC->SCp.phase |= aborted;
-
- current_SC->result = DID_ABORT << 16;
-
- /* Aborts are not done well. . . */
- my_done(shpnt, DID_ABORT << 16);
-
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return SUCCESS;
-}
-
-static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
- struct Scsi_Host *shpnt = SCpnt->device->host;
- unsigned long flags;
-
-#if DEBUG_RESET
- static int called_once = 0;
-#endif
-
-#if ERRORS_ONLY
- if (SCpnt)
- printk("fd_mcs: SCSI Bus Reset\n");
-#endif
-
-#if DEBUG_RESET
- if (called_once)
- fd_mcs_print_info(current_SC);
- called_once = 1;
-#endif
-
- spin_lock_irqsave(shpnt->host_lock, flags);
-
- outb(1, SCSI_Cntl_port);
- do_pause(2);
- outb(0, SCSI_Cntl_port);
- do_pause(115);
- outb(0, SCSI_Mode_Cntl_port);
- outb(PARITY_MASK, TMC_Cntl_port);
-
- spin_unlock_irqrestore(shpnt->host_lock, flags);
-
- /* Unless this is the very first call (i.e., SCPnt == NULL), everything
- is probably hosed at this point. We will, however, try to keep
- things going by informing the high-level code that we need help. */
- return SUCCESS;
-}
-
-#include <scsi/scsi_ioctl.h>
-
-static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev,
- sector_t capacity, int *info_array)
-{
- unsigned char *p = scsi_bios_ptable(bdev);
- int size = capacity;
-
- /* BIOS >= 3.4 for MCA cards */
- /* This algorithm was provided by Future Domain (much thanks!). */
-
- if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */
- && p[4]) { /* Partition type */
- /* The partition table layout is as follows:
-
- Start: 0x1b3h
- Offset: 0 = partition status
- 1 = starting head
- 2 = starting sector and cylinder (word, encoded)
- 4 = partition type
- 5 = ending head
- 6 = ending sector and cylinder (word, encoded)
- 8 = starting absolute sector (double word)
- c = number of sectors (double word)
- Signature: 0x1fe = 0x55aa
-
- So, this algorithm assumes:
- 1) the first partition table is in use,
- 2) the data in the first entry is correct, and
- 3) partitions never divide cylinders
-
- Note that (1) may be FALSE for NetBSD (and other BSD flavors),
- as well as for Linux. Note also, that Linux doesn't pay any
- attention to the fields that are used by this algorithm -- it
- only uses the absolute sector data. Recent versions of Linux's
- fdisk(1) will fill this data in correctly, and forthcoming
- versions will check for consistency.
-
- Checking for a non-zero partition type is not part of the
- Future Domain algorithm, but it seemed to be a reasonable thing
- to do, especially in the Linux and BSD worlds. */
-
- info_array[0] = p[5] + 1; /* heads */
- info_array[1] = p[6] & 0x3f; /* sectors */
- } else {
- /* Note that this new method guarantees that there will always be
- less than 1024 cylinders on a platter. This is good for drives
- up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */
- if ((unsigned int) size >= 0x7e0000U)
- {
- info_array[0] = 0xff; /* heads = 255 */
- info_array[1] = 0x3f; /* sectors = 63 */
- } else if ((unsigned int) size >= 0x200000U) {
- info_array[0] = 0x80; /* heads = 128 */
- info_array[1] = 0x3f; /* sectors = 63 */
- } else {
- info_array[0] = 0x40; /* heads = 64 */
- info_array[1] = 0x20; /* sectors = 32 */
- }
- }
- /* For both methods, compute the cylinders */
- info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]);
- kfree(p);
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .proc_name = "fd_mcs",
- .proc_info = fd_mcs_proc_info,
- .detect = fd_mcs_detect,
- .release = fd_mcs_release,
- .info = fd_mcs_info,
- .queuecommand = fd_mcs_queue,
- .eh_abort_handler = fd_mcs_abort,
- .eh_bus_reset_handler = fd_mcs_bus_reset,
- .bios_param = fd_mcs_biosparam,
- .can_queue = 1,
- .this_id = 7,
- .sg_tablesize = 64,
- .cmd_per_lun = 1,
- .use_clustering = DISABLE_CLUSTERING,
-};
-#include "scsi_module.c"
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
deleted file mode 100644
index cd09132..0000000
--- a/drivers/scsi/ibmmca.c
+++ /dev/null
@@ -1,2379 +0,0 @@
-/*
- Low Level Linux Driver for the IBM Microchannel SCSI Subsystem for
- Linux Kernel >= 2.4.0.
- Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU
- General Public License. Written by Martin Kolinek, December 1995.
- Further development by: Chris Beauregard, Klaus Kudielka, Michael Lang
- See the file Documentation/scsi/ibmmca.txt for a detailed description
- of this driver, the commandline arguments and the history of its
- development.
- See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest
- updates, info and ADF-files for adapters supported by this driver.
-
- Alan Cox <alan@lxorguk.ukuu.org.uk>
- Updated for Linux 2.5.45 to use the new error handler, cleaned up the
- lock macros and did a few unavoidable locking tweaks, plus one locking
- fix in the irq and completion path.
-
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/mca.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-
-/* Common forward declarations for all Linux-versions: */
-static int ibmmca_queuecommand (struct Scsi_Host *, struct scsi_cmnd *);
-static int ibmmca_abort (Scsi_Cmnd *);
-static int ibmmca_host_reset (Scsi_Cmnd *);
-static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *);
-static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout);
-
-
-
-/* current version of this driver-source: */
-#define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac"
-
-/* driver configuration */
-#define IM_MAX_HOSTS 8 /* maximum number of host adapters */
-#define IM_RESET_DELAY 60 /* seconds allowed for a reset */
-
-/* driver debugging - #undef all for normal operation */
-/* if defined: count interrupts and ignore this special one: */
-#undef IM_DEBUG_TIMEOUT //50
-#define TIMEOUT_PUN 0
-#define TIMEOUT_LUN 0
-/* verbose interrupt: */
-#undef IM_DEBUG_INT
-/* verbose queuecommand: */
-#undef IM_DEBUG_CMD
-/* verbose queucommand for specific SCSI-device type: */
-#undef IM_DEBUG_CMD_SPEC_DEV
-/* verbose device probing */
-#undef IM_DEBUG_PROBE
-
-/* device type that shall be displayed on syslog (only during debugging): */
-#define IM_DEBUG_CMD_DEVICE TYPE_TAPE
-
-/* relative addresses of hardware registers on a subsystem */
-#define IM_CMD_REG(h) ((h)->io_port) /*Command Interface, (4 bytes long) */
-#define IM_ATTN_REG(h) ((h)->io_port+4) /*Attention (1 byte) */
-#define IM_CTR_REG(h) ((h)->io_port+5) /*Basic Control (1 byte) */
-#define IM_INTR_REG(h) ((h)->io_port+6) /*Interrupt Status (1 byte, r/o) */
-#define IM_STAT_REG(h) ((h)->io_port+7) /*Basic Status (1 byte, read only) */
-
-/* basic I/O-port of first adapter */
-#define IM_IO_PORT 0x3540
-/* maximum number of hosts that can be found */
-#define IM_N_IO_PORT 8
-
-/*requests going into the upper nibble of the Attention register */
-/*note: the lower nibble specifies the device(0-14), or subsystem(15) */
-#define IM_IMM_CMD 0x10 /*immediate command */
-#define IM_SCB 0x30 /*Subsystem Control Block command */
-#define IM_LONG_SCB 0x40 /*long Subsystem Control Block command */
-#define IM_EOI 0xe0 /*end-of-interrupt request */
-
-/*values for bits 7,1,0 of Basic Control reg. (bits 6-2 reserved) */
-#define IM_HW_RESET 0x80 /*hardware reset */
-#define IM_ENABLE_DMA 0x02 /*enable subsystem's busmaster DMA */
-#define IM_ENABLE_INTR 0x01 /*enable interrupts to the system */
-
-/*to interpret the upper nibble of Interrupt Status register */
-/*note: the lower nibble specifies the device(0-14), or subsystem(15) */
-#define IM_SCB_CMD_COMPLETED 0x10
-#define IM_SCB_CMD_COMPLETED_WITH_RETRIES 0x50
-#define IM_LOOP_SCATTER_BUFFER_FULL 0x60
-#define IM_ADAPTER_HW_FAILURE 0x70
-#define IM_IMMEDIATE_CMD_COMPLETED 0xa0
-#define IM_CMD_COMPLETED_WITH_FAILURE 0xc0
-#define IM_CMD_ERROR 0xe0
-#define IM_SOFTWARE_SEQUENCING_ERROR 0xf0
-
-/*to interpret bits 3-0 of Basic Status register (bits 7-4 reserved) */
-#define IM_CMD_REG_FULL 0x08
-#define IM_CMD_REG_EMPTY 0x04
-#define IM_INTR_REQUEST 0x02
-#define IM_BUSY 0x01
-
-/*immediate commands (word written into low 2 bytes of command reg) */
-#define IM_RESET_IMM_CMD 0x0400
-#define IM_FEATURE_CTR_IMM_CMD 0x040c
-#define IM_DMA_PACING_IMM_CMD 0x040d
-#define IM_ASSIGN_IMM_CMD 0x040e
-#define IM_ABORT_IMM_CMD 0x040f
-#define IM_FORMAT_PREP_IMM_CMD 0x0417
-
-/*SCB (Subsystem Control Block) structure */
-struct im_scb {
- unsigned short command; /*command word (read, etc.) */
- unsigned short enable; /*enable word, modifies cmd */
- union {
- unsigned long log_blk_adr; /*block address on SCSI device */
- unsigned char scsi_cmd_length; /*6,10,12, for other scsi cmd */
- } u1;
- unsigned long sys_buf_adr; /*physical system memory adr */
- unsigned long sys_buf_length; /*size of sys mem buffer */
- unsigned long tsb_adr; /*Termination Status Block adr */
- unsigned long scb_chain_adr; /*optional SCB chain address */
- union {
- struct {
- unsigned short count; /*block count, on SCSI device */
- unsigned short length; /*block length, on SCSI device */
- } blk;
- unsigned char scsi_command[12]; /*other scsi command */
- } u2;
-};
-
-/*structure scatter-gather element (for list of system memory areas) */
-struct im_sge {
- void *address;
- unsigned long byte_length;
-};
-
-/*structure returned by a get_pos_info command: */
-struct im_pos_info {
- unsigned short pos_id; /* adapter id */
- unsigned char pos_3a; /* pos 3 (if pos 6 = 0) */
- unsigned char pos_2; /* pos 2 */
- unsigned char int_level; /* interrupt level IRQ 11 or 14 */
- unsigned char pos_4a; /* pos 4 (if pos 6 = 0) */
- unsigned short connector_size; /* MCA connector size: 16 or 32 Bit */
- unsigned char num_luns; /* number of supported luns per device */
- unsigned char num_puns; /* number of supported puns */
- unsigned char pacing_factor; /* pacing factor */
- unsigned char num_ldns; /* number of ldns available */
- unsigned char eoi_off; /* time EOI and interrupt inactive */
- unsigned char max_busy; /* time between reset and busy on */
- unsigned short cache_stat; /* ldn cachestat. Bit=1 = not cached */
- unsigned short retry_stat; /* retry status of ldns. Bit=1=disabled */
- unsigned char pos_4b; /* pos 4 (if pos 6 = 1) */
- unsigned char pos_3b; /* pos 3 (if pos 6 = 1) */
- unsigned char pos_6; /* pos 6 */
- unsigned char pos_5; /* pos 5 */
- unsigned short max_overlap; /* maximum overlapping requests */
- unsigned short num_bus; /* number of SCSI-busses */
-};
-
-/*values for SCB command word */
-#define IM_NO_SYNCHRONOUS 0x0040 /*flag for any command */
-#define IM_NO_DISCONNECT 0x0080 /*flag for any command */
-#define IM_READ_DATA_CMD 0x1c01
-#define IM_WRITE_DATA_CMD 0x1c02
-#define IM_READ_VERIFY_CMD 0x1c03
-#define IM_WRITE_VERIFY_CMD 0x1c04
-#define IM_REQUEST_SENSE_CMD 0x1c08
-#define IM_READ_CAPACITY_CMD 0x1c09
-#define IM_DEVICE_INQUIRY_CMD 0x1c0b
-#define IM_READ_LOGICAL_CMD 0x1c2a
-#define IM_OTHER_SCSI_CMD_CMD 0x241f
-
-/* unused, but supported, SCB commands */
-#define IM_GET_COMMAND_COMPLETE_STATUS_CMD 0x1c07 /* command status */
-#define IM_GET_POS_INFO_CMD 0x1c0a /* returns neat stuff */
-#define IM_READ_PREFETCH_CMD 0x1c31 /* caching controller only */
-#define IM_FOMAT_UNIT_CMD 0x1c16 /* format unit */
-#define IM_REASSIGN_BLOCK_CMD 0x1c18 /* in case of error */
-
-/*values to set bits in the enable word of SCB */
-#define IM_READ_CONTROL 0x8000
-#define IM_REPORT_TSB_ONLY_ON_ERROR 0x4000
-#define IM_RETRY_ENABLE 0x2000
-#define IM_POINTER_TO_LIST 0x1000
-#define IM_SUPRESS_EXCEPTION_SHORT 0x0400
-#define IM_BYPASS_BUFFER 0x0200
-#define IM_CHAIN_ON_NO_ERROR 0x0001
-
-/*TSB (Termination Status Block) structure */
-struct im_tsb {
- unsigned short end_status;
- unsigned short reserved1;
- unsigned long residual_byte_count;
- unsigned long sg_list_element_adr;
- unsigned short status_length;
- unsigned char dev_status;
- unsigned char cmd_status;
- unsigned char dev_error;
- unsigned char cmd_error;
- unsigned short reserved2;
- unsigned short reserved3;
- unsigned short low_of_last_scb_adr;
- unsigned short high_of_last_scb_adr;
-};
-
-/*subsystem uses interrupt request level 14 */
-#define IM_IRQ 14
-/*SCSI-2 F/W may evade to interrupt 11 */
-#define IM_IRQ_FW 11
-
-/* Model 95 has an additional alphanumeric display, which can be used
- to display SCSI-activities. 8595 models do not have any disk led, which
- makes this feature quite useful.
- The regular PS/2 disk led is turned on/off by bits 6,7 of system
- control port. */
-
-/* LED display-port (actually, last LED on display) */
-#define MOD95_LED_PORT 0x108
-/* system-control-register of PS/2s with diskindicator */
-#define PS2_SYS_CTR 0x92
-/* activity displaying methods */
-#define LED_DISP 1
-#define LED_ADISP 2
-#define LED_ACTIVITY 4
-/* failed intr */
-#define CMD_FAIL 255
-
-/* The SCSI-ID(!) of the accessed SCSI-device is shown on PS/2-95 machines' LED
- displays. ldn is no longer displayed here, because the ldn mapping is now
- done dynamically and the ldn <-> pun,lun maps can be looked-up at boottime
- or during uptime in /proc/scsi/ibmmca/<host_no> in case of trouble,
- interest, debugging or just for having fun. The left number gives the
- host-adapter number and the right shows the accessed SCSI-ID. */
-
-/* display_mode is set by the ibmmcascsi= command line arg */
-static int display_mode = 0;
-/* set default adapter timeout */
-static unsigned int adapter_timeout = 45;
-/* for probing on feature-command: */
-static unsigned int global_command_error_excuse = 0;
-/* global setting by command line for adapter_speed */
-static int global_adapter_speed = 0; /* full speed by default */
-
-/* Panel / LED on, do it right for F/W addressin, too. adisplay will
- * just ignore ids>7, as the panel has only 7 digits available */
-#define PS2_DISK_LED_ON(ad,id) { if (display_mode & LED_DISP) { if (id>9) \
- outw((ad+48)|((id+55)<<8), MOD95_LED_PORT ); else \
- outw((ad+48)|((id+48)<<8), MOD95_LED_PORT ); } else \
- if (display_mode & LED_ADISP) { if (id<7) outb((char)(id+48),MOD95_LED_PORT+1+id); \
- outb((char)(ad+48), MOD95_LED_PORT); } \
- if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
- outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); }
-
-/* Panel / LED off */
-/* bug fixed, Dec 15, 1997, where | was replaced by & here */
-#define PS2_DISK_LED_OFF() { if (display_mode & LED_DISP) \
- outw(0x2020, MOD95_LED_PORT ); else if (display_mode & LED_ADISP) { \
- outl(0x20202020,MOD95_LED_PORT); outl(0x20202020,MOD95_LED_PORT+4); } \
- if ((display_mode & LED_ACTIVITY)||(!display_mode)) \
- outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); }
-
-/* types of different supported hardware that goes to hostdata special */
-#define IBM_SCSI2_FW 0
-#define IBM_7568_WCACHE 1
-#define IBM_EXP_UNIT 2
-#define IBM_SCSI_WCACHE 3
-#define IBM_SCSI 4
-#define IBM_INTEGSCSI 5
-
-/* other special flags for hostdata structure */
-#define FORCED_DETECTION 100
-#define INTEGRATED_SCSI 101
-
-/* List of possible IBM-SCSI-adapters */
-static short ibmmca_id_table[] = {
- 0x8efc,
- 0x8efd,
- 0x8ef8,
- 0x8eff,
- 0x8efe,
- /* No entry for integrated SCSI, that's part of the register */
- 0
-};
-
-static const char *ibmmca_description[] = {
- "IBM SCSI-2 F/W Adapter", /* special = 0 */
- "IBM 7568 Industrial Computer SCSI Adapter w/Cache", /* special = 1 */
- "IBM Expansion Unit SCSI Controller", /* special = 2 */
- "IBM SCSI Adapter w/Cache", /* special = 3 */
- "IBM SCSI Adapter", /* special = 4 */
- "IBM Integrated SCSI Controller", /* special = 5 */
-};
-
-/* Max number of logical devices (can be up from 0 to 14). 15 is the address
-of the adapter itself. */
-#define MAX_LOG_DEV 15
-
-/*local data for a logical device */
-struct logical_device {
- struct im_scb scb; /* SCSI-subsystem-control-block structure */
- struct im_tsb tsb; /* SCSI command complete status block structure */
- struct im_sge sge[16]; /* scatter gather list structure */
- unsigned char buf[256]; /* SCSI command return data buffer */
- Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */
- int device_type; /* type of the SCSI-device. See include/scsi/scsi.h
- for interpretation of the possible values */
- int block_length; /* blocksize of a particular logical SCSI-device */
- int cache_flag; /* 1 if this is uncached, 0 if cache is present for ldn */
- int retry_flag; /* 1 if adapter retry is disabled, 0 if enabled */
-};
-
-/* statistics of the driver during operations (for proc_info) */
-struct Driver_Statistics {
- /* SCSI statistics on the adapter */
- int ldn_access[MAX_LOG_DEV + 1]; /* total accesses on a ldn */
- int ldn_read_access[MAX_LOG_DEV + 1]; /* total read-access on a ldn */
- int ldn_write_access[MAX_LOG_DEV + 1]; /* total write-access on a ldn */
- int ldn_inquiry_access[MAX_LOG_DEV + 1]; /* total inquiries on a ldn */
- int ldn_modeselect_access[MAX_LOG_DEV + 1]; /* total mode selects on ldn */
- int scbs; /* short SCBs queued */
- int long_scbs; /* long SCBs queued */
- int total_accesses; /* total accesses on all ldns */
- int total_interrupts; /* total interrupts (should be
- same as total_accesses) */
- int total_errors; /* command completed with error */
- /* dynamical assignment statistics */
- int total_scsi_devices; /* number of physical pun,lun */
- int dyn_flag; /* flag showing dynamical mode */
- int dynamical_assignments; /* number of remappings of ldns */
- int ldn_assignments[MAX_LOG_DEV + 1]; /* number of remappings of each
- ldn */
-};
-
-/* data structure for each host adapter */
-struct ibmmca_hostdata {
- /* array of logical devices: */
- struct logical_device _ld[MAX_LOG_DEV + 1];
- /* array to convert (pun, lun) into logical device number: */
- unsigned char _get_ldn[16][8];
- /*array that contains the information about the physical SCSI-devices
- attached to this host adapter: */
- unsigned char _get_scsi[16][8];
- /* used only when checking logical devices: */
- int _local_checking_phase_flag;
- /* report received interrupt: */
- int _got_interrupt;
- /* report termination-status of SCSI-command: */
- int _stat_result;
- /* reset status (used only when doing reset): */
- int _reset_status;
- /* code of the last SCSI command (needed for panic info): */
- int _last_scsi_command[MAX_LOG_DEV + 1];
- /* identifier of the last SCSI-command type */
- int _last_scsi_type[MAX_LOG_DEV + 1];
- /* last blockcount */
- int _last_scsi_blockcount[MAX_LOG_DEV + 1];
- /* last locgical block address */
- unsigned long _last_scsi_logical_block[MAX_LOG_DEV + 1];
- /* Counter that points on the next reassignable ldn for dynamical
- remapping. The default value is 7, that is the first reassignable
- number in the list at boottime: */
- int _next_ldn;
- /* Statistics-structure for this IBM-SCSI-host: */
- struct Driver_Statistics _IBM_DS;
- /* This hostadapters pos-registers pos2 until pos6 */
- unsigned int _pos[8];
- /* assign a special variable, that contains dedicated info about the
- adaptertype */
- int _special;
- /* connector size on the MCA bus */
- int _connector_size;
- /* synchronous SCSI transfer rate bitpattern */
- int _adapter_speed;
-};
-
-/* macros to access host data structure */
-#define subsystem_pun(h) ((h)->this_id)
-#define subsystem_maxid(h) ((h)->max_id)
-#define ld(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_ld)
-#define get_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_ldn)
-#define get_scsi(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_get_scsi)
-#define local_checking_phase_flag(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_local_checking_phase_flag)
-#define got_interrupt(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_got_interrupt)
-#define stat_result(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_stat_result)
-#define reset_status(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_reset_status)
-#define last_scsi_command(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_command)
-#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
-#define last_scsi_blockcount(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_blockcount)
-#define last_scsi_logical_block(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_logical_block)
-#define last_scsi_type(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_last_scsi_type)
-#define next_ldn(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_next_ldn)
-#define IBM_DS(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_IBM_DS)
-#define special(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_special)
-#define subsystem_connector_size(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_connector_size)
-#define adapter_speed(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_adapter_speed)
-#define pos2(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[2])
-#define pos3(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[3])
-#define pos4(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[4])
-#define pos5(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[5])
-#define pos6(h) (((struct ibmmca_hostdata *) (h)->hostdata)->_pos[6])
-
-/* Define a arbitrary number as subsystem-marker-type. This number is, as
- described in the ANSI-SCSI-standard, not occupied by other device-types. */
-#define TYPE_IBM_SCSI_ADAPTER 0x2F
-
-/* Define 0xFF for no device type, because this type is not defined within
- the ANSI-SCSI-standard, therefore, it can be used and should not cause any
- harm. */
-#define TYPE_NO_DEVICE 0xFF
-
-/* define medium-changer. If this is not defined previously, e.g. Linux
- 2.0.x, define this type here. */
-#ifndef TYPE_MEDIUM_CHANGER
-#define TYPE_MEDIUM_CHANGER 0x08
-#endif
-
-/* define possible operations for the immediate_assign command */
-#define SET_LDN 0
-#define REMOVE_LDN 1
-
-/* ldn which is used to probe the SCSI devices */
-#define PROBE_LDN 0
-
-/* reset status flag contents */
-#define IM_RESET_NOT_IN_PROGRESS 0
-#define IM_RESET_IN_PROGRESS 1
-#define IM_RESET_FINISHED_OK 2
-#define IM_RESET_FINISHED_FAIL 3
-#define IM_RESET_NOT_IN_PROGRESS_NO_INT 4
-#define IM_RESET_FINISHED_OK_NO_INT 5
-
-/* define undefined SCSI-command */
-#define NO_SCSI 0xffff
-
-/*-----------------------------------------------------------------------*/
-
-/* if this is nonzero, ibmmcascsi option has been passed to the kernel */
-static int io_port[IM_MAX_HOSTS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-static int scsi_id[IM_MAX_HOSTS] = { 7, 7, 7, 7, 7, 7, 7, 7 };
-
-/* fill module-parameters only, when this define is present.
- (that is kernel version 2.1.x) */
-#if defined(MODULE)
-static char *boot_options = NULL;
-module_param(boot_options, charp, 0);
-module_param_array(io_port, int, NULL, 0);
-module_param_array(scsi_id, int, NULL, 0);
-
-MODULE_LICENSE("GPL");
-#endif
-/*counter of concurrent disk read/writes, to turn on/off disk led */
-static int disk_rw_in_progress = 0;
-
-static unsigned int pos[8]; /* whole pos register-line for diagnosis */
-/* Taking into account the additions, made by ZP Gu.
- * This selects now the preset value from the configfile and
- * offers the 'normal' commandline option to be accepted */
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
-static char ibm_ansi_order = 1;
-#else
-static char ibm_ansi_order = 0;
-#endif
-
-static void issue_cmd(struct Scsi_Host *, unsigned long, unsigned char);
-static void internal_done(Scsi_Cmnd * cmd);
-static void check_devices(struct Scsi_Host *, int);
-static int immediate_assign(struct Scsi_Host *, unsigned int, unsigned int, unsigned int, unsigned int);
-static int immediate_feature(struct Scsi_Host *, unsigned int, unsigned int);
-#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
-static int immediate_reset(struct Scsi_Host *, unsigned int);
-#endif
-static int device_inquiry(struct Scsi_Host *, int);
-static int read_capacity(struct Scsi_Host *, int);
-static int get_pos_info(struct Scsi_Host *);
-static char *ti_p(int);
-static char *ti_l(int);
-static char *ibmrate(unsigned int, int);
-static int probe_display(int);
-static int probe_bus_mode(struct Scsi_Host *);
-static int device_exists(struct Scsi_Host *, int, int *, int *);
-static int option_setup(char *);
-/* local functions needed for proc_info */
-static int ldn_access_load(struct Scsi_Host *, int);
-static int ldn_access_total_read_write(struct Scsi_Host *);
-
-static irqreturn_t interrupt_handler(int irq, void *dev_id)
-{
- unsigned int intr_reg;
- unsigned int cmd_result;
- unsigned int ldn;
- unsigned long flags;
- Scsi_Cmnd *cmd;
- int lastSCSI;
- struct device *dev = dev_id;
- struct Scsi_Host *shpnt = dev_get_drvdata(dev);
-
- spin_lock_irqsave(shpnt->host_lock, flags);
-
- if(!(inb(IM_STAT_REG(shpnt)) & IM_INTR_REQUEST)) {
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_NONE;
- }
-
- /* the reset-function already did all the job, even ints got
- renabled on the subsystem, so just return */
- if ((reset_status(shpnt) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(shpnt) == IM_RESET_FINISHED_OK_NO_INT)) {
- reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- }
-
- /*must wait for attention reg not busy, then send EOI to subsystem */
- while (1) {
- if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
- break;
- cpu_relax();
- }
-
- /*get command result and logical device */
- intr_reg = (unsigned char) (inb(IM_INTR_REG(shpnt)));
- cmd_result = intr_reg & 0xf0;
- ldn = intr_reg & 0x0f;
- /* get the last_scsi_command here */
- lastSCSI = last_scsi_command(shpnt)[ldn];
- outb(IM_EOI | ldn, IM_ATTN_REG(shpnt));
-
- /*these should never happen (hw fails, or a local programming bug) */
- if (!global_command_error_excuse) {
- switch (cmd_result) {
- /* Prevent from Ooopsing on error to show the real reason */
- case IM_ADAPTER_HW_FAILURE:
- case IM_SOFTWARE_SEQUENCING_ERROR:
- case IM_CMD_ERROR:
- printk(KERN_ERR "IBM MCA SCSI: Fatal Subsystem ERROR!\n");
- printk(KERN_ERR " Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(shpnt)[ldn].scb.enable);
- if (ld(shpnt)[ldn].cmd)
- printk("%ld/%ld,", (long) (scsi_bufflen(ld(shpnt)[ldn].cmd)), (long) (ld(shpnt)[ldn].scb.sys_buf_length));
- else
- printk("none,");
- if (ld(shpnt)[ldn].cmd)
- printk("Blocksize=%d", ld(shpnt)[ldn].scb.u2.blk.length);
- else
- printk("Blocksize=none");
- printk(", host=%p, ldn=0x%x\n", shpnt, ldn);
- if (ld(shpnt)[ldn].cmd) {
- printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(shpnt)[ldn], ld(shpnt)[ldn].scb.u2.blk.count);
- printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(shpnt)[ldn], ld(shpnt)[ldn].scb.u1.log_blk_adr);
- }
- printk(KERN_ERR "Reason given: %s\n", (cmd_result == IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : (cmd_result == IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN");
- /* if errors appear, enter this section to give detailed info */
- printk(KERN_ERR "IBM MCA SCSI: Subsystem Error-Status follows:\n");
- printk(KERN_ERR " Command Type................: %x\n", last_scsi_type(shpnt)[ldn]);
- printk(KERN_ERR " Attention Register..........: %x\n", inb(IM_ATTN_REG(shpnt)));
- printk(KERN_ERR " Basic Control Register......: %x\n", inb(IM_CTR_REG(shpnt)));
- printk(KERN_ERR " Interrupt Status Register...: %x\n", intr_reg);
- printk(KERN_ERR " Basic Status Register.......: %x\n", inb(IM_STAT_REG(shpnt)));
- if ((last_scsi_type(shpnt)[ldn] == IM_SCB) || (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB)) {
- printk(KERN_ERR " SCB-Command.................: %x\n", ld(shpnt)[ldn].scb.command);
- printk(KERN_ERR " SCB-Enable..................: %x\n", ld(shpnt)[ldn].scb.enable);
- printk(KERN_ERR " SCB-logical block address...: %lx\n", ld(shpnt)[ldn].scb.u1.log_blk_adr);
- printk(KERN_ERR " SCB-system buffer address...: %lx\n", ld(shpnt)[ldn].scb.sys_buf_adr);
- printk(KERN_ERR " SCB-system buffer length....: %lx\n", ld(shpnt)[ldn].scb.sys_buf_length);
- printk(KERN_ERR " SCB-tsb address.............: %lx\n", ld(shpnt)[ldn].scb.tsb_adr);
- printk(KERN_ERR " SCB-Chain address...........: %lx\n", ld(shpnt)[ldn].scb.scb_chain_adr);
- printk(KERN_ERR " SCB-block count.............: %x\n", ld(shpnt)[ldn].scb.u2.blk.count);
- printk(KERN_ERR " SCB-block length............: %x\n", ld(shpnt)[ldn].scb.u2.blk.length);
- }
- printk(KERN_ERR " Send this report to the maintainer.\n");
- panic("IBM MCA SCSI: Fatal error message from the subsystem (0x%X,0x%X)!\n", lastSCSI, cmd_result);
- break;
- }
- } else {
- /* The command error handling is made silent, but we tell the
- * calling function, that there is a reported error from the
- * adapter. */
- switch (cmd_result) {
- case IM_ADAPTER_HW_FAILURE:
- case IM_SOFTWARE_SEQUENCING_ERROR:
- case IM_CMD_ERROR:
- global_command_error_excuse = CMD_FAIL;
- break;
- default:
- global_command_error_excuse = 0;
- break;
- }
- }
- /* if no panic appeared, increase the interrupt-counter */
- IBM_DS(shpnt).total_interrupts++;
- /*only for local checking phase */
- if (local_checking_phase_flag(shpnt)) {
- stat_result(shpnt) = cmd_result;
- got_interrupt(shpnt) = 1;
- reset_status(shpnt) = IM_RESET_FINISHED_OK;
- last_scsi_command(shpnt)[ldn] = NO_SCSI;
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- }
- /* handling of commands coming from upper level of scsi driver */
- if (last_scsi_type(shpnt)[ldn] == IM_IMM_CMD) {
- /* verify ldn, and may handle rare reset immediate command */
- if ((reset_status(shpnt) == IM_RESET_IN_PROGRESS) && (last_scsi_command(shpnt)[ldn] == IM_RESET_IMM_CMD)) {
- if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
- disk_rw_in_progress = 0;
- PS2_DISK_LED_OFF();
- reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
- } else {
- /*reset disk led counter, turn off disk led */
- disk_rw_in_progress = 0;
- PS2_DISK_LED_OFF();
- reset_status(shpnt) = IM_RESET_FINISHED_OK;
- }
- stat_result(shpnt) = cmd_result;
- last_scsi_command(shpnt)[ldn] = NO_SCSI;
- last_scsi_type(shpnt)[ldn] = 0;
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- } else if (last_scsi_command(shpnt)[ldn] == IM_ABORT_IMM_CMD) {
- /* react on SCSI abort command */
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
-#endif
- disk_rw_in_progress = 0;
- PS2_DISK_LED_OFF();
- cmd = ld(shpnt)[ldn].cmd;
- ld(shpnt)[ldn].cmd = NULL;
- if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
- cmd->result = DID_NO_CONNECT << 16;
- else
- cmd->result = DID_ABORT << 16;
- stat_result(shpnt) = cmd_result;
- last_scsi_command(shpnt)[ldn] = NO_SCSI;
- last_scsi_type(shpnt)[ldn] = 0;
- if (cmd->scsi_done)
- (cmd->scsi_done) (cmd); /* should be the internal_done */
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- } else {
- disk_rw_in_progress = 0;
- PS2_DISK_LED_OFF();
- reset_status(shpnt) = IM_RESET_FINISHED_OK;
- stat_result(shpnt) = cmd_result;
- last_scsi_command(shpnt)[ldn] = NO_SCSI;
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- }
- }
- last_scsi_command(shpnt)[ldn] = NO_SCSI;
- last_scsi_type(shpnt)[ldn] = 0;
- cmd = ld(shpnt)[ldn].cmd;
- ld(shpnt)[ldn].cmd = NULL;
-#ifdef IM_DEBUG_TIMEOUT
- if (cmd) {
- if ((cmd->target == TIMEOUT_PUN) && (cmd->device->lun == TIMEOUT_LUN)) {
- spin_unlock_irqsave(shpnt->host_lock, flags);
- printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->device->lun);
- return IRQ_HANDLED;
- }
- }
-#endif
- /*if no command structure, just return, else clear cmd */
- if (!cmd)
- {
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
- }
-
-#ifdef IM_DEBUG_INT
- printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(shpnt)[ldn].tsb.dev_status, ld(shpnt)[ldn].tsb.cmd_status, ld(shpnt)[ldn].tsb.dev_error, ld(shpnt)[ldn].tsb.cmd_error);
-#endif
- /*if this is end of media read/write, may turn off PS/2 disk led */
- if ((ld(shpnt)[ldn].device_type != TYPE_NO_LUN) && (ld(shpnt)[ldn].device_type != TYPE_NO_DEVICE)) {
- /* only access this, if there was a valid device addressed */
- if (--disk_rw_in_progress == 0)
- PS2_DISK_LED_OFF();
- }
-
- /* IBM describes the status-mask to be 0x1e, but this is not conform
- * with SCSI-definition, I suppose, the reason for it is that IBM
- * adapters do not support CMD_TERMINATED, TASK_SET_FULL and
- * ACA_ACTIVE as returning statusbyte information. (ML) */
- if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) {
- cmd->result = (unsigned char) (ld(shpnt)[ldn].tsb.dev_status & 0x1e);
- IBM_DS(shpnt).total_errors++;
- } else
- cmd->result = 0;
- /* write device status into cmd->result, and call done function */
- if (lastSCSI == NO_SCSI) { /* unexpected interrupt :-( */
- cmd->result |= DID_BAD_INTR << 16;
- printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n");
- } else /* things went right :-) */
- cmd->result |= DID_OK << 16;
- if (cmd->scsi_done)
- (cmd->scsi_done) (cmd);
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return IRQ_HANDLED;
-}
-
-static void issue_cmd(struct Scsi_Host *shpnt, unsigned long cmd_reg,
- unsigned char attn_reg)
-{
- unsigned long flags;
- /* must wait for attention reg not busy */
- while (1) {
- spin_lock_irqsave(shpnt->host_lock, flags);
- if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
- break;
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- }
- /* write registers and enable system interrupts */
- outl(cmd_reg, IM_CMD_REG(shpnt));
- outb(attn_reg, IM_ATTN_REG(shpnt));
- spin_unlock_irqrestore(shpnt->host_lock, flags);
-}
-
-static void internal_done(Scsi_Cmnd * cmd)
-{
- cmd->SCp.Status++;
- return;
-}
-
-/* SCSI-SCB-command for device_inquiry */
-static int device_inquiry(struct Scsi_Host *shpnt, int ldn)
-{
- int retr;
- struct im_scb *scb;
- struct im_tsb *tsb;
- unsigned char *buf;
-
- scb = &(ld(shpnt)[ldn].scb);
- tsb = &(ld(shpnt)[ldn].tsb);
- buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
- ld(shpnt)[ldn].tsb.dev_status = 0; /* prepare statusblock */
- for (retr = 0; retr < 3; retr++) {
- /* fill scb with inquiry command */
- scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT;
- scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
- last_scsi_command(shpnt)[ldn] = IM_DEVICE_INQUIRY_CMD;
- last_scsi_type(shpnt)[ldn] = IM_SCB;
- scb->sys_buf_adr = isa_virt_to_bus(buf);
- scb->sys_buf_length = 255; /* maximum bufferlength gives max info */
- scb->tsb_adr = isa_virt_to_bus(tsb);
- /* issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt(shpnt) = 0;
- issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
- while (!got_interrupt(shpnt))
- barrier();
-
- /*if command successful, break */
- if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
- return 1;
- }
- /*if all three retries failed, return "no device at this ldn" */
- if (retr >= 3)
- return 0;
- else
- return 1;
-}
-
-static int read_capacity(struct Scsi_Host *shpnt, int ldn)
-{
- int retr;
- struct im_scb *scb;
- struct im_tsb *tsb;
- unsigned char *buf;
-
- scb = &(ld(shpnt)[ldn].scb);
- tsb = &(ld(shpnt)[ldn].tsb);
- buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
- ld(shpnt)[ldn].tsb.dev_status = 0;
- for (retr = 0; retr < 3; retr++) {
- /*fill scb with read capacity command */
- scb->command = IM_READ_CAPACITY_CMD;
- scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
- last_scsi_command(shpnt)[ldn] = IM_READ_CAPACITY_CMD;
- last_scsi_type(shpnt)[ldn] = IM_SCB;
- scb->sys_buf_adr = isa_virt_to_bus(buf);
- scb->sys_buf_length = 8;
- scb->tsb_adr = isa_virt_to_bus(tsb);
- /*issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt(shpnt) = 0;
- issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
- while (!got_interrupt(shpnt))
- barrier();
-
- /*if got capacity, get block length and return one device found */
- if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
- return 1;
- }
- /*if all three retries failed, return "no device at this ldn" */
- if (retr >= 3)
- return 0;
- else
- return 1;
-}
-
-static int get_pos_info(struct Scsi_Host *shpnt)
-{
- int retr;
- struct im_scb *scb;
- struct im_tsb *tsb;
- unsigned char *buf;
-
- scb = &(ld(shpnt)[MAX_LOG_DEV].scb);
- tsb = &(ld(shpnt)[MAX_LOG_DEV].tsb);
- buf = (unsigned char *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
- ld(shpnt)[MAX_LOG_DEV].tsb.dev_status = 0;
- for (retr = 0; retr < 3; retr++) {
- /*fill scb with get_pos_info command */
- scb->command = IM_GET_POS_INFO_CMD;
- scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER;
- last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD;
- last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_SCB;
- scb->sys_buf_adr = isa_virt_to_bus(buf);
- if (special(shpnt) == IBM_SCSI2_FW)
- scb->sys_buf_length = 256; /* get all info from F/W adapter */
- else
- scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */
- scb->tsb_adr = isa_virt_to_bus(tsb);
- /*issue scb to ldn=15, and busy wait for interrupt */
- got_interrupt(shpnt) = 0;
- issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV);
-
- /* FIXME: timeout */
- while (!got_interrupt(shpnt))
- barrier();
-
- /*if got POS-stuff, get block length and return one device found */
- if ((stat_result(shpnt) == IM_SCB_CMD_COMPLETED) || (stat_result(shpnt) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
- return 1;
- }
- /* if all three retries failed, return "no device at this ldn" */
- if (retr >= 3)
- return 0;
- else
- return 1;
-}
-
-/* SCSI-immediate-command for assign. This functions maps/unmaps specific
- ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
- subsystem and for dynamical remapping od ldns. */
-static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
- unsigned int lun, unsigned int ldn,
- unsigned int operation)
-{
- int retr;
- unsigned long imm_cmd;
-
- for (retr = 0; retr < 3; retr++) {
- /* select mutation level of the SCSI-adapter */
- switch (special(shpnt)) {
- case IBM_SCSI2_FW:
- imm_cmd = (unsigned long) (IM_ASSIGN_IMM_CMD);
- imm_cmd |= (unsigned long) ((lun & 7) << 24);
- imm_cmd |= (unsigned long) ((operation & 1) << 23);
- imm_cmd |= (unsigned long) ((pun & 7) << 20) | ((pun & 8) << 24);
- imm_cmd |= (unsigned long) ((ldn & 15) << 16);
- break;
- default:
- imm_cmd = inl(IM_CMD_REG(shpnt));
- imm_cmd &= (unsigned long) (0xF8000000); /* keep reserved bits */
- imm_cmd |= (unsigned long) (IM_ASSIGN_IMM_CMD);
- imm_cmd |= (unsigned long) ((lun & 7) << 24);
- imm_cmd |= (unsigned long) ((operation & 1) << 23);
- imm_cmd |= (unsigned long) ((pun & 7) << 20);
- imm_cmd |= (unsigned long) ((ldn & 15) << 16);
- break;
- }
- last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD;
- last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
- got_interrupt(shpnt) = 0;
- issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
- while (!got_interrupt(shpnt))
- barrier();
-
- /*if command successful, break */
- if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
- return 1;
- }
- if (retr >= 3)
- return 0;
- else
- return 1;
-}
-
-static int immediate_feature(struct Scsi_Host *shpnt, unsigned int speed, unsigned int timeout)
-{
- int retr;
- unsigned long imm_cmd;
-
- for (retr = 0; retr < 3; retr++) {
- /* select mutation level of the SCSI-adapter */
- imm_cmd = IM_FEATURE_CTR_IMM_CMD;
- imm_cmd |= (unsigned long) ((speed & 0x7) << 29);
- imm_cmd |= (unsigned long) ((timeout & 0x1fff) << 16);
- last_scsi_command(shpnt)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD;
- last_scsi_type(shpnt)[MAX_LOG_DEV] = IM_IMM_CMD;
- got_interrupt(shpnt) = 0;
- /* we need to run into command errors in order to probe for the
- * right speed! */
- global_command_error_excuse = 1;
- issue_cmd(shpnt, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV);
-
- /* FIXME: timeout */
- while (!got_interrupt(shpnt))
- barrier();
- if (global_command_error_excuse == CMD_FAIL) {
- global_command_error_excuse = 0;
- return 2;
- } else
- global_command_error_excuse = 0;
- /*if command successful, break */
- if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
- return 1;
- }
- if (retr >= 3)
- return 0;
- else
- return 1;
-}
-
-#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
-static int immediate_reset(struct Scsi_Host *shpnt, unsigned int ldn)
-{
- int retries;
- int ticks;
- unsigned long imm_command;
-
- for (retries = 0; retries < 3; retries++) {
- imm_command = inl(IM_CMD_REG(shpnt));
- imm_command &= (unsigned long) (0xFFFF0000); /* keep reserved bits */
- imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
- last_scsi_command(shpnt)[ldn] = IM_RESET_IMM_CMD;
- last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
- got_interrupt(shpnt) = 0;
- reset_status(shpnt) = IM_RESET_IN_PROGRESS;
- issue_cmd(shpnt, (unsigned long) (imm_command), IM_IMM_CMD | ldn);
- ticks = IM_RESET_DELAY * HZ;
- while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks) {
- udelay((1 + 999 / HZ) * 1000);
- barrier();
- }
- /* if reset did not complete, just complain */
- if (!ticks) {
- printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
- reset_status(shpnt) = IM_RESET_FINISHED_OK;
- /* did not work, finish */
- return 1;
- }
- /*if command successful, break */
- if (stat_result(shpnt) == IM_IMMEDIATE_CMD_COMPLETED)
- return 1;
- }
- if (retries >= 3)
- return 0;
- else
- return 1;
-}
-#endif
-
-/* type-interpreter for physical device numbers */
-static char *ti_p(int dev)
-{
- switch (dev) {
- case TYPE_IBM_SCSI_ADAPTER:
- return ("A");
- case TYPE_DISK:
- return ("D");
- case TYPE_TAPE:
- return ("T");
- case TYPE_PROCESSOR:
- return ("P");
- case TYPE_WORM:
- return ("W");
- case TYPE_ROM:
- return ("R");
- case TYPE_SCANNER:
- return ("S");
- case TYPE_MOD:
- return ("M");
- case TYPE_MEDIUM_CHANGER:
- return ("C");
- case TYPE_NO_LUN:
- return ("+"); /* show NO_LUN */
- }
- return ("-"); /* TYPE_NO_DEVICE and others */
-}
-
-/* interpreter for logical device numbers (ldn) */
-static char *ti_l(int val)
-{
- const char hex[16] = "0123456789abcdef";
- static char answer[2];
-
- answer[1] = (char) (0x0);
- if (val <= MAX_LOG_DEV)
- answer[0] = hex[val];
- else
- answer[0] = '-';
- return (char *) &answer;
-}
-
-/* transfers bitpattern of the feature command to values in MHz */
-static char *ibmrate(unsigned int speed, int i)
-{
- switch (speed) {
- case 0:
- return i ? "5.00" : "10.00";
- case 1:
- return i ? "4.00" : "8.00";
- case 2:
- return i ? "3.33" : "6.66";
- case 3:
- return i ? "2.86" : "5.00";
- case 4:
- return i ? "2.50" : "4.00";
- case 5:
- return i ? "2.22" : "3.10";
- case 6:
- return i ? "2.00" : "2.50";
- case 7:
- return i ? "1.82" : "2.00";
- }
- return "---";
-}
-
-static int probe_display(int what)
-{
- static int rotator = 0;
- const char rotor[] = "|/-\\";
-
- if (!(display_mode & LED_DISP))
- return 0;
- if (!what) {
- outl(0x20202020, MOD95_LED_PORT);
- outl(0x20202020, MOD95_LED_PORT + 4);
- } else {
- outb('S', MOD95_LED_PORT + 7);
- outb('C', MOD95_LED_PORT + 6);
- outb('S', MOD95_LED_PORT + 5);
- outb('I', MOD95_LED_PORT + 4);
- outb('i', MOD95_LED_PORT + 3);
- outb('n', MOD95_LED_PORT + 2);
- outb('i', MOD95_LED_PORT + 1);
- outb((char) (rotor[rotator]), MOD95_LED_PORT);
- rotator++;
- if (rotator > 3)
- rotator = 0;
- }
- return 0;
-}
-
-static int probe_bus_mode(struct Scsi_Host *shpnt)
-{
- struct im_pos_info *info;
- int num_bus = 0;
- int ldn;
-
- info = (struct im_pos_info *) (&(ld(shpnt)[MAX_LOG_DEV].buf));
- if (get_pos_info(shpnt)) {
- if (info->connector_size & 0xf000)
- subsystem_connector_size(shpnt) = 16;
- else
- subsystem_connector_size(shpnt) = 32;
- num_bus |= (info->pos_4b & 8) >> 3;
- for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
- if ((special(shpnt) == IBM_SCSI_WCACHE) || (special(shpnt) == IBM_7568_WCACHE)) {
- if (!((info->cache_stat >> ldn) & 1))
- ld(shpnt)[ldn].cache_flag = 0;
- }
- if (!((info->retry_stat >> ldn) & 1))
- ld(shpnt)[ldn].retry_flag = 0;
- }
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: SCSI-Cache bits: ");
- for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
- printk("%d", ld(shpnt)[ldn].cache_flag);
- }
- printk("\nIBM MCA SCSI: SCSI-Retry bits: ");
- for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
- printk("%d", ld(shpnt)[ldn].retry_flag);
- }
- printk("\n");
-#endif
- }
- return num_bus;
-}
-
-/* probing scsi devices */
-static void check_devices(struct Scsi_Host *shpnt, int adaptertype)
-{
- int id, lun, ldn, ticks;
- int count_devices; /* local counter for connected device */
- int max_pun;
- int num_bus;
- int speedrun; /* local adapter_speed check variable */
-
- /* assign default values to certain variables */
- ticks = 0;
- count_devices = 0;
- IBM_DS(shpnt).dyn_flag = 0; /* normally no need for dynamical ldn management */
- IBM_DS(shpnt).total_errors = 0; /* set errorcounter to 0 */
- next_ldn(shpnt) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */
-
- /* initialize the very important driver-informational arrays/structs */
- memset(ld(shpnt), 0, sizeof(ld(shpnt)));
- for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) {
- last_scsi_command(shpnt)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */
- last_scsi_type(shpnt)[ldn] = 0;
- ld(shpnt)[ldn].cache_flag = 1;
- ld(shpnt)[ldn].retry_flag = 1;
- }
- memset(get_ldn(shpnt), TYPE_NO_DEVICE, sizeof(get_ldn(shpnt))); /* this is essential ! */
- memset(get_scsi(shpnt), TYPE_NO_DEVICE, sizeof(get_scsi(shpnt))); /* this is essential ! */
- for (lun = 0; lun < 8; lun++) {
- /* mark the adapter at its pun on all luns */
- get_scsi(shpnt)[subsystem_pun(shpnt)][lun] = TYPE_IBM_SCSI_ADAPTER;
- get_ldn(shpnt)[subsystem_pun(shpnt)][lun] = MAX_LOG_DEV; /* make sure, the subsystem
- ldn is active for all
- luns. */
- }
- probe_display(0); /* Supercool display usage during SCSI-probing. */
- /* This makes sense, when booting without any */
- /* monitor connected on model XX95. */
-
- /* STEP 1: */
- adapter_speed(shpnt) = global_adapter_speed;
- speedrun = adapter_speed(shpnt);
- while (immediate_feature(shpnt, speedrun, adapter_timeout) == 2) {
- probe_display(1);
- if (speedrun == 7)
- panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n");
- speedrun++;
- if (speedrun > 7)
- speedrun = 7;
- }
- adapter_speed(shpnt) = speedrun;
- /* Get detailed information about the current adapter, necessary for
- * device operations: */
- num_bus = probe_bus_mode(shpnt);
-
- /* num_bus contains only valid data for the F/W adapter! */
- if (adaptertype == IBM_SCSI2_FW) { /* F/W SCSI adapter: */
- /* F/W adapter PUN-space extension evaluation: */
- if (num_bus) {
- printk(KERN_INFO "IBM MCA SCSI: Separate bus mode (wide-addressing enabled)\n");
- subsystem_maxid(shpnt) = 16;
- } else {
- printk(KERN_INFO "IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n");
- subsystem_maxid(shpnt) = 8;
- }
- printk(KERN_INFO "IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", ibmrate(speedrun, adaptertype));
- } else /* all other IBM SCSI adapters: */
- printk(KERN_INFO "IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", ibmrate(speedrun, adaptertype));
-
- /* assign correct PUN device space */
- max_pun = subsystem_maxid(shpnt);
-
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: Current SCSI-host index: %d\n", shpnt);
- printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
-#else
- printk(KERN_INFO "IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", (ibm_ansi_order) ? "ANSI" : "New");
-#endif
- for (ldn = 0; ldn < MAX_LOG_DEV; ldn++) {
- probe_display(1);
-#ifdef IM_DEBUG_PROBE
- printk(".");
-#endif
- immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN); /* remove ldn (wherever) */
- }
- lun = 0; /* default lun is 0 */
-#ifndef IM_DEBUG_PROBE
- printk("cleared,");
-#endif
- /* STEP 2: */
-#ifdef IM_DEBUG_PROBE
- printk("\nIBM MCA SCSI: Scanning SCSI-devices.");
-#endif
- for (id = 0; id < max_pun; id++)
-#ifdef CONFIG_SCSI_MULTI_LUN
- for (lun = 0; lun < 8; lun++)
-#endif
- {
- probe_display(1);
-#ifdef IM_DEBUG_PROBE
- printk(".");
-#endif
- if (id != subsystem_pun(shpnt)) {
- /* if pun is not the adapter: */
- /* set ldn=0 to pun,lun */
- immediate_assign(shpnt, id, lun, PROBE_LDN, SET_LDN);
- if (device_inquiry(shpnt, PROBE_LDN)) { /* probe device */
- get_scsi(shpnt)[id][lun] = (unsigned char) (ld(shpnt)[PROBE_LDN].buf[0]);
- /* entry, even for NO_LUN */
- if (ld(shpnt)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
- count_devices++; /* a existing device is found */
- }
- /* remove ldn */
- immediate_assign(shpnt, id, lun, PROBE_LDN, REMOVE_LDN);
- }
- }
-#ifndef IM_DEBUG_PROBE
- printk("scanned,");
-#endif
- /* STEP 3: */
-#ifdef IM_DEBUG_PROBE
- printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
-#endif
- ldn = 0;
- lun = 0;
-#ifdef CONFIG_SCSI_MULTI_LUN
- for (lun = 0; lun < 8 && ldn < MAX_LOG_DEV; lun++)
-#endif
- for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) {
- probe_display(1);
-#ifdef IM_DEBUG_PROBE
- printk(".");
-#endif
- if (id != subsystem_pun(shpnt)) {
- if (get_scsi(shpnt)[id][lun] != TYPE_NO_LUN && get_scsi(shpnt)[id][lun] != TYPE_NO_DEVICE) {
- /* Only map if accepted type. Always enter for
- lun == 0 to get no gaps into ldn-mapping for ldn<7. */
- immediate_assign(shpnt, id, lun, ldn, SET_LDN);
- get_ldn(shpnt)[id][lun] = ldn; /* map ldn */
- if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
-#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
- printk("resetting device at ldn=%x ... ", ldn);
- immediate_reset(shpnt, ldn);
-#endif
- ldn++;
- } else {
- /* device vanished, probably because we don't know how to
- * handle it or because it has problems */
- if (lun > 0) {
- /* remove mapping */
- get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
- immediate_assign(shpnt, 0, 0, ldn, REMOVE_LDN);
- } else
- ldn++;
- }
- } else if (lun == 0) {
- /* map lun == 0, even if no device exists */
- immediate_assign(shpnt, id, lun, ldn, SET_LDN);
- get_ldn(shpnt)[id][lun] = ldn; /* map ldn */
- ldn++;
- }
- }
- }
- /* STEP 4: */
-
- /* map remaining ldns to non-existing devices */
- for (lun = 1; lun < 8 && ldn < MAX_LOG_DEV; lun++)
- for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) {
- if (get_scsi(shpnt)[id][lun] == TYPE_NO_LUN || get_scsi(shpnt)[id][lun] == TYPE_NO_DEVICE) {
- probe_display(1);
- /* Map remaining ldns only to NON-existing pun,lun
- combinations to make sure an inquiry will fail.
- For MULTI_LUN, it is needed to avoid adapter autonome
- SCSI-remapping. */
- immediate_assign(shpnt, id, lun, ldn, SET_LDN);
- get_ldn(shpnt)[id][lun] = ldn;
- ldn++;
- }
- }
-#ifndef IM_DEBUG_PROBE
- printk("mapped.");
-#endif
- printk("\n");
-#ifdef IM_DEBUG_PROBE
- if (ibm_ansi_order)
- printk("IBM MCA SCSI: Device order: IBM/ANSI (pun=7 is first).\n");
- else
- printk("IBM MCA SCSI: Device order: New Industry Standard (pun=0 is first).\n");
-#endif
-
-#ifdef IM_DEBUG_PROBE
- /* Show the physical and logical mapping during boot. */
- printk("IBM MCA SCSI: Determined SCSI-device-mapping:\n");
- printk(" Physical SCSI-Device Map Logical SCSI-Device Map\n");
- printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
- for (id = 0; id < max_pun; id++) {
- printk("%2d ", id);
- for (lun = 0; lun < 8; lun++)
- printk("%2s ", ti_p(get_scsi(shpnt)[id][lun]));
- printk(" %2d ", id);
- for (lun = 0; lun < 8; lun++)
- printk("%2s ", ti_l(get_ldn(shpnt)[id][lun]));
- printk("\n");
- }
-#endif
-
- /* assign total number of found SCSI-devices to the statistics struct */
- IBM_DS(shpnt).total_scsi_devices = count_devices;
-
- /* decide for output in /proc-filesystem, if the configuration of
- SCSI-devices makes dynamical reassignment of devices necessary */
- if (count_devices >= MAX_LOG_DEV)
- IBM_DS(shpnt).dyn_flag = 1; /* dynamical assignment is necessary */
- else
- IBM_DS(shpnt).dyn_flag = 0; /* dynamical assignment is not necessary */
-
- /* If no SCSI-devices are assigned, return 1 in order to cause message. */
- if (ldn == 0)
- printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
-
- /* reset the counters for statistics on the current adapter */
- IBM_DS(shpnt).scbs = 0;
- IBM_DS(shpnt).long_scbs = 0;
- IBM_DS(shpnt).total_accesses = 0;
- IBM_DS(shpnt).total_interrupts = 0;
- IBM_DS(shpnt).dynamical_assignments = 0;
- memset(IBM_DS(shpnt).ldn_access, 0x0, sizeof(IBM_DS(shpnt).ldn_access));
- memset(IBM_DS(shpnt).ldn_read_access, 0x0, sizeof(IBM_DS(shpnt).ldn_read_access));
- memset(IBM_DS(shpnt).ldn_write_access, 0x0, sizeof(IBM_DS(shpnt).ldn_write_access));
- memset(IBM_DS(shpnt).ldn_inquiry_access, 0x0, sizeof(IBM_DS(shpnt).ldn_inquiry_access));
- memset(IBM_DS(shpnt).ldn_modeselect_access, 0x0, sizeof(IBM_DS(shpnt).ldn_modeselect_access));
- memset(IBM_DS(shpnt).ldn_assignments, 0x0, sizeof(IBM_DS(shpnt).ldn_assignments));
- probe_display(0);
- return;
-}
-
-static int device_exists(struct Scsi_Host *shpnt, int ldn, int *block_length, int *device_type)
-{
- unsigned char *buf;
- /* if no valid device found, return immediately with 0 */
- if (!(device_inquiry(shpnt, ldn)))
- return 0;
- buf = (unsigned char *) (&(ld(shpnt)[ldn].buf));
- if (*buf == TYPE_ROM) {
- *device_type = TYPE_ROM;
- *block_length = 2048; /* (standard blocksize for yellow-/red-book) */
- return 1;
- }
- if (*buf == TYPE_WORM) {
- *device_type = TYPE_WORM;
- *block_length = 2048;
- return 1;
- }
- if (*buf == TYPE_DISK) {
- *device_type = TYPE_DISK;
- if (read_capacity(shpnt, ldn)) {
- *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
- return 1;
- } else
- return 0;
- }
- if (*buf == TYPE_MOD) {
- *device_type = TYPE_MOD;
- if (read_capacity(shpnt, ldn)) {
- *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24);
- return 1;
- } else
- return 0;
- }
- if (*buf == TYPE_TAPE) {
- *device_type = TYPE_TAPE;
- *block_length = 0; /* not in use (setting by mt and mtst in op.) */
- return 1;
- }
- if (*buf == TYPE_PROCESSOR) {
- *device_type = TYPE_PROCESSOR;
- *block_length = 0; /* they set their stuff on drivers */
- return 1;
- }
- if (*buf == TYPE_SCANNER) {
- *device_type = TYPE_SCANNER;
- *block_length = 0; /* they set their stuff on drivers */
- return 1;
- }
- if (*buf == TYPE_MEDIUM_CHANGER) {
- *device_type = TYPE_MEDIUM_CHANGER;
- *block_length = 0; /* One never knows, what to expect on a medium
- changer device. */
- return 1;
- }
- return 0;
-}
-
-static void internal_ibmmca_scsi_setup(char *str, int *ints)
-{
- int i, j, io_base, id_base;
- char *token;
-
- io_base = 0;
- id_base = 0;
- if (str) {
- j = 0;
- while ((token = strsep(&str, ",")) != NULL) {
- if (!strcmp(token, "activity"))
- display_mode |= LED_ACTIVITY;
- if (!strcmp(token, "display"))
- display_mode |= LED_DISP;
- if (!strcmp(token, "adisplay"))
- display_mode |= LED_ADISP;
- if (!strcmp(token, "normal"))
- ibm_ansi_order = 0;
- if (!strcmp(token, "ansi"))
- ibm_ansi_order = 1;
- if (!strcmp(token, "fast"))
- global_adapter_speed = 0;
- if (!strcmp(token, "medium"))
- global_adapter_speed = 4;
- if (!strcmp(token, "slow"))
- global_adapter_speed = 7;
- if ((*token == '-') || (isdigit(*token))) {
- if (!(j % 2) && (io_base < IM_MAX_HOSTS))
- io_port[io_base++] = simple_strtoul(token, NULL, 0);
- if ((j % 2) && (id_base < IM_MAX_HOSTS))
- scsi_id[id_base++] = simple_strtoul(token, NULL, 0);
- j++;
- }
- }
- } else if (ints) {
- for (i = 0; i < IM_MAX_HOSTS && 2 * i + 2 < ints[0]; i++) {
- io_port[i] = ints[2 * i + 2];
- scsi_id[i] = ints[2 * i + 2];
- }
- }
- return;
-}
-
-#if 0
- FIXME NEED TO MOVE TO SYSFS
-
-static int ibmmca_getinfo(char *buf, int slot, void *dev_id)
-{
- struct Scsi_Host *shpnt;
- int len, speciale, connectore, k;
- unsigned int pos[8];
- unsigned long flags;
- struct Scsi_Host *dev = dev_id;
-
- spin_lock_irqsave(dev->host_lock, flags);
-
- shpnt = dev; /* assign host-structure to local pointer */
- len = 0; /* set filled text-buffer index to 0 */
- /* get the _special contents of the hostdata structure */
- speciale = ((struct ibmmca_hostdata *) shpnt->hostdata)->_special;
- connectore = ((struct ibmmca_hostdata *) shpnt->hostdata)->_connector_size;
- for (k = 2; k < 4; k++)
- pos[k] = ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k];
- if (speciale == FORCED_DETECTION) { /* forced detection */
- len += sprintf(buf + len,
- "Adapter category: forced detected\n" "***************************************\n" "*** Forced detected SCSI Adapter ***\n" "*** No chip-information available ***\n" "***************************************\n");
- } else if (speciale == INTEGRATED_SCSI) {
- /* if the integrated subsystem has been found automatically: */
- len += sprintf(buf + len,
- "Adapter category: integrated\n" "Chip revision level: %d\n" "Chip status: %s\n" "8 kByte NVRAM status: %s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 1) ? "enabled" : "disabled", (pos[2] & 2) ? "locked" : "accessible");
- } else if ((speciale >= 0) && (speciale < ARRAY_SIZE(subsys_list))) {
- /* if the subsystem is a slot adapter */
- len += sprintf(buf + len, "Adapter category: slot-card\n" "ROM Segment Address: ");
- if ((pos[2] & 0xf0) == 0xf0)
- len += sprintf(buf + len, "off\n");
- else
- len += sprintf(buf + len, "0x%x\n", ((pos[2] & 0xf0) << 13) + 0xc0000);
- len += sprintf(buf + len, "Chip status: %s\n", (pos[2] & 1) ? "enabled" : "disabled");
- len += sprintf(buf + len, "Adapter I/O Offset: 0x%x\n", ((pos[2] & 0x0e) << 2));
- } else {
- len += sprintf(buf + len, "Adapter category: unknown\n");
- }
- /* common subsystem information to write to the slotn file */
- len += sprintf(buf + len, "Subsystem PUN: %d\n", shpnt->this_id);
- len += sprintf(buf + len, "I/O base address range: 0x%x-0x%x\n", (unsigned int) (shpnt->io_port), (unsigned int) (shpnt->io_port + 7));
- len += sprintf(buf + len, "MCA-slot size: %d bits", connectore);
- /* Now make sure, the bufferlength is devidable by 4 to avoid
- * paging problems of the buffer. */
- while (len % sizeof(int) != (sizeof(int) - 1))
- len += sprintf(buf + len, " ");
- len += sprintf(buf + len, "\n");
-
- spin_unlock_irqrestore(shpnt->host_lock, flags);
-
- return len;
-}
-#endif
-
-static struct scsi_host_template ibmmca_driver_template = {
- .proc_name = "ibmmca",
- .proc_info = ibmmca_proc_info,
- .name = "IBM SCSI-Subsystem",
- .queuecommand = ibmmca_queuecommand,
- .eh_abort_handler = ibmmca_abort,
- .eh_host_reset_handler = ibmmca_host_reset,
- .bios_param = ibmmca_biosparam,
- .can_queue = 16,
- .this_id = 7,
- .sg_tablesize = 16,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
-};
-
-static int ibmmca_probe(struct device *dev)
-{
- struct Scsi_Host *shpnt;
- int port, id, i, j, k, irq, enabled, ret = -EINVAL;
- struct mca_device *mca_dev = to_mca_device(dev);
- const char *description = ibmmca_description[mca_dev->index];
-
- /* First of all, print the version number of the driver. This is
- * important to allow better user bugreports in case of already
- * having problems with the MCA_bus probing. */
- printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION);
- /* The POS2-register of all PS/2 model SCSI-subsystems has the following
- * interpretation of bits:
- * Bit 7 - 4 : Chip Revision ID (Release)
- * Bit 3 - 2 : Reserved
- * Bit 1 : 8k NVRAM Disabled
- * Bit 0 : Chip Enable (EN-Signal)
- * The POS3-register is interpreted as follows:
- * Bit 7 - 5 : SCSI ID
- * Bit 4 : Reserved = 0
- * Bit 3 - 0 : Reserved = 0
- * (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common
- * Interfaces (1991)").
- * In short words, this means, that IBM PS/2 machines only support
- * 1 single subsystem by default. The slot-adapters must have another
- * configuration on pos2. Here, one has to assume the following
- * things for POS2-register:
- * Bit 7 - 4 : Chip Revision ID (Release)
- * Bit 3 - 1 : port offset factor
- * Bit 0 : Chip Enable (EN-Signal)
- * As I found a patch here, setting the IO-registers to 0x3540 forced,
- * as there was a 0x05 in POS2 on a model 56, I assume, that the
- * port 0x3540 must be fix for integrated SCSI-controllers.
- * Ok, this discovery leads to the following implementation: (M.Lang) */
-
- /* first look for the IBM SCSI integrated subsystem on the motherboard */
- for (j = 0; j < 8; j++) /* read the pos-information */
- pos[j] = mca_device_read_pos(mca_dev, j);
- id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
- enabled = (pos[2] &0x01);
- if (!enabled) {
- printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
- printk(KERN_WARNING " SCSI-operations may not work.\n");
- }
-
- /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but
- * if we ignore the settings of all surrounding pos registers, it is not
- * completely sufficient to only check pos2 and pos3. */
- /* Therefore, now the following if statement is used to
- * make sure, we see a real integrated onboard SCSI-interface and no
- * internal system information, which gets mapped to some pos registers
- * on models 95xx. */
- if (mca_dev->slot == MCA_INTEGSCSI &&
- ((!pos[0] && !pos[1] && pos[2] > 0 &&
- pos[3] > 0 && !pos[4] && !pos[5] &&
- !pos[6] && !pos[7]) ||
- (pos[0] == 0xff && pos[1] == 0xff &&
- pos[2] < 0xff && pos[3] < 0xff &&
- pos[4] == 0xff && pos[5] == 0xff &&
- pos[6] == 0xff && pos[7] == 0xff))) {
- irq = IM_IRQ;
- port = IM_IO_PORT;
- } else {
- irq = IM_IRQ;
- port = IM_IO_PORT + ((pos[2] &0x0e) << 2);
- if ((mca_dev->index == IBM_SCSI2_FW) && (pos[6] != 0)) {
- printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n");
- printk(KERN_ERR " Impossible to determine adapter PUN!\n");
- printk(KERN_ERR " Guessing adapter PUN = 7.\n");
- id = 7;
- } else {
- id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */
- if (mca_dev->index == IBM_SCSI2_FW) {
- id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit
- * for F/W adapters */
- }
- }
- if ((mca_dev->index == IBM_SCSI2_FW) &&
- (pos[4] & 0x01) && (pos[6] == 0)) {
- /* IRQ11 is used by SCSI-2 F/W Adapter/A */
- printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n");
- irq = IM_IRQ_FW;
- }
- }
-
-
-
- /* give detailed information on the subsystem. This helps me
- * additionally during debugging and analyzing bug-reports. */
- printk(KERN_INFO "IBM MCA SCSI: %s found, io=0x%x, scsi id=%d,\n",
- description, port, id);
- if (mca_dev->slot == MCA_INTEGSCSI)
- printk(KERN_INFO " chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled.");
- else {
- if ((pos[2] & 0xf0) == 0xf0)
- printk(KERN_DEBUG " ROM Addr.=off,");
- else
- printk(KERN_DEBUG " ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000);
-
- printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled.");
- }
-
- /* check I/O region */
- if (!request_region(port, IM_N_IO_PORT, description)) {
- printk(KERN_ERR "IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);
- goto out_fail;
- }
-
- /* register host */
- shpnt = scsi_host_alloc(&ibmmca_driver_template,
- sizeof(struct ibmmca_hostdata));
- if (!shpnt) {
- printk(KERN_ERR "IBM MCA SCSI: Unable to register host.\n");
- goto out_release;
- }
-
- dev_set_drvdata(dev, shpnt);
- if(request_irq(irq, interrupt_handler, IRQF_SHARED, description, dev)) {
- printk(KERN_ERR "IBM MCA SCSI: failed to request interrupt %d\n", irq);
- goto out_free_host;
- }
-
- /* request I/O region */
- special(shpnt) = mca_dev->index; /* important assignment or else crash! */
- subsystem_connector_size(shpnt) = 0; /* preset slot-size */
- shpnt->irq = irq; /* assign necessary stuff for the adapter */
- shpnt->io_port = port;
- shpnt->n_io_port = IM_N_IO_PORT;
- shpnt->this_id = id;
- shpnt->max_id = 8; /* 8 PUNs are default */
- /* now, the SCSI-subsystem is connected to Linux */
-
-#ifdef IM_DEBUG_PROBE
- ctrl = (unsigned int) (inb(IM_CTR_REG(found))); /* get control-register status */
- printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl, inb(IM_STAT_REG(found)));
- printk("IBM MCA SCSI: This adapters' POS-registers: ");
- for (i = 0; i < 8; i++)
- printk("%x ", pos[i]);
- printk("\n");
-#endif
- reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS;
-
- for (i = 0; i < 16; i++) /* reset the tables */
- for (j = 0; j < 8; j++)
- get_ldn(shpnt)[i][j] = MAX_LOG_DEV;
-
- /* check which logical devices exist */
- /* after this line, local interrupting is possible: */
- local_checking_phase_flag(shpnt) = 1;
- check_devices(shpnt, mca_dev->index); /* call by value, using the global variable hosts */
- local_checking_phase_flag(shpnt) = 0;
-
- /* an ibm mca subsystem has been detected */
-
- for (k = 2; k < 7; k++)
- ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k];
- ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI;
- mca_device_set_name(mca_dev, description);
- /* FIXME: NEED TO REPLUMB TO SYSFS
- mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt);
- */
- mca_device_set_claim(mca_dev, 1);
- if (scsi_add_host(shpnt, dev)) {
- dev_printk(KERN_ERR, dev, "IBM MCA SCSI: scsi_add_host failed\n");
- goto out_free_host;
- }
- scsi_scan_host(shpnt);
-
- return 0;
- out_free_host:
- scsi_host_put(shpnt);
- out_release:
- release_region(port, IM_N_IO_PORT);
- out_fail:
- return ret;
-}
-
-static int __devexit ibmmca_remove(struct device *dev)
-{
- struct Scsi_Host *shpnt = dev_get_drvdata(dev);
- scsi_remove_host(shpnt);
- release_region(shpnt->io_port, shpnt->n_io_port);
- free_irq(shpnt->irq, dev);
- scsi_host_put(shpnt);
- return 0;
-}
-
-/* The following routine is the SCSI command queue for the midlevel driver */
-static int ibmmca_queuecommand_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
-{
- unsigned int ldn;
- unsigned int scsi_cmd;
- struct im_scb *scb;
- struct Scsi_Host *shpnt;
- int current_ldn;
- int id, lun;
- int target;
- int max_pun;
- int i;
- struct scatterlist *sg;
-
- shpnt = cmd->device->host;
-
- max_pun = subsystem_maxid(shpnt);
- if (ibm_ansi_order) {
- target = max_pun - 1 - cmd->device->id;
- if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
- target--;
- else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
- target++;
- } else
- target = cmd->device->id;
-
- /* if (target,lun) is NO LUN or not existing at all, return error */
- if ((get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_LUN) || (get_scsi(shpnt)[target][cmd->device->lun] == TYPE_NO_DEVICE)) {
- cmd->result = DID_NO_CONNECT << 16;
- if (done)
- done(cmd);
- return 0;
- }
-
- /*if (target,lun) unassigned, do further checks... */
- ldn = get_ldn(shpnt)[target][cmd->device->lun];
- if (ldn >= MAX_LOG_DEV) { /* on invalid ldn do special stuff */
- if (ldn > MAX_LOG_DEV) { /* dynamical remapping if ldn unassigned */
- current_ldn = next_ldn(shpnt); /* stop-value for one circle */
- while (ld(shpnt)[next_ldn(shpnt)].cmd) { /* search for a occupied, but not in */
- /* command-processing ldn. */
- next_ldn(shpnt)++;
- if (next_ldn(shpnt) >= MAX_LOG_DEV)
- next_ldn(shpnt) = 7;
- if (current_ldn == next_ldn(shpnt)) { /* One circle done ? */
- /* no non-processing ldn found */
- scmd_printk(KERN_WARNING, cmd,
- "IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n"
- " On ldn 7-14 SCSI-commands everywhere in progress.\n"
- " Reporting DID_NO_CONNECT for device.\n");
- cmd->result = DID_NO_CONNECT << 16; /* return no connect */
- if (done)
- done(cmd);
- return 0;
- }
- }
-
- /* unmap non-processing ldn */
- for (id = 0; id < max_pun; id++)
- for (lun = 0; lun < 8; lun++) {
- if (get_ldn(shpnt)[id][lun] == next_ldn(shpnt)) {
- get_ldn(shpnt)[id][lun] = TYPE_NO_DEVICE;
- get_scsi(shpnt)[id][lun] = TYPE_NO_DEVICE;
- /* unmap entry */
- }
- }
- /* set reduced interrupt_handler-mode for checking */
- local_checking_phase_flag(shpnt) = 1;
- /* map found ldn to pun,lun */
- get_ldn(shpnt)[target][cmd->device->lun] = next_ldn(shpnt);
- /* change ldn to the right value, that is now next_ldn */
- ldn = next_ldn(shpnt);
- /* unassign all ldns (pun,lun,ldn does not matter for remove) */
- immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
- /* set only LDN for remapped device */
- immediate_assign(shpnt, target, cmd->device->lun, ldn, SET_LDN);
- /* get device information for ld[ldn] */
- if (device_exists(shpnt, ldn, &ld(shpnt)[ldn].block_length, &ld(shpnt)[ldn].device_type)) {
- ld(shpnt)[ldn].cmd = NULL; /* To prevent panic set 0, because
- devices that were not assigned,
- should have nothing in progress. */
- get_scsi(shpnt)[target][cmd->device->lun] = ld(shpnt)[ldn].device_type;
- /* increase assignment counters for statistics in /proc */
- IBM_DS(shpnt).dynamical_assignments++;
- IBM_DS(shpnt).ldn_assignments[ldn]++;
- } else
- /* panic here, because a device, found at boottime has
- vanished */
- panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->device->lun);
- /* unassign again all ldns (pun,lun,ldn does not matter for remove) */
- immediate_assign(shpnt, 0, 0, 0, REMOVE_LDN);
- /* remap all ldns, as written in the pun/lun table */
- lun = 0;
-#ifdef CONFIG_SCSI_MULTI_LUN
- for (lun = 0; lun < 8; lun++)
-#endif
- for (id = 0; id < max_pun; id++) {
- if (get_ldn(shpnt)[id][lun] <= MAX_LOG_DEV)
- immediate_assign(shpnt, id, lun, get_ldn(shpnt)[id][lun], SET_LDN);
- }
- /* set back to normal interrupt_handling */
- local_checking_phase_flag(shpnt) = 0;
-#ifdef IM_DEBUG_PROBE
- /* Information on syslog terminal */
- printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->device->lun);
-#endif
- /* increase next_ldn for next dynamical assignment */
- next_ldn(shpnt)++;
- if (next_ldn(shpnt) >= MAX_LOG_DEV)
- next_ldn(shpnt) = 7;
- } else { /* wall against Linux accesses to the subsystem adapter */
- cmd->result = DID_BAD_TARGET << 16;
- if (done)
- done(cmd);
- return 0;
- }
- }
-
- /*verify there is no command already in progress for this log dev */
- if (ld(shpnt)[ldn].cmd)
- panic("IBM MCA SCSI: cmd already in progress for this ldn.\n");
-
- /*save done in cmd, and save cmd for the interrupt handler */
- cmd->scsi_done = done;
- ld(shpnt)[ldn].cmd = cmd;
-
- /*fill scb information independent of the scsi command */
- scb = &(ld(shpnt)[ldn].scb);
- ld(shpnt)[ldn].tsb.dev_status = 0;
- scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE;
- scb->tsb_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].tsb));
- scsi_cmd = cmd->cmnd[0];
-
- if (scsi_sg_count(cmd)) {
- BUG_ON(scsi_sg_count(cmd) > 16);
-
- scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) {
- ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg_page(sg)) + sg->offset);
- ld(shpnt)[ldn].sge[i].byte_length = sg->length;
- }
- scb->enable |= IM_POINTER_TO_LIST;
- scb->sys_buf_adr = isa_virt_to_bus(&(ld(shpnt)[ldn].sge[0]));
- scb->sys_buf_length = scsi_sg_count(cmd) * sizeof(struct im_sge);
- } else {
- scb->sys_buf_adr = isa_virt_to_bus(scsi_sglist(cmd));
- /* recent Linux midlevel SCSI places 1024 byte for inquiry
- * command. Far too much for old PS/2 hardware. */
- switch (scsi_cmd) {
- /* avoid command errors by setting bufferlengths to
- * ANSI-standard. Beware of forcing it to 255,
- * this could SEGV the kernel!!! */
- case INQUIRY:
- case REQUEST_SENSE:
- case MODE_SENSE:
- case MODE_SELECT:
- if (scsi_bufflen(cmd) > 255)
- scb->sys_buf_length = 255;
- else
- scb->sys_buf_length = scsi_bufflen(cmd);
- break;
- case TEST_UNIT_READY:
- scb->sys_buf_length = 0;
- break;
- default:
- scb->sys_buf_length = scsi_bufflen(cmd);
- break;
- }
- }
- /*fill scb information dependent on scsi command */
-
-#ifdef IM_DEBUG_CMD
- printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
-#endif
-
- /* for specific device-type debugging: */
-#ifdef IM_DEBUG_CMD_SPEC_DEV
- if (ld(shpnt)[ldn].device_type == IM_DEBUG_CMD_DEVICE)
- printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(shpnt)[ldn].device_type, scsi_cmd, ldn);
-#endif
-
- /* for possible panics store current command */
- last_scsi_command(shpnt)[ldn] = scsi_cmd;
- last_scsi_type(shpnt)[ldn] = IM_SCB;
- /* update statistical info */
- IBM_DS(shpnt).total_accesses++;
- IBM_DS(shpnt).ldn_access[ldn]++;
-
- switch (scsi_cmd) {
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- /* Distinguish between disk and other devices. Only disks (that are the
- most frequently accessed devices) should be supported by the
- IBM-SCSI-Subsystem commands. */
- switch (ld(shpnt)[ldn].device_type) {
- case TYPE_DISK: /* for harddisks enter here ... */
- case TYPE_MOD: /* ... try it also for MO-drives (send flames as */
- /* you like, if this won't work.) */
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) {
- /* read command preparations */
- scb->enable |= IM_READ_CONTROL;
- IBM_DS(shpnt).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */
- scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT;
- } else { /* write command preparations */
- IBM_DS(shpnt).ldn_write_access[ldn]++; /* increase write-count on ldn stat. */
- scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT;
- }
- if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) {
- scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) | (((unsigned) cmd->cmnd[2]) << 8) | ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16);
- scb->u2.blk.count = (unsigned) cmd->cmnd[4];
- } else {
- scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24);
- scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8);
- }
- last_scsi_logical_block(shpnt)[ldn] = scb->u1.log_blk_adr;
- last_scsi_blockcount(shpnt)[ldn] = scb->u2.blk.count;
- scb->u2.blk.length = ld(shpnt)[ldn].block_length;
- break;
- /* for other devices, enter here. Other types are not known by
- Linux! TYPE_NO_LUN is forbidden as valid device. */
- case TYPE_ROM:
- case TYPE_TAPE:
- case TYPE_PROCESSOR:
- case TYPE_WORM:
- case TYPE_SCANNER:
- case TYPE_MEDIUM_CHANGER:
- /* If there is a sequential-device, IBM recommends to use
- IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE.
- This includes CD-ROM devices, too, due to the partial sequential
- read capabilities. */
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12)
- /* enable READ */
- scb->enable |= IM_READ_CONTROL;
- scb->enable |= IM_BYPASS_BUFFER;
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
- last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
- /* Read/write on this non-disk devices is also displayworthy,
- so flash-up the LED/display. */
- break;
- }
- break;
- case INQUIRY:
- IBM_DS(shpnt).ldn_inquiry_access[ldn]++;
- scb->command = IM_DEVICE_INQUIRY_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
- scb->u1.log_blk_adr = 0;
- break;
- case TEST_UNIT_READY:
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
- scb->u1.log_blk_adr = 0;
- scb->u1.scsi_cmd_length = 6;
- memcpy(scb->u2.scsi_command, cmd->cmnd, 6);
- last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
- break;
- case READ_CAPACITY:
- /* the length of system memory buffer must be exactly 8 bytes */
- scb->command = IM_READ_CAPACITY_CMD;
- scb->enable |= IM_READ_CONTROL | IM_BYPASS_BUFFER;
- if (scb->sys_buf_length > 8)
- scb->sys_buf_length = 8;
- break;
- /* Commands that need read-only-mode (system <- device): */
- case REQUEST_SENSE:
- scb->command = IM_REQUEST_SENSE_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
- break;
- /* Commands that need write-only-mode (system -> device): */
- case MODE_SELECT:
- case MODE_SELECT_10:
- IBM_DS(shpnt).ldn_modeselect_access[ldn]++;
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; /*Select needs WRITE-enabled */
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
- last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
- break;
- /* For other commands, read-only is useful. Most other commands are
- running without an input-data-block. */
- default:
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER;
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
- last_scsi_type(shpnt)[ldn] = IM_LONG_SCB;
- break;
- }
- /*issue scb command, and return */
- if (++disk_rw_in_progress == 1)
- PS2_DISK_LED_ON(shpnt->host_no, target);
-
- if (last_scsi_type(shpnt)[ldn] == IM_LONG_SCB) {
- issue_cmd(shpnt, isa_virt_to_bus(scb), IM_LONG_SCB | ldn);
- IBM_DS(shpnt).long_scbs++;
- } else {
- issue_cmd(shpnt, isa_virt_to_bus(scb), IM_SCB | ldn);
- IBM_DS(shpnt).scbs++;
- }
- return 0;
-}
-
-static DEF_SCSI_QCMD(ibmmca_queuecommand)
-
-static int __ibmmca_abort(Scsi_Cmnd * cmd)
-{
- /* Abort does not work, as the adapter never generates an interrupt on
- * whatever situation is simulated, even when really pending commands
- * are running on the adapters' hardware ! */
-
- struct Scsi_Host *shpnt;
- unsigned int ldn;
- void (*saved_done) (Scsi_Cmnd *);
- int target;
- int max_pun;
- unsigned long imm_command;
-
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: Abort subroutine called...\n");
-#endif
-
- shpnt = cmd->device->host;
-
- max_pun = subsystem_maxid(shpnt);
- if (ibm_ansi_order) {
- target = max_pun - 1 - cmd->device->id;
- if ((target <= subsystem_pun(shpnt)) && (cmd->device->id <= subsystem_pun(shpnt)))
- target--;
- else if ((target >= subsystem_pun(shpnt)) && (cmd->device->id >= subsystem_pun(shpnt)))
- target++;
- } else
- target = cmd->device->id;
-
- /* get logical device number, and disable system interrupts */
- printk(KERN_WARNING "IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->device->lun);
- ldn = get_ldn(shpnt)[target][cmd->device->lun];
-
- /*if cmd for this ldn has already finished, no need to abort */
- if (!ld(shpnt)[ldn].cmd) {
- return SUCCESS;
- }
-
- /* Clear ld.cmd, save done function, install internal done,
- * send abort immediate command (this enables sys. interrupts),
- * and wait until the interrupt arrives.
- */
- saved_done = cmd->scsi_done;
- cmd->scsi_done = internal_done;
- cmd->SCp.Status = 0;
- last_scsi_command(shpnt)[ldn] = IM_ABORT_IMM_CMD;
- last_scsi_type(shpnt)[ldn] = IM_IMM_CMD;
- imm_command = inl(IM_CMD_REG(shpnt));
- imm_command &= (unsigned long) (0xffff0000); /* mask reserved stuff */
- imm_command |= (unsigned long) (IM_ABORT_IMM_CMD);
- /* must wait for attention reg not busy */
- /* FIXME - timeout, politeness */
- while (1) {
- if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
- break;
- }
- /* write registers and enable system interrupts */
- outl(imm_command, IM_CMD_REG(shpnt));
- outb(IM_IMM_CMD | ldn, IM_ATTN_REG(shpnt));
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: Abort queued to adapter...\n");
-#endif
- spin_unlock_irq(shpnt->host_lock);
- while (!cmd->SCp.Status)
- yield();
- spin_lock_irq(shpnt->host_lock);
- cmd->scsi_done = saved_done;
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: Abort returned with adapter response...\n");
-#endif
-
- /*if abort went well, call saved done, then return success or error */
- if (cmd->result == (DID_ABORT << 16))
- {
- cmd->result |= DID_ABORT << 16;
- if (cmd->scsi_done)
- (cmd->scsi_done) (cmd);
- ld(shpnt)[ldn].cmd = NULL;
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: Abort finished with success.\n");
-#endif
- return SUCCESS;
- } else {
- cmd->result |= DID_NO_CONNECT << 16;
- if (cmd->scsi_done)
- (cmd->scsi_done) (cmd);
- ld(shpnt)[ldn].cmd = NULL;
-#ifdef IM_DEBUG_PROBE
- printk("IBM MCA SCSI: Abort failed.\n");
-#endif
- return FAILED;
- }
-}
-
-static int ibmmca_abort(Scsi_Cmnd * cmd)
-{
- struct Scsi_Host *shpnt = cmd->device->host;
- int rc;
-
- spin_lock_irq(shpnt->host_lock);
- rc = __ibmmca_abort(cmd);
- spin_unlock_irq(shpnt->host_lock);
-
- return rc;
-}
-
-static int __ibmmca_host_reset(Scsi_Cmnd * cmd)
-{
- struct Scsi_Host *shpnt;
- Scsi_Cmnd *cmd_aid;
- int ticks, i;
- unsigned long imm_command;
-
- BUG_ON(cmd == NULL);
-
- ticks = IM_RESET_DELAY * HZ;
- shpnt = cmd->device->host;
-
- if (local_checking_phase_flag(shpnt)) {
- printk(KERN_WARNING "IBM MCA SCSI: unable to reset while checking devices.\n");
- return FAILED;
- }
-
- /* issue reset immediate command to subsystem, and wait for interrupt */
- printk("IBM MCA SCSI: resetting all devices.\n");
- reset_status(shpnt) = IM_RESET_IN_PROGRESS;
- last_scsi_command(shpnt)[0xf] = IM_RESET_IMM_CMD;
- last_scsi_type(shpnt)[0xf] = IM_IMM_CMD;
- imm_command = inl(IM_CMD_REG(shpnt));
- imm_command &= (unsigned long) (0xffff0000); /* mask reserved stuff */
- imm_command |= (unsigned long) (IM_RESET_IMM_CMD);
- /* must wait for attention reg not busy */
- while (1) {
- if (!(inb(IM_STAT_REG(shpnt)) & IM_BUSY))
- break;
- spin_unlock_irq(shpnt->host_lock);
- yield();
- spin_lock_irq(shpnt->host_lock);
- }
- /*write registers and enable system interrupts */
- outl(imm_command, IM_CMD_REG(shpnt));
- outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(shpnt));
- /* wait for interrupt finished or intr_stat register to be set, as the
- * interrupt will not be executed, while we are in here! */
-
- /* FIXME: This is really really icky we so want a sleeping version of this ! */
- while (reset_status(shpnt) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(shpnt)) & 0x8f) != 0x8f)) {
- udelay((1 + 999 / HZ) * 1000);
- barrier();
- }
- /* if reset did not complete, just return an error */
- if (!ticks) {
- printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY);
- reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
- return FAILED;
- }
-
- if ((inb(IM_INTR_REG(shpnt)) & 0x8f) == 0x8f) {
- /* analysis done by this routine and not by the intr-routine */
- if (inb(IM_INTR_REG(shpnt)) == 0xaf)
- reset_status(shpnt) = IM_RESET_FINISHED_OK_NO_INT;
- else if (inb(IM_INTR_REG(shpnt)) == 0xcf)
- reset_status(shpnt) = IM_RESET_FINISHED_FAIL;
- else /* failed, 4get it */
- reset_status(shpnt) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
- outb(IM_EOI | 0xf, IM_ATTN_REG(shpnt));
- }
-
- /* if reset failed, just return an error */
- if (reset_status(shpnt) == IM_RESET_FINISHED_FAIL) {
- printk(KERN_ERR "IBM MCA SCSI: reset failed.\n");
- return FAILED;
- }
-
- /* so reset finished ok - call outstanding done's, and return success */
- printk(KERN_INFO "IBM MCA SCSI: Reset successfully completed.\n");
- for (i = 0; i < MAX_LOG_DEV; i++) {
- cmd_aid = ld(shpnt)[i].cmd;
- if (cmd_aid && cmd_aid->scsi_done) {
- ld(shpnt)[i].cmd = NULL;
- cmd_aid->result = DID_RESET << 16;
- }
- }
- return SUCCESS;
-}
-
-static int ibmmca_host_reset(Scsi_Cmnd * cmd)
-{
- struct Scsi_Host *shpnt = cmd->device->host;
- int rc;
-
- spin_lock_irq(shpnt->host_lock);
- rc = __ibmmca_host_reset(cmd);
- spin_unlock_irq(shpnt->host_lock);
-
- return rc;
-}
-
-static int ibmmca_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *info)
-{
- int size = capacity;
- info[0] = 64;
- info[1] = 32;
- info[2] = size / (info[0] * info[1]);
- if (info[2] >= 1024) {
- info[0] = 128;
- info[1] = 63;
- info[2] = size / (info[0] * info[1]);
- if (info[2] >= 1024) {
- info[0] = 255;
- info[1] = 63;
- info[2] = size / (info[0] * info[1]);
- if (info[2] >= 1024)
- info[2] = 1023;
- }
- }
- return 0;
-}
-
-/* calculate percentage of total accesses on a ldn */
-static int ldn_access_load(struct Scsi_Host *shpnt, int ldn)
-{
- if (IBM_DS(shpnt).total_accesses == 0)
- return (0);
- if (IBM_DS(shpnt).ldn_access[ldn] == 0)
- return (0);
- return (IBM_DS(shpnt).ldn_access[ldn] * 100) / IBM_DS(shpnt).total_accesses;
-}
-
-/* calculate total amount of r/w-accesses */
-static int ldn_access_total_read_write(struct Scsi_Host *shpnt)
-{
- int a;
- int i;
-
- a = 0;
- for (i = 0; i <= MAX_LOG_DEV; i++)
- a += IBM_DS(shpnt).ldn_read_access[i] + IBM_DS(shpnt).ldn_write_access[i];
- return (a);
-}
-
-static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
-{
- int a;
- int i;
-
- a = 0;
- for (i = 0; i <= MAX_LOG_DEV; i++)
- a += IBM_DS(shpnt).ldn_inquiry_access[i];
- return (a);
-}
-
-static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
-{
- int a;
- int i;
-
- a = 0;
- for (i = 0; i <= MAX_LOG_DEV; i++)
- a += IBM_DS(shpnt).ldn_modeselect_access[i];
- return (a);
-}
-
-/* routine to display info in the proc-fs-structure (a deluxe feature) */
-static int ibmmca_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout)
-{
- int len = 0;
- int i, id, lun;
- unsigned long flags;
- int max_pun;
-
-
- spin_lock_irqsave(shpnt->host_lock, flags); /* Check it */
-
- max_pun = subsystem_maxid(shpnt);
-
- len += sprintf(buffer + len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION);
- len += sprintf(buffer + len, " SCSI Access-Statistics:\n");
- len += sprintf(buffer + len, " Device Scanning Order....: %s\n", (ibm_ansi_order) ? "IBM/ANSI" : "New Industry Standard");
-#ifdef CONFIG_SCSI_MULTI_LUN
- len += sprintf(buffer + len, " Multiple LUN probing.....: Yes\n");
-#else
- len += sprintf(buffer + len, " Multiple LUN probing.....: No\n");
-#endif
- len += sprintf(buffer + len, " This Hostnumber..........: %d\n", shpnt->host_no);
- len += sprintf(buffer + len, " Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(shpnt)));
- len += sprintf(buffer + len, " (Shared) IRQ.............: %d\n", IM_IRQ);
- len += sprintf(buffer + len, " Total Interrupts.........: %d\n", IBM_DS(shpnt).total_interrupts);
- len += sprintf(buffer + len, " Total SCSI Accesses......: %d\n", IBM_DS(shpnt).total_accesses);
- len += sprintf(buffer + len, " Total short SCBs.........: %d\n", IBM_DS(shpnt).scbs);
- len += sprintf(buffer + len, " Total long SCBs..........: %d\n", IBM_DS(shpnt).long_scbs);
- len += sprintf(buffer + len, " Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(shpnt));
- len += sprintf(buffer + len, " Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(shpnt));
- len += sprintf(buffer + len, " Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(shpnt));
- len += sprintf(buffer + len, " Total SCSI other cmds..: %d\n", IBM_DS(shpnt).total_accesses - ldn_access_total_read_write(shpnt)
- - ldn_access_total_modeselect(shpnt)
- - ldn_access_total_inquiry(shpnt));
- len += sprintf(buffer + len, " Total SCSI command fails.: %d\n\n", IBM_DS(shpnt).total_errors);
- len += sprintf(buffer + len, " Logical-Device-Number (LDN) Access-Statistics:\n");
- len += sprintf(buffer + len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n");
- len += sprintf(buffer + len, " -----|--------------|-----------|-----------|--------------\n");
- for (i = 0; i <= MAX_LOG_DEV; i++)
- len += sprintf(buffer + len, " %2X | %3d | %8d | %8d | %8d\n", i, ldn_access_load(shpnt, i), IBM_DS(shpnt).ldn_read_access[i], IBM_DS(shpnt).ldn_write_access[i], IBM_DS(shpnt).ldn_assignments[i]);
- len += sprintf(buffer + len, " -----------------------------------------------------------\n\n");
- len += sprintf(buffer + len, " Dynamical-LDN-Assignment-Statistics:\n");
- len += sprintf(buffer + len, " Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(shpnt).total_scsi_devices);
- len += sprintf(buffer + len, " Dynamical Assignment necessary...: %s\n", IBM_DS(shpnt).dyn_flag ? "Yes" : "No ");
- len += sprintf(buffer + len, " Next LDN to be assigned..........: 0x%x\n", next_ldn(shpnt));
- len += sprintf(buffer + len, " Dynamical assignments done yet...: %d\n", IBM_DS(shpnt).dynamical_assignments);
- len += sprintf(buffer + len, "\n Current SCSI-Device-Mapping:\n");
- len += sprintf(buffer + len, " Physical SCSI-Device Map Logical SCSI-Device Map\n");
- len += sprintf(buffer + len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
- for (id = 0; id < max_pun; id++) {
- len += sprintf(buffer + len, " %2d ", id);
- for (lun = 0; lun < 8; lun++)
- len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(shpnt)[id][lun]));
- len += sprintf(buffer + len, " %2d ", id);
- for (lun = 0; lun < 8; lun++)
- len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(shpnt)[id][lun]));
- len += sprintf(buffer + len, "\n");
- }
-
- len += sprintf(buffer + len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n");
- len += sprintf(buffer + len, " R = CD-ROM, S = Scanner, M = MO-Drive, C = Medium-Changer, + = unprovided LUN,\n");
- len += sprintf(buffer + len, " - = nothing found, nothing assigned or unprobed LUN)\n\n");
-
- *start = buffer + offset;
- len -= offset;
- if (len > length)
- len = length;
- spin_unlock_irqrestore(shpnt->host_lock, flags);
- return len;
-}
-
-static int option_setup(char *str)
-{
- int ints[IM_MAX_HOSTS];
- char *cur = str;
- int i = 1;
-
- while (cur && isdigit(*cur) && i < IM_MAX_HOSTS) {
- ints[i++] = simple_strtoul(cur, NULL, 0);
- if ((cur = strchr(cur, ',')) != NULL)
- cur++;
- }
- ints[0] = i - 1;
- internal_ibmmca_scsi_setup(cur, ints);
- return 1;
-}
-
-__setup("ibmmcascsi=", option_setup);
-
-static struct mca_driver ibmmca_driver = {
- .id_table = ibmmca_id_table,
- .driver = {
- .name = "ibmmca",
- .bus = &mca_bus_type,
- .probe = ibmmca_probe,
- .remove = __devexit_p(ibmmca_remove),
- },
-};
-
-static int __init ibmmca_init(void)
-{
-#ifdef MODULE
- /* If the driver is run as module, read from conf.modules or cmd-line */
- if (boot_options)
- option_setup(boot_options);
-#endif
-
- return mca_register_driver_integrated(&ibmmca_driver, MCA_INTEGSCSI);
-}
-
-static void __exit ibmmca_exit(void)
-{
- mca_unregister_driver(&ibmmca_driver);
-}
-
-module_init(ibmmca_init);
-module_exit(ibmmca_exit);
diff --git a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
index 8ac6ce7..a318264 100644
--- a/drivers/scsi/sim710.c
+++ b/drivers/scsi/sim710.c
@@ -17,7 +17,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*----------------------------------------------------------------------------
*
- * MCA card detection code by Trent McNair.
+ * MCA card detection code by Trent McNair. (now deleted)
* Fixes to not explicitly nul bss data from Xavier Bestel.
* Some multiboard fixes from Rolf Eike Beer.
* Auto probing of EISA config space from Trevor Hemsley.
@@ -32,7 +32,6 @@
#include <linux/blkdev.h>
#include <linux/device.h>
#include <linux/init.h>
-#include <linux/mca.h>
#include <linux/eisa.h>
#include <linux/interrupt.h>
#include <scsi/scsi_host.h>
@@ -43,7 +42,7 @@
#include "53c700.h"
-/* Must be enough for both EISA and MCA */
+/* Must be enough for EISA */
#define MAX_SLOTS 8
static __u8 __initdata id_array[MAX_SLOTS] = { [0 ... MAX_SLOTS-1] = 7 };
@@ -89,7 +88,7 @@ param_setup(char *str)
__setup("sim710=", param_setup);
static struct scsi_host_template sim710_driver_template = {
- .name = "LSI (Symbios) 710 MCA/EISA",
+ .name = "LSI (Symbios) 710 EISA",
.proc_name = "sim710",
.this_id = 7,
.module = THIS_MODULE,
@@ -169,114 +168,6 @@ sim710_device_remove(struct device *dev)
return 0;
}
-#ifdef CONFIG_MCA
-
-/* CARD ID 01BB and 01BA use the same pos values */
-#define MCA_01BB_IO_PORTS { 0x0000, 0x0000, 0x0800, 0x0C00, 0x1000, 0x1400, \
- 0x1800, 0x1C00, 0x2000, 0x2400, 0x2800, \
- 0x2C00, 0x3000, 0x3400, 0x3800, 0x3C00, \
- 0x4000, 0x4400, 0x4800, 0x4C00, 0x5000 }
-
-#define MCA_01BB_IRQS { 3, 5, 11, 14 }
-
-/* CARD ID 004f */
-#define MCA_004F_IO_PORTS { 0x0000, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600 }
-#define MCA_004F_IRQS { 5, 9, 14 }
-
-static short sim710_mca_id_table[] = { 0x01bb, 0x01ba, 0x004f, 0};
-
-static __init int
-sim710_mca_probe(struct device *dev)
-{
- struct mca_device *mca_dev = to_mca_device(dev);
- int slot = mca_dev->slot;
- int pos[3];
- unsigned int base;
- int irq_vector;
- short id = sim710_mca_id_table[mca_dev->index];
- static int io_004f_by_pos[] = MCA_004F_IO_PORTS;
- static int irq_004f_by_pos[] = MCA_004F_IRQS;
- static int io_01bb_by_pos[] = MCA_01BB_IO_PORTS;
- static int irq_01bb_by_pos[] = MCA_01BB_IRQS;
- char *name;
- int clock;
-
- pos[0] = mca_device_read_stored_pos(mca_dev, 2);
- pos[1] = mca_device_read_stored_pos(mca_dev, 3);
- pos[2] = mca_device_read_stored_pos(mca_dev, 4);
-
- /*
- * 01BB & 01BA port base by bits 7,6,5,4,3,2 in pos[2]
- *
- * 000000 <disabled> 001010 0x2800
- * 000001 <invalid> 001011 0x2C00
- * 000010 0x0800 001100 0x3000
- * 000011 0x0C00 001101 0x3400
- * 000100 0x1000 001110 0x3800
- * 000101 0x1400 001111 0x3C00
- * 000110 0x1800 010000 0x4000
- * 000111 0x1C00 010001 0x4400
- * 001000 0x2000 010010 0x4800
- * 001001 0x2400 010011 0x4C00
- * 010100 0x5000
- *
- * 00F4 port base by bits 3,2,1 in pos[0]
- *
- * 000 <disabled> 001 0x200
- * 010 0x300 011 0x400
- * 100 0x500 101 0x600
- *
- * 01BB & 01BA IRQ is specified in pos[0] bits 7 and 6:
- *
- * 00 3 10 11
- * 01 5 11 14
- *
- * 00F4 IRQ specified by bits 6,5,4 in pos[0]
- *
- * 100 5 101 9
- * 110 14
- */
-
- if (id == 0x01bb || id == 0x01ba) {
- base = io_01bb_by_pos[(pos[2] & 0xFC) >> 2];
- irq_vector =
- irq_01bb_by_pos[((pos[0] & 0xC0) >> 6)];
-
- clock = 50;
- if (id == 0x01bb)
- name = "NCR 3360/3430 SCSI SubSystem";
- else
- name = "NCR Dual SIOP SCSI Host Adapter Board";
- } else if ( id == 0x004f ) {
- base = io_004f_by_pos[((pos[0] & 0x0E) >> 1)];
- irq_vector =
- irq_004f_by_pos[((pos[0] & 0x70) >> 4) - 4];
- clock = 50;
- name = "NCR 53c710 SCSI Host Adapter Board";
- } else {
- return -ENODEV;
- }
- mca_device_set_name(mca_dev, name);
- mca_device_set_claim(mca_dev, 1);
- base = mca_device_transform_ioport(mca_dev, base);
- irq_vector = mca_device_transform_irq(mca_dev, irq_vector);
-
- return sim710_probe_common(dev, base, irq_vector, clock,
- 0, id_array[slot]);
-}
-
-static struct mca_driver sim710_mca_driver = {
- .id_table = sim710_mca_id_table,
- .driver = {
- .name = "sim710",
- .bus = &mca_bus_type,
- .probe = sim710_mca_probe,
- .remove = __devexit_p(sim710_device_remove),
- },
-};
-
-#endif /* CONFIG_MCA */
-
#ifdef CONFIG_EISA
static struct eisa_device_id sim710_eisa_ids[] = {
{ "CPQ4410" },
@@ -344,10 +235,6 @@ static int __init sim710_init(void)
param_setup(sim710);
#endif
-#ifdef CONFIG_MCA
- err = mca_register_driver(&sim710_mca_driver);
-#endif
-
#ifdef CONFIG_EISA
err = eisa_driver_register(&sim710_eisa_driver);
#endif
@@ -361,11 +248,6 @@ static int __init sim710_init(void)
static void __exit sim710_exit(void)
{
-#ifdef CONFIG_MCA
- if (MCA_bus)
- mca_unregister_driver(&sim710_mca_driver);
-#endif
-
#ifdef CONFIG_EISA
eisa_driver_unregister(&sim710_eisa_driver);
#endif