⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ibmmca.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 + -