fd_mcs.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* fd_mcs.c -- Future Domain MCS 600/700 (or IBM OEM) driver 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FutureDomain MCS-600/700 v0.2 03/11/1998 by ZP Gu (zpg@castle.net) 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver is cloned from fdomain.* to specifically support 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Future Domain MCS 600/700 MCA SCSI adapters. Some PS/2s 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * also equipped with IBM Fast SCSI Adapter/A which is an OEM 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of MCS 700. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver also supports Reply SB16/SCSI card (the SCSI part). 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * What makes this driver different is that this driver is MCA only 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and it supports multiple adapters in the same system, IRQ 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sharing, some driver statistics, and maps highest SCSI id to sda. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All cards are auto-detected. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Assumptions: TMC-1800/18C50/18C30, BIOS >= 3.4 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LILO command-line options: 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fd_mcs=<FIFO_COUNT>[,<FIFO_SIZE>] 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ******************************************************** 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Please see Copyrights/Comments in fdomain.* for credits. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Following is from fdomain.c for acknowledgement: 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Revised: Wed Oct 2 11:10:55 1996 by r.faith@ieee.org 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author: Rickard E. Faith, faith@cs.unc.edu 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * $Id: fdomain.c,v 5.45 1996/10/02 15:13:06 root Exp $ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify it 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * under the terms of the GNU General Public License as published by the 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free Software Foundation; either version 2, or (at your option) any 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * later version. 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License for more details. 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License along 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 675 Mass Ave, Cambridge, MA 02139, USA. 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ************************************************************************** 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NOTES ON USER DEFINABLE OPTIONS: 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DEBUG: This turns on the printing of various debug information. 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ENABLE_PARITY: This turns on SCSI parity checking. With the current 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds driver, all attached devices must support SCSI parity. If none of your 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds devices support parity, then you can probably get the driver to work by 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds turning this option off. I have no way of testing this, however, and it 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds would appear that no one ever uses this option. 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the SCSI device, an interrupt will be raised. Therefore, this could be as 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds low as 0, or as high as 16. Note, however, that values which are too high 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds or too low seem to prevent any interrupts from occurring, and thereby lock 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up the machine. I have found that 2 is a good number, but throughput may 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds be increased by changing this value to values which are close to 2. 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Please let me know if you try any different values. 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds [*****Now a runtime option*****] 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RESELECTION: This is no longer an option, since I gave up trying to 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds implement it in version 4.x of this driver. It did not improve 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds performance at all and made the driver unstable (because I never found one 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds of the two race conditions which were introduced by the multiple 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outstanding command code). The instability seems a very high price to pay 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds just so that you don't have to wait for the tape to rewind. If you want 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this feature implemented, send me patches. I'll be happy to send a copy 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds of my (broken) driver to anyone who would like to see a copy. 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds **************************************************************************/ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mca.h> 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsicam.h> 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mca-legacy.h> 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/system.h> 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi.h" 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h> 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>" 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* START OF USER DEFINABLE OPTIONS */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG 0 /* Enable debugging output */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ENABLE_PARITY 1 /* Enable SCSI Parity */ 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* END OF USER DEFINABLE OPTIONS */ 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EVERY_ACCESS 0 /* Write a line on every scsi access */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ERRORS_ONLY 1 /* Only write a line if there is an error */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_ABORT 1 /* Debug abort() routine */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_RESET 1 /* Debug reset() routine */ 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_RACE 1 /* Debug interrupt-driven race condition */ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ERRORS_ONLY 0 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_MESSAGES 0 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_ABORT 0 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_RESET 0 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_RACE 0 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Errors are reported on the line, so we don't need to report them again */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef ERRORS_ONLY 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ERRORS_ONLY 0 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if ENABLE_PARITY 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PARITY_MASK 0x08 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PARITY_MASK 0x00 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum chip_type { 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unknown = 0x00, 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmc1800 = 0x01, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmc18c50 = 0x02, 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmc18c30 = 0x03, 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_arbitration = 0x02, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_selection = 0x04, 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_other = 0x08, 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disconnect = 0x10, 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aborted = 0x20, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sent_ident = 0x40, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum in_port_type { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Read_SCSI_Data = 0, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Status = 1, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TMC_Status = 2, 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LSB_ID_Code = 5, 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MSB_ID_Code = 6, 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Read_Loopback = 7, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Data_NoACK = 8, 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Interrupt_Status = 9, 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Configuration1 = 10, 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Configuration2 = 11, /* tmc18c50/tmc18c30 only */ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Read_FIFO = 12, 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_Data_Count = 14 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum out_port_type { 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Write_SCSI_Data = 0, 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Cntl = 1, 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Interrupt_Cntl = 2, 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Mode_Cntl = 3, 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TMC_Cntl = 4, 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Write_Loopback = 7, 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IO_Control = 11, /* tmc18c30 only */ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Write_FIFO = 12 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct fd_hostdata { 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long _bios_base; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _bios_major; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _bios_minor; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile int _in_command; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Scsi_Cmnd *_current_SC; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum chip_type _chip; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _adapter_mask; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _fifo_count; /* Number of 512 byte blocks before INTR */ 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char _adapter_name[64]; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile int _in_interrupt_flag; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _SCSI_Mode_Cntl_port; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _FIFO_Data_Count_port; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Interrupt_Cntl_port; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Interrupt_Status_port; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Interrupt_Cond_port; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Read_FIFO_port; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Read_SCSI_Data_port; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _SCSI_Cntl_port; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _SCSI_Data_NoACK_port; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _SCSI_Status_port; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _TMC_Cntl_port; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _TMC_Status_port; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Write_FIFO_port; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Write_SCSI_Data_port; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _FIFO_Size; /* = 0x2000; 8k FIFO for 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pre-tmc18c30 chips */ 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* simple stats */ 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Bytes_Read; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _Bytes_Written; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int _INTR_Processed; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FD_MAX_HOSTS 3 /* enough? */ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HOSTDATA(shpnt) ((struct fd_hostdata *) shpnt->hostdata) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define bios_base (HOSTDATA(shpnt)->_bios_base) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define bios_major (HOSTDATA(shpnt)->_bios_major) 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define bios_minor (HOSTDATA(shpnt)->_bios_minor) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define in_command (HOSTDATA(shpnt)->_in_command) 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define current_SC (HOSTDATA(shpnt)->_current_SC) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define chip (HOSTDATA(shpnt)->_chip) 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define adapter_mask (HOSTDATA(shpnt)->_adapter_mask) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FIFO_COUNT (HOSTDATA(shpnt)->_fifo_count) 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define adapter_name (HOSTDATA(shpnt)->_adapter_name) 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define in_interrupt_flag (HOSTDATA(shpnt)->_in_interrupt_flag) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_Mode_Cntl_port (HOSTDATA(shpnt)->_SCSI_Mode_Cntl_port) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FIFO_Data_Count_port (HOSTDATA(shpnt)->_FIFO_Data_Count_port) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Interrupt_Cntl_port (HOSTDATA(shpnt)->_Interrupt_Cntl_port) 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Interrupt_Status_port (HOSTDATA(shpnt)->_Interrupt_Status_port) 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Interrupt_Cond_port (HOSTDATA(shpnt)->_Interrupt_Cond_port) 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Read_FIFO_port (HOSTDATA(shpnt)->_Read_FIFO_port) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Read_SCSI_Data_port (HOSTDATA(shpnt)->_Read_SCSI_Data_port) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_Cntl_port (HOSTDATA(shpnt)->_SCSI_Cntl_port) 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_Data_NoACK_port (HOSTDATA(shpnt)->_SCSI_Data_NoACK_port) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SCSI_Status_port (HOSTDATA(shpnt)->_SCSI_Status_port) 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMC_Cntl_port (HOSTDATA(shpnt)->_TMC_Cntl_port) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TMC_Status_port (HOSTDATA(shpnt)->_TMC_Status_port) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Write_FIFO_port (HOSTDATA(shpnt)->_Write_FIFO_port) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Write_SCSI_Data_port (HOSTDATA(shpnt)->_Write_SCSI_Data_port) 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FIFO_Size (HOSTDATA(shpnt)->_FIFO_Size) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Bytes_Read (HOSTDATA(shpnt)->_Bytes_Read) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define Bytes_Written (HOSTDATA(shpnt)->_Bytes_Written) 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INTR_Processed (HOSTDATA(shpnt)->_INTR_Processed) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct fd_mcs_adapters_struct { 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *name; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int id; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enum chip_type fd_chip; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fifo_size; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fifo_count; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define REPLY_ID 0x5137 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fd_mcs_adapters_struct fd_mcs_adapters[] = { 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Future Domain SCSI Adapter MCS-700(18C50)", 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x60e9, 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmc18c50, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2000, 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4}, 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Future Domain SCSI Adapter MCS-600/700(TMC-1800)", 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x6127, 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmc1800, 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2000, 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4}, 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Reply Sound Blaster/SCSI Adapter", 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REPLY_ID, 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmc18c30, 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x800, 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2}, 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FD_BRDS sizeof(fd_mcs_adapters)/sizeof(struct fd_mcs_adapters_struct) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 }; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* host information */ 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int found = 0; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL }; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int user_fifo_count = 0; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int user_fifo_size = 0; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init fd_mcs_setup(char *str) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int done_setup = 0; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ints[3]; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_options(str, 3, ints); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) { 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n"); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds user_fifo_count = ints[0] >= 1 ? ints[1] : 0; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds user_fifo_size = ints[0] >= 2 ? ints[2] : 0; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds__setup("fd_mcs=", fd_mcs_setup); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void print_banner(struct Scsi_Host *shpnt) 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("scsi%d <fd_mcs>: ", shpnt->host_no); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bios_base) { 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("BIOS at 0x%lX", bios_base); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("No BIOS"); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 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); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void do_pause(unsigned amount) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ /* Pause for amount*10 milliseconds */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(10); 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (--amount); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fd_mcs_make_bus_idle(struct Scsi_Host *shpnt) 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, SCSI_Cntl_port); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, SCSI_Mode_Cntl_port); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip == tmc18c50 || chip == tmc18c30) 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x21 | PARITY_MASK, TMC_Cntl_port); /* Clear forced intr. */ 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x01 | PARITY_MASK, TMC_Cntl_port); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_detect(Scsi_Host_Template * tpnt) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int loop; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shpnt; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get id, port, bios, irq */ 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int slot; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char pos2, pos3, pos4; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int id, port, irq; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long bios; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if not MCA machine, return */ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MCA_bus) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* changeable? */ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds id = 7; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (loop = 0; loop < FD_BRDS; loop++) { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot = 0; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (MCA_NOTFOUND != (slot = mca_find_adapter(fd_mcs_adapters[loop].id, slot))) { 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if we get this far, an adapter has been detected and is 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enabled */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "scsi <fd_mcs>: %s at slot %d\n", fd_mcs_adapters[loop].name, slot + 1); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos2 = mca_read_stored_pos(slot, 2); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos3 = mca_read_stored_pos(slot, 3); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pos4 = mca_read_stored_pos(slot, 4); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ready for next probe */ 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot++; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fd_mcs_adapters[loop].id == REPLY_ID) { /* reply card */ 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int reply_irq[] = { 10, 11, 14, 15 }; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bios = 0; /* no bios */ 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pos2 & 0x2) 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = ports[pos4 & 0x3]; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* can't really disable it, same as irq=10 */ 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = reply_irq[((pos4 >> 2) & 0x1) + 2 * ((pos4 >> 4) & 0x1)]; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bios = addresses[pos2 >> 6]; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = ports[(pos2 >> 4) & 0x03]; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = interrupts[(pos2 >> 1) & 0x07]; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (irq) { 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* claim the slot */ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mca_set_adapter_name(slot - 1, fd_mcs_adapters[loop].name); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check irq/region */ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_irq(irq, fd_mcs_intr, SA_SHIRQ, "fd_mcs", hosts)) { 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "fd_mcs: interrupt is not available, skipping...\n"); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* request I/O region */ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_region(port, 0x10, "fd_mcs")) { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "fd_mcs: I/O region is already in use, skipping...\n"); 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* register */ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(shpnt = scsi_register(tpnt, sizeof(struct fd_hostdata)))) { 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "fd_mcs: scsi_register() failed\n"); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(port, 0x10); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(irq, hosts); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save name */ 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(adapter_name, fd_mcs_adapters[loop].name); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* chip/fifo */ 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip = fd_mcs_adapters[loop].fd_chip; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* use boot time value if available */ 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */ 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NOT_USED 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* *************************************************** */ 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try to toggle 32-bit mode. This only 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds works on an 18c30 chip. (User reports 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds say this works, so we should switch to 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it in the near future.) */ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x80, port + IO_Control); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((inb(port + Configuration2) & 0x80) == 0x80) { 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, port + IO_Control); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((inb(port + Configuration2) & 0x80) == 0x00) { 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip = tmc18c30; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_Size = 0x800; /* 2k FIFO */ 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("FIRST: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* That should have worked, but appears to 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds have problems. Let's assume it is an 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18c30 if the RAM is disabled. */ 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inb(port + Configuration2) & 0x02) { 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip = tmc18c30; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_Size = 0x800; /* 2k FIFO */ 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SECOND: chip=%s, fifo_size=0x%x\n", (chip == tmc18c30) ? "tmc18c30" : "tmc18c50", FIFO_Size); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* *************************************************** */ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* IBM/ANSI scsi scan ordering */ 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Stick this back in when the scsi.c changes are there */ 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shpnt->reverse_ordering = 1; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* saving info */ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hosts[found++] = shpnt; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shpnt->this_id = id; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shpnt->irq = irq; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shpnt->io_port = port; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds shpnt->n_io_port = 0x10; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save */ 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bios_base = bios; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter_mask = (1 << id); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* save more */ 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Mode_Cntl_port = port + SCSI_Mode_Cntl; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FIFO_Data_Count_port = port + FIFO_Data_Count; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Interrupt_Cntl_port = port + Interrupt_Cntl; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Interrupt_Status_port = port + Interrupt_Status; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Interrupt_Cond_port = port + Interrupt_Cond; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Read_FIFO_port = port + Read_FIFO; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Read_SCSI_Data_port = port + Read_SCSI_Data; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Cntl_port = port + SCSI_Cntl; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Data_NoACK_port = port + SCSI_Data_NoACK; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCSI_Status_port = port + SCSI_Status; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TMC_Cntl_port = port + TMC_Cntl; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TMC_Status_port = port + TMC_Status; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Write_FIFO_port = port + Write_FIFO; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Write_SCSI_Data_port = port + Write_SCSI_Data; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Bytes_Read = 0; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Bytes_Written = 0; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTR_Processed = 0; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* say something */ 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds print_banner(shpnt); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reset */ 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(1, SCSI_Cntl_port); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_pause(2); 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, SCSI_Cntl_port); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_pause(115); 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, SCSI_Mode_Cntl_port); 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(PARITY_MASK, TMC_Cntl_port); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* done reset */ 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found == FD_MAX_HOSTS) { 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: detecting reached max=%d host adapters.\n", FD_MAX_HOSTS); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return found; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *fd_mcs_info(struct Scsi_Host *shpnt) 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return adapter_name; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int TOTAL_INTR = 0; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inout : decides on the direction of the dataflow and the meaning of the 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * variables 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * buffer: If inout==FALSE data is being written to it else read from it 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * *start: If inout==FALSE start of the valid data in the buffer 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * offset: If inout==FALSE offset from the beginning of the imaginary file 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from which we start writing into the buffer 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * length: If inout==FALSE max number of bytes to be written into the buffer 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * else number of bytes in the buffer 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout) 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len = 0; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inout) 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (-ENOSYS); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = buffer + offset; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += sprintf(buffer + len, "Future Domain MCS-600/700 Driver %s\n", DRIVER_VERSION); 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += sprintf(buffer + len, "HOST #%d: %s\n", shpnt->host_no, adapter_name); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += sprintf(buffer + len, "FIFO Size=0x%x, FIFO Count=%d\n", FIFO_Size, FIFO_COUNT); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += sprintf(buffer + len, "DriverCalls=%d, Interrupts=%d, BytesRead=%d, BytesWrite=%d\n\n", TOTAL_INTR, INTR_Processed, Bytes_Read, Bytes_Written); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((len -= offset) <= 0) 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len > length) 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = length; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return len; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_select(struct Scsi_Host *shpnt, int target) 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long timeout; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */ 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(adapter_mask | (1 << target), SCSI_Data_NoACK_port); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Stop arbitration and enable parity */ 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(PARITY_MASK, TMC_Cntl_port); 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds timeout = 350; /* 350mS -- because of timeouts 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (was 250mS) */ 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = inb(SCSI_Status_port); /* Read adapter status */ 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 1) { /* Busy asserted */ 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Enable SCSI Bus (on error, should make bus idle with 0) */ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x80, SCSI_Cntl_port); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1000); /* wait one msec */ 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (--timeout); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make bus idle */ 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fd_mcs_make_bus_idle(shpnt); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!target) 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Selection failed\n"); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if ERRORS_ONLY 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!target) { 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int flag = 0; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!flag) /* Skip first failure for all chips. */ 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++flag; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: Selection failed\n"); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void my_done(struct Scsi_Host *shpnt, int error) 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (in_command) { 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_command = 0; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, Interrupt_Cntl_port); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fd_mcs_make_bus_idle(shpnt); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->result = error; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->scsi_done(current_SC); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds panic("fd_mcs: my_done() called outside of command\n"); 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_interrupt_flag = 0; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* only my_done needs to be protected */ 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs) 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int done = 0; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned data_count, tmp_count; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 0; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shpnt; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TOTAL_INTR++; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* search for one adapter-response on shared interrupt */ 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((shpnt = hosts[i++])) { 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((inb(TMC_Status_port)) & 1) 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* return if some other device on this IRQ caused the interrupt */ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!shpnt) { 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INTR_Processed++; 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, Interrupt_Cntl_port); 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Abort calls my_done, so we do nothing here. */ 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->SCp.phase & aborted) { 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_ABORT 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Interrupt after abort, ignoring\n"); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* return IRQ_HANDLED; */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++in_interrupt_flag; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->SCp.phase & in_arbitration) { 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = inb(TMC_Status_port); /* Read adapter status */ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & 0x02)) { 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" AFAIL "); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds my_done(shpnt, DID_BUS_BUSY << 16); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shpnt->host_lock, flags); 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.phase = in_selection; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x40 | FIFO_COUNT, Interrupt_Cntl_port); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x82, SCSI_Cntl_port); /* Bus Enable + Select */ 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(adapter_mask | (1 << current_SC->device->id), SCSI_Data_NoACK_port); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Stop arbitration and enable parity */ 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x10 | PARITY_MASK, TMC_Cntl_port); 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_interrupt_flag = 0; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (current_SC->SCp.phase & in_selection) { 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = inb(SCSI_Status_port); 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(status & 0x01)) { 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Try again, for slow devices */ 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fd_mcs_select(shpnt, current_SC->device->id)) { 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" SFAIL "); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds my_done(shpnt, DID_NO_CONNECT << 16); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shpnt->host_lock, flags); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" AltSel "); 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Stop arbitration and enable parity */ 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x10 | PARITY_MASK, TMC_Cntl_port); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.phase = in_other; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x80, SCSI_Cntl_port); 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_interrupt_flag = 0; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* current_SC->SCp.phase == in_other: this is the body of the routine */ 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = inb(SCSI_Status_port); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 0x10) { /* REQ */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (status & 0x0e) { 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x08: /* COMMAND OUT */ 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(current_SC->cmnd[current_SC->SCp.sent_command++], Write_SCSI_Data_port); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("CMD = %x,", current_SC->cmnd[current_SC->SCp.sent_command - 1]); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip != tmc1800 && !current_SC->SCp.have_data_in) { 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.have_data_in = -1; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0xd0 | PARITY_MASK, TMC_Cntl_port); 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip != tmc1800 && !current_SC->SCp.have_data_in) { 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.have_data_in = 1; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x90 | PARITY_MASK, TMC_Cntl_port); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0c: /* STATUS IN */ 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.Status = inb(Read_SCSI_Data_port); 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Status = %x, ", current_SC->SCp.Status); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if ERRORS_ONLY 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->SCp.Status && current_SC->SCp.Status != 2 && current_SC->SCp.Status != 8) { 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("ERROR fd_mcs: target = %d, command = %x, status = %x\n", current_SC->device->id, current_SC->cmnd[0], current_SC->SCp.Status); 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0a: /* MESSAGE OUT */ 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(MESSAGE_REJECT, Write_SCSI_Data_port); /* Reject */ 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0e: /* MESSAGE IN */ 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.Message = inb(Read_SCSI_Data_port); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Message = %x, ", current_SC->SCp.Message); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!current_SC->SCp.Message) 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++done; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_MESSAGES || EVERY_ACCESS 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->SCp.Message) { 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: message = %x\n", current_SC->SCp.Message); 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip == tmc1800 && !current_SC->SCp.have_data_in && (current_SC->SCp.sent_command >= current_SC->cmd_len)) { 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We have to get the FIFO direction 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds correct, so I've made a table based 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds on the SCSI Standard of which commands 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds appear to require a DATA OUT phase. 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 94: Command for all device types 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CHANGE DEFINITION 40 DATA OUT 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COMPARE 39 DATA OUT 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COPY 18 DATA OUT 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds COPY AND VERIFY 3a DATA OUT 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INQUIRY 12 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOG SELECT 4c DATA OUT 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOG SENSE 4d 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MODE SELECT (6) 15 DATA OUT 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MODE SELECT (10) 55 DATA OUT 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MODE SENSE (6) 1a 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MODE SENSE (10) 5a 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ BUFFER 3c 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RECEIVE DIAGNOSTIC RESULTS 1c 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REQUEST SENSE 03 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEND DIAGNOSTIC 1d DATA OUT 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TEST UNIT READY 00 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE BUFFER 3b DATA OUT 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p.178: Commands for direct-access devices (not listed on p. 94) 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORMAT UNIT 04 DATA OUT 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOCK-UNLOCK CACHE 36 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PRE-FETCH 34 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PREVENT-ALLOW MEDIUM REMOVAL 1e 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ (6)/RECEIVE 08 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ (10) 3c 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ CAPACITY 25 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ DEFECT DATA (10) 37 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ LONG 3e 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REASSIGN BLOCKS 07 DATA OUT 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RELEASE 17 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RESERVE 16 DATA OUT 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REZERO UNIT/REWIND 01 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEARCH DATA EQUAL (10) 31 DATA OUT 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEARCH DATA HIGH (10) 30 DATA OUT 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEARCH DATA LOW (10) 32 DATA OUT 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEEK (6) 0b 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEEK (10) 2b 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET LIMITS (10) 33 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds START STOP UNIT 1b 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SYNCHRONIZE CACHE 35 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VERIFY (10) 2f 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE (6)/PRINT/SEND 0a DATA OUT 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE (10)/SEND 2a DATA OUT 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE AND VERIFY (10) 2e DATA OUT 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE LONG 3f DATA OUT 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE SAME 41 DATA OUT ? 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 261: Commands for sequential-access devices (not previously listed) 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ERASE 19 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOAD UNLOAD 1b 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LOCATE 2b 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ BLOCK LIMITS 05 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ POSITION 34 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ REVERSE 0f 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RECOVER BUFFERED DATA 14 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SPACE 11 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE FILEMARKS 10 ? 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 298: Commands for printer devices (not previously listed) 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ****** NOT SUPPORTED BY THIS DRIVER, since 0b is SEEK (6) ***** 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SLEW AND PRINT 0b DATA OUT -- same as seek 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds STOP PRINT 1b 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SYNCHRONIZE BUFFER 10 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 315: Commands for processor devices (not previously listed) 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 321: Commands for write-once devices (not previously listed) 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEDIUM SCAN 38 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ (12) a8 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEARCH DATA EQUAL (12) b1 DATA OUT 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEARCH DATA HIGH (12) b0 DATA OUT 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEARCH DATA LOW (12) b2 DATA OUT 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET LIMITS (12) b3 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds VERIFY (12) af 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE (12) aa DATA OUT 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE AND VERIFY (12) ae DATA OUT 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 332: Commands for CD-ROM devices (not previously listed) 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAUSE/RESUME 4b 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PLAY AUDIO (10) 45 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PLAY AUDIO (12) a5 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PLAY AUDIO MSF 47 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PLAY TRACK RELATIVE (10) 49 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PLAY TRACK RELATIVE (12) a9 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ HEADER 44 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ SUB-CHANNEL 42 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ TOC 43 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 370: Commands for scanner devices (not previously listed) 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GET DATA BUFFER STATUS 34 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GET WINDOW 25 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OBJECT POSITION 31 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCAN 1b 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET WINDOW 24 DATA OUT 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 391: Commands for optical memory devices (not listed) 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ERASE (10) 2c 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ERASE (12) ac 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MEDIUM SCAN 38 DATA OUT 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ DEFECT DATA (12) b7 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ GENERATION 29 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ UPDATED BLOCK 2d 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds UPDATE BLOCK 3d DATA OUT 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 419: Commands for medium changer devices (not listed) 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXCHANGE MEDIUM 46 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds INITIALIZE ELEMENT STATUS 07 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MOVE MEDIUM a5 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds POSITION TO ELEMENT 2b 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds READ ELEMENT STATUS b8 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REQUEST VOL. ELEMENT ADDRESS b5 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SEND VOLUME TAG b6 DATA OUT 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p. 454: Commands for communications devices (not listed previously) 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GET MESSAGE (6) 08 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GET MESSAGE (10) 28 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GET MESSAGE (12) a8 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (current_SC->cmnd[0]) { 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CHANGE_DEFINITION: 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case COMPARE: 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case COPY: 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case COPY_VERIFY: 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case LOG_SELECT: 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MODE_SELECT: 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case MODE_SELECT_10: 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEND_DIAGNOSTIC: 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case WRITE_BUFFER: 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FORMAT_UNIT: 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case REASSIGN_BLOCKS: 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case RESERVE: 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEARCH_EQUAL: 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEARCH_HIGH: 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEARCH_LOW: 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case WRITE_6: 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case WRITE_10: 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case WRITE_VERIFY: 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3f: 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x41: 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xb1: 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xb0: 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xb2: 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xaa: 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xae: 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x24: 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x38: 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3d: 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xb6: 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0xea: /* alternate number for WRITE LONG */ 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.have_data_in = -1; 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0xd0 | PARITY_MASK, TMC_Cntl_port); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x00: 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.have_data_in = 1; 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x90 | PARITY_MASK, TMC_Cntl_port); 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */ 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((data_count = FIFO_Size - inw(FIFO_Data_Count_port)) > 512) { 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("DC=%d, ", data_count); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data_count > current_SC->SCp.this_residual) 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data_count = current_SC->SCp.this_residual; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data_count > 0) { 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%d OUT, ", data_count); 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data_count == 1) { 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Bytes_Written++; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(*current_SC->SCp.ptr++, Write_FIFO_port); 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds --current_SC->SCp.this_residual; 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data_count >>= 1; 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_count = data_count << 1; 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outsw(Write_FIFO_port, current_SC->SCp.ptr, data_count); 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.ptr += tmp_count; 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Bytes_Written += tmp_count; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.this_residual -= tmp_count; 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!current_SC->SCp.this_residual) { 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->SCp.buffers_residual) { 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds --current_SC->SCp.buffers_residual; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++current_SC->SCp.buffer; 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.this_residual = current_SC->SCp.buffer->length; 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (current_SC->SCp.have_data_in == 1) { /* DATA IN */ 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((data_count = inw(FIFO_Data_Count_port)) > 0) { 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("DC=%d, ", data_count); 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data_count > current_SC->SCp.this_residual) 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data_count = current_SC->SCp.this_residual; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data_count) { 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%d IN, ", data_count); 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data_count == 1) { 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Bytes_Read++; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *current_SC->SCp.ptr++ = inb(Read_FIFO_port); 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds --current_SC->SCp.this_residual; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data_count >>= 1; /* Number of words */ 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp_count = data_count << 1; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds insw(Read_FIFO_port, current_SC->SCp.ptr, data_count); 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.ptr += tmp_count; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Bytes_Read += tmp_count; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.this_residual -= tmp_count; 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) { 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds --current_SC->SCp.buffers_residual; 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ++current_SC->SCp.buffer; 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.this_residual = current_SC->SCp.buffer->length; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (done) { 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" ** IN DONE %d ** ", current_SC->SCp.have_data_in); 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if ERRORS_ONLY 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) { 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((unsigned char) (*((char *) current_SC->request_buffer + 2)) & 0x0f) { 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char key; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char code; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char qualifier; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key = (unsigned char) (*((char *) current_SC->request_buffer + 2)) & 0x0f; 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds code = (unsigned char) (*((char *) current_SC->request_buffer + 12)); 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds qualifier = (unsigned char) (*((char *) current_SC->request_buffer + 13)); 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key != UNIT_ATTENTION && !(key == NOT_READY && code == 0x04 && (!qualifier || qualifier == 0x02 || qualifier == 0x01)) 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && !(key == ILLEGAL_REQUEST && (code == 0x25 || code == 0x24 || !code))) 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: REQUEST SENSE " "Key = %x, Code = %x, Qualifier = %x\n", key, code, qualifier); 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("BEFORE MY_DONE. . ."); 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds my_done(shpnt, (current_SC->SCp.Status & 0xff) 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16)); 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shpnt->host_lock, flags); 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("RETURNING.\n"); 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->SCp.phase & disconnect) { 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0xd0 | FIFO_COUNT, Interrupt_Cntl_port); 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, SCSI_Cntl_port); 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x90 | FIFO_COUNT, Interrupt_Cntl_port); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_interrupt_flag = 0; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_release(struct Scsi_Host *shpnt) 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, this_host, irq_usage; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(shpnt->io_port, shpnt->n_io_port); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this_host = -1; 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_usage = 0; 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < found; i++) { 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (shpnt == hosts[i]) 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this_host = i; 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (shpnt->irq == hosts[i]->irq) 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_usage++; 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* only for the last one */ 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (1 == irq_usage) 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(shpnt->irq, hosts); 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds found--; 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = this_host; i < found; i++) 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hosts[i] = hosts[i + 1]; 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hosts[found] = NULL; 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shpnt = SCpnt->device->host; 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (in_command) { 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds panic("fd_mcs: fd_mcs_queue() NOT REENTRANT!\n"); 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", SCpnt->target, *(unsigned char *) SCpnt->cmnd, SCpnt->use_sg, SCpnt->request_bufflen); 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fd_mcs_make_bus_idle(shpnt); 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->scsi_done = done; /* Save this for the done function */ 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC = SCpnt; 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize static data */ 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_SC->use_sg) { 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.buffer = (struct scatterlist *) current_SC->request_buffer; 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.this_residual = current_SC->SCp.buffer->length; 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.buffers_residual = current_SC->use_sg - 1; 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.ptr = (char *) current_SC->request_buffer; 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.this_residual = current_SC->request_bufflen; 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.buffer = NULL; 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.buffers_residual = 0; 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.Status = 0; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.Message = 0; 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.have_data_in = 0; 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.sent_command = 0; 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.phase = in_arbitration; 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start arbitration */ 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, Interrupt_Cntl_port); 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, SCSI_Cntl_port); /* Disable data drivers */ 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(adapter_mask, SCSI_Data_NoACK_port); /* Set our id bit */ 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in_command = 1; 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x20, Interrupt_Cntl_port); 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x14 | PARITY_MASK, TMC_Cntl_port); /* Start arbitration */ 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_ABORT || DEBUG_RESET 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void fd_mcs_print_info(Scsi_Cmnd * SCpnt) 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int imr; 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int irr; 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int isr; 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shpnt = SCpnt->host; 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!SCpnt || !SCpnt->host) { 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: cannot provide detailed information\n"); 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s\n", fd_mcs_info(SCpnt->host)); 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds print_banner(SCpnt->host); 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (SCpnt->SCp.phase) { 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case in_arbitration: 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("arbitration "); 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case in_selection: 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("selection "); 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case in_other: 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("other "); 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("unknown "); 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("(%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", SCpnt->SCp.phase, SCpnt->device->id, *(unsigned char *) SCpnt->cmnd, SCpnt->use_sg, SCpnt->request_bufflen); 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("sent_command = %d, have_data_in = %d, timeout = %d\n", SCpnt->SCp.sent_command, SCpnt->SCp.have_data_in, SCpnt->timeout); 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RACE 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("in_interrupt_flag = %d\n", in_interrupt_flag); 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds imr = (inb(0x0a1) << 8) + inb(0x21); 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x0a, 0xa0); 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irr = inb(0xa0) << 8; 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x0a, 0x20); 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irr += inb(0x20); 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x0b, 0xa0); 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isr = inb(0xa0) << 8; 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x0b, 0x20); 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds isr += inb(0x20); 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Print out interesting information */ 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("IMR = 0x%04x", imr); 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (imr & (1 << shpnt->irq)) 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" (masked)"); 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr); 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("SCSI Status = 0x%02x\n", inb(SCSI_Status_port)); 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("TMC Status = 0x%02x", inb(TMC_Status_port)); 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inb(TMC_Status_port) & 1) 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" (interrupt)"); 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Interrupt Status = 0x%02x", inb(Interrupt_Status_port)); 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inb(Interrupt_Status_port) & 0x08) 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" (enabled)"); 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip == tmc18c50 || chip == tmc18c30) { 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("FIFO Status = 0x%02x\n", inb(shpnt->io_port + FIFO_Status)); 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Int. Condition = 0x%02x\n", inb(shpnt->io_port + Interrupt_Cond)); 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Configuration 1 = 0x%02x\n", inb(shpnt->io_port + Configuration1)); 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip == tmc18c50 || chip == tmc18c30) 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Configuration 2 = 0x%02x\n", inb(shpnt->io_port + Configuration2)); 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_abort(Scsi_Cmnd * SCpnt) 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shpnt = SCpnt->device->host; 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: abort "); 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(shpnt->host_lock, flags); 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!in_command) { 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if EVERY_ACCESS || ERRORS_ONLY 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" (not in command)\n"); 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shpnt->host_lock, flags); 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_ABORT 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fd_mcs_print_info(SCpnt); 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fd_mcs_make_bus_idle(shpnt); 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->SCp.phase |= aborted; 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_SC->result = DID_ABORT << 16; 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Aborts are not done well. . . */ 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds my_done(shpnt, DID_ABORT << 16); 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(shpnt->host_lock, flags); 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_host_reset(Scsi_Cmnd * SCpnt) 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_device_reset(Scsi_Cmnd * SCpnt) 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return FAILED; 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) { 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct Scsi_Host *shpnt = SCpnt->device->host; 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RESET 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int called_once = 0; 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if ERRORS_ONLY 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (SCpnt) 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("fd_mcs: SCSI Bus Reset\n"); 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_RESET 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (called_once) 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fd_mcs_print_info(current_SC); 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds called_once = 1; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(1, SCSI_Cntl_port); 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_pause(2); 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, SCSI_Cntl_port); 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_pause(115); 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, SCSI_Mode_Cntl_port); 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(PARITY_MASK, TMC_Cntl_port); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Unless this is the very first call (i.e., SCPnt == NULL), everything 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds is probably hosed at this point. We will, however, try to keep 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds things going by informing the high-level code that we need help. */ 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return SUCCESS; 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_ioctl.h> 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev, 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sector_t capacity, int *info_array) 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *p = scsi_bios_ptable(bdev); 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size = capacity; 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* BIOS >= 3.4 for MCA cards */ 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This algorithm was provided by Future Domain (much thanks!). */ 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (p && p[65] == 0xaa && p[64] == 0x55 /* Partition table valid */ 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && p[4]) { /* Partition type */ 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The partition table layout is as follows: 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Start: 0x1b3h 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Offset: 0 = partition status 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1 = starting head 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2 = starting sector and cylinder (word, encoded) 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4 = partition type 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5 = ending head 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6 = ending sector and cylinder (word, encoded) 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8 = starting absolute sector (double word) 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds c = number of sectors (double word) 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Signature: 0x1fe = 0x55aa 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds So, this algorithm assumes: 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1) the first partition table is in use, 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2) the data in the first entry is correct, and 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3) partitions never divide cylinders 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Note that (1) may be FALSE for NetBSD (and other BSD flavors), 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds as well as for Linux. Note also, that Linux doesn't pay any 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds attention to the fields that are used by this algorithm -- it 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds only uses the absolute sector data. Recent versions of Linux's 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fdisk(1) will fill this data in correctly, and forthcoming 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds versions will check for consistency. 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Checking for a non-zero partition type is not part of the 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Future Domain algorithm, but it seemed to be a reasonable thing 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to do, especially in the Linux and BSD worlds. */ 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[0] = p[5] + 1; /* heads */ 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[1] = p[6] & 0x3f; /* sectors */ 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note that this new method guarantees that there will always be 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds less than 1024 cylinders on a platter. This is good for drives 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */ 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((unsigned int) size >= 0x7e0000U) 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[0] = 0xff; /* heads = 255 */ 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[1] = 0x3f; /* sectors = 63 */ 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((unsigned int) size >= 0x200000U) { 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[0] = 0x80; /* heads = 128 */ 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[1] = 0x3f; /* sectors = 63 */ 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[0] = 0x40; /* heads = 64 */ 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[1] = 0x20; /* sectors = 32 */ 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For both methods, compute the cylinders */ 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]); 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(p); 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic Scsi_Host_Template driver_template = { 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .proc_name = "fd_mcs", 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .proc_info = fd_mcs_proc_info, 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .detect = fd_mcs_detect, 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = fd_mcs_release, 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .info = fd_mcs_info, 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .queuecommand = fd_mcs_queue, 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_abort_handler = fd_mcs_abort, 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_bus_reset_handler = fd_mcs_bus_reset, 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_host_reset_handler = fd_mcs_host_reset, 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .eh_device_reset_handler = fd_mcs_device_reset, 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bios_param = fd_mcs_biosparam, 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .can_queue = 1, 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .this_id = 7, 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sg_tablesize = 64, 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cmd_per_lun = 1, 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .use_clustering = DISABLE_CLUSTERING, 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "scsi_module.c" 1370