📄 ibmmca.c
字号:
/* Low Level Linux Driver for the IBM Microchannel SCSI Subsystem for Linux Kernel >= 2.4.0. Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU General Public License. Written by Martin Kolinek, December 1995. Further development by: Chris Beauregard, Klaus Kudielka, Michael Lang See the file README.ibmmca for a detailed description of this driver, the commandline arguments and the history of its development. See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest updates, info and ADF-files for adapters supported by this driver.*/#ifndef LINUX_VERSION_CODE#include <linux/version.h>#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)#error "This driver works only with kernel 2.4.0 or higher!"#endif#include <linux/kernel.h>#include <linux/types.h>#include <linux/ctype.h>#include <linux/string.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/blk.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/mca.h>#include <asm/system.h>#include <linux/spinlock.h>#include <asm/io.h>#include <linux/init.h>#include "sd.h"#include "scsi.h"#include "hosts.h"#include "ibmmca.h"#include <linux/config.h>/* current version of this driver-source: */#define IBMMCA_SCSI_DRIVER_VERSION "4.0a"#define IBMLOCK spin_lock_irqsave(&io_request_lock, flags);#define IBMUNLOCK spin_unlock_irqrestore(&io_request_lock, flags);/* driver configuration */#define IM_MAX_HOSTS 8 /* maximum number of host adapters */#define IM_RESET_DELAY 60 /* seconds allowed for a reset *//* driver debugging - #undef all for normal operation *//* if defined: count interrupts and ignore this special one: */#undef IM_DEBUG_TIMEOUT 50 #define TIMEOUT_PUN 0#define TIMEOUT_LUN 0/* verbose interrupt: */#undef IM_DEBUG_INT /* verbose queuecommand: */#undef IM_DEBUG_CMD /* verbose queucommand for specific SCSI-device type: */#undef IM_DEBUG_CMD_SPEC_DEV/* verbose device probing */#undef IM_DEBUG_PROBE/* device type that shall be displayed on syslog (only during debugging): */#define IM_DEBUG_CMD_DEVICE TYPE_TAPE/* relative addresses of hardware registers on a subsystem */#define IM_CMD_REG(hi) (hosts[(hi)]->io_port) /*Command Interface, (4 bytes long) */#define IM_ATTN_REG(hi) (hosts[(hi)]->io_port+4) /*Attention (1 byte) */#define IM_CTR_REG(hi) (hosts[(hi)]->io_port+5) /*Basic Control (1 byte) */#define IM_INTR_REG(hi) (hosts[(hi)]->io_port+6) /*Interrupt Status (1 byte, r/o) */#define IM_STAT_REG(hi) (hosts[(hi)]->io_port+7) /*Basic Status (1 byte, read only) *//* basic I/O-port of first adapter */#define IM_IO_PORT 0x3540/* maximum number of hosts that can be found */#define IM_N_IO_PORT 8/*requests going into the upper nibble of the Attention register *//*note: the lower nibble specifies the device(0-14), or subsystem(15) */#define IM_IMM_CMD 0x10 /*immediate command */#define IM_SCB 0x30 /*Subsystem Control Block command */#define IM_LONG_SCB 0x40 /*long Subsystem Control Block command */#define IM_EOI 0xe0 /*end-of-interrupt request *//*values for bits 7,1,0 of Basic Control reg. (bits 6-2 reserved) */#define IM_HW_RESET 0x80 /*hardware reset */#define IM_ENABLE_DMA 0x02 /*enable subsystem's busmaster DMA */#define IM_ENABLE_INTR 0x01 /*enable interrupts to the system *//*to interpret the upper nibble of Interrupt Status register *//*note: the lower nibble specifies the device(0-14), or subsystem(15) */#define IM_SCB_CMD_COMPLETED 0x10#define IM_SCB_CMD_COMPLETED_WITH_RETRIES 0x50#define IM_LOOP_SCATTER_BUFFER_FULL 0x60#define IM_ADAPTER_HW_FAILURE 0x70#define IM_IMMEDIATE_CMD_COMPLETED 0xa0#define IM_CMD_COMPLETED_WITH_FAILURE 0xc0#define IM_CMD_ERROR 0xe0#define IM_SOFTWARE_SEQUENCING_ERROR 0xf0/*to interpret bits 3-0 of Basic Status register (bits 7-4 reserved) */#define IM_CMD_REG_FULL 0x08#define IM_CMD_REG_EMPTY 0x04#define IM_INTR_REQUEST 0x02#define IM_BUSY 0x01/*immediate commands (word written into low 2 bytes of command reg) */#define IM_RESET_IMM_CMD 0x0400#define IM_FEATURE_CTR_IMM_CMD 0x040c#define IM_DMA_PACING_IMM_CMD 0x040d#define IM_ASSIGN_IMM_CMD 0x040e#define IM_ABORT_IMM_CMD 0x040f#define IM_FORMAT_PREP_IMM_CMD 0x0417/*SCB (Subsystem Control Block) structure */struct im_scb { unsigned short command; /*command word (read, etc.) */ unsigned short enable; /*enable word, modifies cmd */ union { unsigned long log_blk_adr; /*block address on SCSI device */ unsigned char scsi_cmd_length; /*6,10,12, for other scsi cmd */ } u1; unsigned long sys_buf_adr; /*physical system memory adr */ unsigned long sys_buf_length; /*size of sys mem buffer */ unsigned long tsb_adr; /*Termination Status Block adr */ unsigned long scb_chain_adr; /*optional SCB chain address */ union { struct { unsigned short count; /*block count, on SCSI device */ unsigned short length; /*block length, on SCSI device */ } blk; unsigned char scsi_command[12]; /*other scsi command */ } u2;};/*structure scatter-gather element (for list of system memory areas) */struct im_sge { void *address; unsigned long byte_length;};/*structure returned by a get_pos_info command: */struct im_pos_info { unsigned short pos_id; /* adapter id */ unsigned char pos_3a; /* pos 3 (if pos 6 = 0) */ unsigned char pos_2; /* pos 2 */ unsigned char int_level; /* interrupt level IRQ 11 or 14 */ unsigned char pos_4a; /* pos 4 (if pos 6 = 0) */ unsigned short connector_size; /* MCA connector size: 16 or 32 Bit */ unsigned char num_luns; /* number of supported luns per device */ unsigned char num_puns; /* number of supported puns */ unsigned char pacing_factor; /* pacing factor */ unsigned char num_ldns; /* number of ldns available */ unsigned char eoi_off; /* time EOI and interrupt inactive */ unsigned char max_busy; /* time between reset and busy on */ unsigned short cache_stat; /* ldn cachestat. Bit=1 = not cached */ unsigned short retry_stat; /* retry status of ldns. Bit=1=disabled */ unsigned char pos_4b; /* pos 4 (if pos 6 = 1) */ unsigned char pos_3b; /* pos 3 (if pos 6 = 1) */ unsigned char pos_6; /* pos 6 */ unsigned char pos_5; /* pos 5 */ unsigned short max_overlap; /* maximum overlapping requests */ unsigned short num_bus; /* number of SCSI-busses */};/*values for SCB command word */#define IM_NO_SYNCHRONOUS 0x0040 /*flag for any command */#define IM_NO_DISCONNECT 0x0080 /*flag for any command */#define IM_READ_DATA_CMD 0x1c01#define IM_WRITE_DATA_CMD 0x1c02#define IM_READ_VERIFY_CMD 0x1c03#define IM_WRITE_VERIFY_CMD 0x1c04#define IM_REQUEST_SENSE_CMD 0x1c08#define IM_READ_CAPACITY_CMD 0x1c09#define IM_DEVICE_INQUIRY_CMD 0x1c0b#define IM_READ_LOGICAL_CMD 0x1c2a#define IM_OTHER_SCSI_CMD_CMD 0x241f/* unused, but supported, SCB commands */#define IM_GET_COMMAND_COMPLETE_STATUS_CMD 0x1c07 /* command status */#define IM_GET_POS_INFO_CMD 0x1c0a /* returns neat stuff */#define IM_READ_PREFETCH_CMD 0x1c31 /* caching controller only */#define IM_FOMAT_UNIT_CMD 0x1c16 /* format unit */#define IM_REASSIGN_BLOCK_CMD 0x1c18 /* in case of error *//*values to set bits in the enable word of SCB */#define IM_READ_CONTROL 0x8000#define IM_REPORT_TSB_ONLY_ON_ERROR 0x4000#define IM_RETRY_ENABLE 0x2000#define IM_POINTER_TO_LIST 0x1000#define IM_SUPRESS_EXCEPTION_SHORT 0x0400#define IM_BYPASS_BUFFER 0x0200#define IM_CHAIN_ON_NO_ERROR 0x0001/*TSB (Termination Status Block) structure */struct im_tsb { unsigned short end_status; unsigned short reserved1; unsigned long residual_byte_count; unsigned long sg_list_element_adr; unsigned short status_length; unsigned char dev_status; unsigned char cmd_status; unsigned char dev_error; unsigned char cmd_error; unsigned short reserved2; unsigned short reserved3; unsigned short low_of_last_scb_adr; unsigned short high_of_last_scb_adr;};/*subsystem uses interrupt request level 14 */#define IM_IRQ 14/*SCSI-2 F/W may evade to interrupt 11 */#define IM_IRQ_FW 11/* Model 95 has an additional alphanumeric display, which can be used to display SCSI-activities. 8595 models do not have any disk led, which makes this feature quite useful. The regular PS/2 disk led is turned on/off by bits 6,7 of system control port. *//* LED display-port (actually, last LED on display) */#define MOD95_LED_PORT 0x108/* system-control-register of PS/2s with diskindicator */#define PS2_SYS_CTR 0x92/* activity displaying methods */#define LED_DISP 1#define LED_ADISP 2#define LED_ACTIVITY 4/* failed intr */#define CMD_FAIL 255/* The SCSI-ID(!) of the accessed SCSI-device is shown on PS/2-95 machines' LED displays. ldn is no longer displayed here, because the ldn mapping is now done dynamically and the ldn <-> pun,lun maps can be looked-up at boottime or during uptime in /proc/scsi/ibmmca/<host_no> in case of trouble, interest, debugging or just for having fun. The left number gives the host-adapter number and the right shows the accessed SCSI-ID. *//* display_mode is set by the ibmmcascsi= command line arg */static int display_mode = 0;/* set default adapter timeout */static unsigned int adapter_timeout = 45;/* for probing on feature-command: */static unsigned int global_command_error_excuse = 0;/* global setting by command line for adapter_speed */static int global_adapter_speed = 0; /* full speed by default *//* Panel / LED on, do it right for F/W addressin, too. adisplay will * just ignore ids>7, as the panel has only 7 digits available */#define PS2_DISK_LED_ON(ad,id) { if (display_mode & LED_DISP) { if (id>9) \ outw((ad+48)|((id+55)<<8), MOD95_LED_PORT ); else \ outw((ad+48)|((id+48)<<8), MOD95_LED_PORT ); } else \ if (display_mode & LED_ADISP) { if (id<7) outb((char)(id+48),MOD95_LED_PORT+1+id); \ outb((char)(ad+48), MOD95_LED_PORT); } \ if ((display_mode & LED_ACTIVITY)||(!display_mode)) \ outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); }/* Panel / LED off *//* bug fixed, Dec 15, 1997, where | was replaced by & here */#define PS2_DISK_LED_OFF() { if (display_mode & LED_DISP) \ outw(0x2020, MOD95_LED_PORT ); else if (display_mode & LED_ADISP) { \ outl(0x20202020,MOD95_LED_PORT); outl(0x20202020,MOD95_LED_PORT+4); } \ if ((display_mode & LED_ACTIVITY)||(!display_mode)) \ outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); }/*list of supported subsystems */struct subsys_list_struct { unsigned short mca_id; char *description;};/* types of different supported hardware that goes to hostdata special */#define IBM_SCSI2_FW 0#define IBM_7568_WCACHE 1#define IBM_EXP_UNIT 2#define IBM_SCSI_WCACHE 3#define IBM_SCSI 4/* other special flags for hostdata structure */#define FORCED_DETECTION 100#define INTEGRATED_SCSI 101/* List of possible IBM-SCSI-adapters */struct subsys_list_struct subsys_list[] = { {0x8efc,"IBM SCSI-2 F/W Adapter"}, /* special = 0 */ {0x8efd,"IBM 7568 Industrial Computer SCSI Adapter w/Cache"}, /* special = 1 */ {0x8ef8,"IBM Expansion Unit SCSI Controller"},/* special = 2 */ {0x8eff,"IBM SCSI Adapter w/Cache"}, /* special = 3 */ {0x8efe,"IBM SCSI Adapter"}, /* special = 4 */};/* Max number of logical devices (can be up from 0 to 14). 15 is the addressof the adapter itself. */#define MAX_LOG_DEV 15/*local data for a logical device */struct logical_device { struct im_scb scb; /* SCSI-subsystem-control-block structure */ struct im_tsb tsb; /* SCSI command complete status block structure */ struct im_sge sge[16]; /* scatter gather list structure */ unsigned char buf[256]; /* SCSI command return data buffer */ Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */ int device_type; /* type of the SCSI-device. See include/scsi/scsi.h for interpretation of the possible values */ int block_length; /* blocksize of a particular logical SCSI-device */ int cache_flag; /* 1 if this is uncached, 0 if cache is present for ldn */ int retry_flag; /* 1 if adapter retry is disabled, 0 if enabled */};/* statistics of the driver during operations (for proc_info) */struct Driver_Statistics { /* SCSI statistics on the adapter */ int ldn_access[MAX_LOG_DEV+1]; /* total accesses on a ldn */ int ldn_read_access[MAX_LOG_DEV+1]; /* total read-access on a ldn */ int ldn_write_access[MAX_LOG_DEV+1]; /* total write-access on a ldn */ int ldn_inquiry_access[MAX_LOG_DEV+1]; /* total inquiries on a ldn */ int ldn_modeselect_access[MAX_LOG_DEV+1]; /* total mode selects on ldn */ int scbs; /* short SCBs queued */ int long_scbs; /* long SCBs queued */ int total_accesses; /* total accesses on all ldns */ int total_interrupts; /* total interrupts (should be same as total_accesses) */ int total_errors; /* command completed with error */ /* dynamical assignment statistics */ int total_scsi_devices; /* number of physical pun,lun */ int dyn_flag; /* flag showing dynamical mode */ int dynamical_assignments; /* number of remappings of ldns */ int ldn_assignments[MAX_LOG_DEV+1]; /* number of remappings of each ldn */};/* data structure for each host adapter */struct ibmmca_hostdata { /* array of logical devices: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -