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 + -
显示快捷键?