eata.c

来自「linux 内核源代码」· C语言 代码 · 共 2,073 行 · 第 1/5 页

C
2,073
字号
 * *  The default value is: "eata=lc:n,mq:16,tm:0,et:n,rs:n". *  An example using the list of detection probes could be: *  "eata=0x7410,0x230,lc:y,tm:2,mq:4,et:n". * *  When loading as a module, parameters can be specified as well. *  The above example would be (use 1 in place of y and 0 in place of n): * *  modprobe eata io_port=0x7410,0x230 linked_comm=1 \ *                max_queue_depth=4 ext_tran=0 tag_mode=2 \ *                rev_scan=1 * *  ---------------------------------------------------------------------------- *  In this implementation, linked commands are designed to work with any DISK *  or CD-ROM, since this linking has only the intent of clustering (time-wise) *  and reordering by elevator sorting commands directed to each device, *  without any relation with the actual SCSI protocol between the controller *  and the device. *  If Q is the queue depth reported at boot time for each device (also named *  cmds/lun) and Q > 2, whenever there is already an active command to the *  device all other commands to the same device  (up to Q-1) are kept waiting *  in the elevator sorting queue. When the active command completes, the *  commands in this queue are sorted by sector address. The sort is chosen *  between increasing or decreasing by minimizing the seek distance between *  the sector of the commands just completed and the sector of the first *  command in the list to be sorted. *  Trivial math assures that the unsorted average seek distance when doing *  random seeks over S sectors is S/3. *  When (Q-1) requests are uniformly distributed over S sectors, the average *  distance between two adjacent requests is S/((Q-1) + 1), so the sorted *  average seek distance for (Q-1) random requests over S sectors is S/Q. *  The elevator sorting hence divides the seek distance by a factor Q/3. *  The above pure geometric remarks are valid in all cases and the *  driver effectively reduces the seek distance by the predicted factor *  when there are Q concurrent read i/o operations on the device, but this *  does not necessarily results in a noticeable performance improvement: *  your mileage may vary.... * *  Note: command reordering inside a batch of queued commands could cause *        wrong results only if there is at least one write request and the *        intersection (sector-wise) of all requests is not empty. *        When the driver detects a batch including overlapping requests *        (a really rare event) strict serial (pid) order is enforced. *  ---------------------------------------------------------------------------- *  The extended translation option (et:y) is useful when using large physical *  disks/arrays. It could also be useful when switching between Adaptec boards *  and DPT boards without reformatting the disk. *  When a boot disk is partitioned with extended translation, in order to *  be able to boot it with a DPT board is could be necessary to add to *  lilo.conf additional commands as in the following example: * *  fix-table *  disk=/dev/sda bios=0x80 sectors=63 heads=128 cylindres=546 * *  where the above geometry should be replaced with the one reported at *  power up by the DPT controller. *  ---------------------------------------------------------------------------- * *  The boards are named EATA0, EATA1,... according to the detection order. * *  In order to support multiple ISA boards in a reliable way, *  the driver sets host->wish_block = 1 for all ISA boards. */#include <linux/string.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/proc_fs.h>#include <linux/blkdev.h>#include <linux/interrupt.h>#include <linux/stat.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ctype.h>#include <linux/spinlock.h>#include <linux/dma-mapping.h>#include <asm/byteorder.h>#include <asm/dma.h>#include <asm/io.h>#include <asm/irq.h>#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_device.h>#include <scsi/scsi_host.h>#include <scsi/scsi_tcq.h>#include <scsi/scsicam.h>static int eata2x_detect(struct scsi_host_template *);static int eata2x_release(struct Scsi_Host *);static int eata2x_queuecommand(struct scsi_cmnd *,			       void (*done) (struct scsi_cmnd *));static int eata2x_eh_abort(struct scsi_cmnd *);static int eata2x_eh_host_reset(struct scsi_cmnd *);static int eata2x_bios_param(struct scsi_device *, struct block_device *,			     sector_t, int *);static int eata2x_slave_configure(struct scsi_device *);static struct scsi_host_template driver_template = {	.name = "EATA/DMA 2.0x rev. 8.10.00 ",	.detect = eata2x_detect,	.release = eata2x_release,	.queuecommand = eata2x_queuecommand,	.eh_abort_handler = eata2x_eh_abort,	.eh_host_reset_handler = eata2x_eh_host_reset,	.bios_param = eata2x_bios_param,	.slave_configure = eata2x_slave_configure,	.this_id = 7,	.unchecked_isa_dma = 1,	.use_clustering = ENABLE_CLUSTERING,	.use_sg_chaining = ENABLE_SG_CHAINING,};#if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD)#error "Adjust your <asm/byteorder.h> defines"#endif/* Subversion values */#define ISA  0#define ESA 1#undef  FORCE_CONFIG#undef  DEBUG_LINKED_COMMANDS#undef  DEBUG_DETECT#undef  DEBUG_PCI_DETECT#undef  DEBUG_INTERRUPT#undef  DEBUG_RESET#undef  DEBUG_GENERATE_ERRORS#undef  DEBUG_GENERATE_ABORTS#undef  DEBUG_GEOMETRY#define MAX_ISA 4#define MAX_VESA 0#define MAX_EISA 15#define MAX_PCI 16#define MAX_BOARDS (MAX_ISA + MAX_VESA + MAX_EISA + MAX_PCI)#define MAX_CHANNEL 4#define MAX_LUN 32#define MAX_TARGET 32#define MAX_MAILBOXES 64#define MAX_SGLIST 64#define MAX_LARGE_SGLIST 122#define MAX_INTERNAL_RETRIES 64#define MAX_CMD_PER_LUN 2#define MAX_TAGGED_CMD_PER_LUN (MAX_MAILBOXES - MAX_CMD_PER_LUN)#define SKIP ULONG_MAX#define FREE 0#define IN_USE   1#define LOCKED   2#define IN_RESET 3#define IGNORE   4#define READY    5#define ABORTING 6#define NO_DMA  0xff#define MAXLOOP  10000#define TAG_DISABLED 0#define TAG_SIMPLE   1#define TAG_ORDERED  2#define REG_CMD         7#define REG_STATUS      7#define REG_AUX_STATUS  8#define REG_DATA        0#define REG_DATA2       1#define REG_SEE         6#define REG_LOW         2#define REG_LM          3#define REG_MID         4#define REG_MSB         5#define REGION_SIZE     9UL#define MAX_ISA_ADDR    0x03ff#define MIN_EISA_ADDR   0x1c88#define MAX_EISA_ADDR   0xfc88#define BSY_ASSERTED      0x80#define DRQ_ASSERTED      0x08#define ABSY_ASSERTED     0x01#define IRQ_ASSERTED      0x02#define READ_CONFIG_PIO   0xf0#define SET_CONFIG_PIO    0xf1#define SEND_CP_PIO       0xf2#define RECEIVE_SP_PIO    0xf3#define TRUNCATE_XFR_PIO  0xf4#define RESET_PIO         0xf9#define READ_CONFIG_DMA   0xfd#define SET_CONFIG_DMA    0xfe#define SEND_CP_DMA       0xff#define ASOK              0x00#define ASST              0x01#define YESNO(a) ((a) ? 'y' : 'n')#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM)/* "EATA", in Big Endian format */#define EATA_SIG_BE 0x45415441/* Number of valid bytes in the board config structure for EATA 2.0x */#define EATA_2_0A_SIZE 28#define EATA_2_0B_SIZE 30#define EATA_2_0C_SIZE 34/* Board info structure */struct eata_info {	u_int32_t data_len;	/* Number of valid bytes after this field */	u_int32_t sign;		/* ASCII "EATA" signature */#if defined(__BIG_ENDIAN_BITFIELD)	unchar version	: 4,	       		: 4;	unchar haaval	: 1,	       ata	: 1,	       drqvld	: 1,	       dmasup	: 1,	       morsup	: 1,	       trnxfr	: 1,	       tarsup	: 1,	       ocsena	: 1;#else	unchar		: 4,	/* unused low nibble */	 	version	: 4;	/* EATA version, should be 0x1 */	unchar ocsena	: 1,	/* Overlap Command Support Enabled */	       tarsup	: 1,	/* Target Mode Supported */	       trnxfr	: 1,	/* Truncate Transfer Cmd NOT Necessary */	       morsup	: 1,	/* More Supported */	       dmasup	: 1,	/* DMA Supported */	       drqvld	: 1,	/* DRQ Index (DRQX) is valid */	       ata	: 1,	/* This is an ATA device */	       haaval	: 1;	/* Host Adapter Address Valid */#endif	ushort cp_pad_len;	/* Number of pad bytes after cp_len */	unchar host_addr[4];	/* Host Adapter SCSI ID for channels 3, 2, 1, 0 */	u_int32_t cp_len;	/* Number of valid bytes in cp */	u_int32_t sp_len;	/* Number of valid bytes in sp */	ushort queue_size;	/* Max number of cp that can be queued */	ushort unused;	ushort scatt_size;	/* Max number of entries in scatter/gather table */#if defined(__BIG_ENDIAN_BITFIELD)	unchar drqx	: 2,	       second	: 1,	       irq_tr	: 1,	       irq	: 4;	unchar sync;	unchar		: 4,	       res1	: 1,	       large_sg	: 1,	       forcaddr	: 1,	       isaena	: 1;	unchar max_chan	: 3,	       max_id	: 5;	unchar max_lun;	unchar eisa	: 1,	       pci	: 1,	       idquest	: 1,	       m1	: 1,	       		: 4;#else	unchar irq	: 4,	/* Interrupt Request assigned to this controller */	       irq_tr	: 1,	/* 0 for edge triggered, 1 for level triggered */	       second	: 1,	/* 1 if this is a secondary (not primary) controller */	       drqx	: 2;	/* DRQ Index (0=DMA0, 1=DMA7, 2=DMA6, 3=DMA5) */	unchar sync;		/* 1 if scsi target id 7...0 is running sync scsi */	/* Structure extension defined in EATA 2.0B */	unchar isaena	: 1,	/* ISA i/o addressing is disabled/enabled */	       forcaddr	: 1,	/* Port address has been forced */	       large_sg	: 1,	/* 1 if large SG lists are supported */	       res1	: 1,	       		: 4;	unchar max_id	: 5,	/* Max SCSI target ID number */	       max_chan	: 3;	/* Max SCSI channel number on this board */	/* Structure extension defined in EATA 2.0C */	unchar max_lun;		/* Max SCSI LUN number */	unchar			: 4,	       m1	: 1,	/* This is a PCI with an M1 chip installed */	       idquest	: 1,	/* RAIDNUM returned is questionable */	       pci	: 1,	/* This board is PCI */	       eisa	: 1;	/* This board is EISA */#endif	unchar raidnum;		/* Uniquely identifies this HBA in a system */	unchar notused;	ushort ipad[247];};/* Board config structure */struct eata_config {	ushort len;		/* Number of bytes following this field */#if defined(__BIG_ENDIAN_BITFIELD)	unchar		: 4,	       tarena	: 1,	       mdpena	: 1,	       ocena	: 1,	       edis	: 1;#else	unchar edis	: 1,	/* Disable EATA interface after config command */	       ocena	: 1,	/* Overlapped Commands Enabled */	       mdpena	: 1,	/* Transfer all Modified Data Pointer Messages */	       tarena	: 1,	/* Target Mode Enabled for this controller */	       		: 4;#endif	unchar cpad[511];};/* Returned status packet structure */struct mssp {#if defined(__BIG_ENDIAN_BITFIELD)	unchar eoc	: 1,	       adapter_status : 7;#else	unchar adapter_status : 7,	/* State related to current command */	       eoc	: 1;		/* End Of Command (1 = command completed) */#endif	unchar target_status;	/* SCSI status received after data transfer */	unchar unused[2];	u_int32_t inv_res_len;	/* Number of bytes not transferred */	u_int32_t cpp_index;	/* Index of address set in cp */	char mess[12];};struct sg_list {	unsigned int address;	/* Segment Address */	unsigned int num_bytes;	/* Segment Length */};/* MailBox SCSI Command Packet */struct mscp {#if defined(__BIG_ENDIAN_BITFIELD)	unchar din	: 1,	       dout	: 1,	       interp	: 1,	       		: 1,		sg	: 1,		reqsen	:1,		init	: 1,		sreset	: 1;	unchar sense_len;	unchar unused[3];	unchar		: 7,	       fwnest	: 1;	unchar		: 5,	       hbaci	: 1,	       iat	: 1,	       phsunit	: 1;	unchar channel	: 3,	       target	: 5;	unchar one	: 1,	       dispri	: 1,	       luntar	: 1,	       lun	: 5;#else	unchar sreset	:1,	/* SCSI Bus Reset Signal should be asserted */	       init	:1,	/* Re-initialize controller and self test */	       reqsen	:1,	/* Transfer Request Sense Data to addr using DMA */	       sg	:1,	/* Use Scatter/Gather */	       		:1,	       interp	:1,	/* The controller interprets cp, not the target */	       dout	:1,	/* Direction of Transfer is Out (Host to Target) */	       din	:1;	/* Direction of Transfer is In (Target to Host) */	unchar sense_len;	/* Request Sense Length */	unchar unused[3];	unchar fwnest	: 1,	/* Send command to a component of an Array Group */			: 7;	unchar phsunit	: 1,	/* Send to Target Physical Unit (bypass RAID) */	       iat	: 1,	/* Inhibit Address Translation */	       hbaci	: 1,	/* Inhibit HBA Caching for this command */	       		: 5;	unchar target	: 5,	/* SCSI target ID */	       channel	: 3;	/* SCSI channel number */	unchar lun	: 5,	/* SCSI logical unit number */	       luntar	: 1,	/* This cp is for Target (not LUN) */	       dispri	: 1,	/* Disconnect Privilege granted */	       one	: 1;	/* 1 */#endif	unchar mess[3];		/* Massage to/from Target */	unchar cdb[12];		/* Command Descriptor Block */	u_int32_t data_len;	/* If sg=0 Data Length, if sg=1 sglist length */	u_int32_t cpp_index;	/* Index of address to be returned in sp */	u_int32_t data_address;	/* If sg=0 Data Address, if sg=1 sglist address */	u_int32_t sp_dma_addr;	/* Address where sp is DMA'ed when cp completes */	u_int32_t sense_addr;	/* Address where Sense Data is DMA'ed on error */	/* Additional fields begin here. */	struct scsi_cmnd *SCpnt;	/* All the cp structure is zero filled by queuecommand except the	   following CP_TAIL_SIZE bytes, initialized by detect */	dma_addr_t cp_dma_addr;	/* dma handle for this cp structure */	struct sg_list *sglist;	/* pointer to the allocated SG list */};#define CP_TAIL_SIZE (sizeof(struct sglist *) + sizeof(dma_addr_t))struct hostdata {	struct mscp cp[MAX_MAILBOXES];	/* Mailboxes for this board */	unsigned int cp_stat[MAX_MAILBOXES];	/* FREE, IN_USE, LOCKED, IN_RESET */	unsigned int last_cp_used;	/* Index of last mailbox used */	unsigned int iocount;	/* Total i/o done for this board */	int board_number;	/* Number of this board */	char board_name[16];	/* Name of this board */	int in_reset;		/* True if board is doing a reset */	int target_to[MAX_TARGET][MAX_CHANNEL];	/* N. of timeout errors on target */	int target_redo[MAX_TARGET][MAX_CHANNEL];	/* If 1 redo i/o on target */	unsigned int retries;	/* Number of internal retries */	unsigned long last_retried_pid;	/* Pid of last retried command */	unsigned char subversion;	/* Bus type, either ISA or EISA/PCI */	unsigned char protocol_rev;	/* EATA 2.0 rev., 'A' or 'B' or 'C' */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?