📄 eata.c
字号:
#include <asm/dma.h>#include <asm/irq.h>#include "eata.h"#include <linux/stat.h>#include <linux/config.h>#include <linux/pci.h>#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93)#include <linux/bios32.h>#endif#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,36)#include <linux/init.h>#else#define __initfunc(A) A#define __initdata#define __init#endif#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,101)#include <asm/spinlock.h>#define IRQ_FLAGS#define IRQ_LOCK#define IRQ_LOCK_SAVE#define IRQ_UNLOCK#define IRQ_UNLOCK_RESTORE#define SPIN_FLAGS unsigned long spin_flags;#define SPIN_LOCK spin_lock_irq(&io_request_lock);#define SPIN_LOCK_SAVE spin_lock_irqsave(&io_request_lock, spin_flags);#define SPIN_UNLOCK spin_unlock_irq(&io_request_lock);#define SPIN_UNLOCK_RESTORE \ spin_unlock_irqrestore(&io_request_lock, spin_flags);static int use_new_eh_code = TRUE;#else#define IRQ_FLAGS unsigned long irq_flags;#define IRQ_LOCK cli();#define IRQ_LOCK_SAVE do {save_flags(irq_flags); cli();} while (0);#define IRQ_UNLOCK sti();#define IRQ_UNLOCK_RESTORE do {restore_flags(irq_flags);} while (0);#define SPIN_FLAGS#define SPIN_LOCK#define SPIN_LOCK_SAVE#define SPIN_UNLOCK#define SPIN_UNLOCK_RESTOREstatic int use_new_eh_code = FALSE;#endifstruct proc_dir_entry proc_scsi_eata2x = { PROC_SCSI_EATA2X, 6, "eata2x", S_IFDIR | S_IRUGO | S_IXUGO, 2};/* 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 FALSE 0#define TRUE 1#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_MIXED 0#define TAG_SIMPLE 1#define TAG_HEAD 2#define TAG_ORDERED 3#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 9#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 ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr)[0])#define YESNO(a) ((a) ? 'y' : 'n')#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM)/* "EATA", in Big Endian format */#define EATA_SIGNATURE 0x41544145/* 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 { ulong data_len; /* Number of valid bytes after this field */ ulong sign; /* ASCII "EATA" signature */ 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 */ 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 */ ulong cp_len; /* Number of valid bytes in cp */ ulong 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 */ 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 */ 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 */ 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; unchar cpad[511]; };/* Returned status packet structure */struct mssp { unchar adapter_status:7, /* State related to current command */ eoc:1; /* End Of Command (1 = command completed) */ unchar target_status; /* SCSI status received after data transfer */ unchar unused[2]; ulong inv_res_len; /* Number of bytes not transferred */ struct mscp *cpp; /* 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 { 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 */ unchar mess[3]; /* Massage to/from Target */ unchar cdb[12]; /* Command Descriptor Block */ ulong data_len; /* If sg=0 Data Length, if sg=1 sglist length */ struct mscp *cpp; /* Address to be returned in sp */ ulong data_address; /* If sg=0 Data Address, if sg=1 sglist address */ ulong sp_addr; /* Address where sp is DMA'ed when cp completes */ ulong sense_addr; /* Address where Sense Data is DMA'ed on error */ Scsi_Cmnd *SCpnt; unsigned int index; /* cp index */ struct sg_list *sglist; };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 */ char board_id[256]; /* data from INQUIRY on 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 TRUE 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' */ struct mssp sp[2]; /* Returned status for this board */ };static struct Scsi_Host *sh[MAX_BOARDS + 1];static const char *driver_name = "EATA";static char sha[MAX_BOARDS];/* Initialize num_boards so that ihdlr can work while detect is in progress */static unsigned int num_boards = MAX_BOARDS;static unsigned long io_port[] __initdata = { /* Space for MAX_INT_PARAM ports usable while loading as a module */ SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, /* First ISA */ 0x1f0, /* Space for MAX_PCI ports possibly reported by PCI_BIOS */ SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, /* MAX_EISA ports */ 0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88, 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, /* Other (MAX_ISA - 1) ports */ 0x170, 0x230, 0x330, /* End of list */ 0x0 };#define HD(board) ((struct hostdata *) &sh[board]->hostdata)#define BN(board) (HD(board)->board_name)#define H2DEV(x) htonl(x)#define DEV2H(x) H2DEV(x)#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)static void do_interrupt_handler(int, void *, struct pt_regs *);static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int);static int do_trace = FALSE;static int setup_done = FALSE;static int link_statistics = 0;static int tag_mode = TAG_MIXED;static int ext_tran = FALSE;static int rev_scan = TRUE;#if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE)static int tagged_comm = TRUE;#elsestatic int tagged_comm = FALSE;#endif#if defined(CONFIG_SCSI_EATA_LINKED_COMMANDS)static int linked_comm = TRUE;#elsestatic int linked_comm = FALSE;#endif#if defined(CONFIG_SCSI_EATA_MAX_TAGS)static int max_queue_depth = CONFIG_SCSI_EATA_MAX_TAGS;#elsestatic int max_queue_depth = MAX_CMD_PER_LUN;#endifstatic void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { Scsi_Device *dev; int j, ntag = 0, nuntag = 0, tqd, utqd; IRQ_FLAGS IRQ_LOCK_SAVE j = ((struct hostdata *) host->hostdata)->board_number; for(dev = devlist; dev; dev = dev->next) { if (dev->host != host) continue; if (TLDEV(dev->type) && (dev->tagged_supported || linked_comm)) ntag++; else nuntag++; } utqd = MAX_CMD_PER_LUN; tqd = (host->can_queue - utqd * nuntag) / (ntag ? ntag : 1); if (tqd > max_queue_depth) tqd = max_queue_depth; if (tqd < MAX_CMD_PER_LUN) tqd = MAX_CMD_PER_LUN; for(dev = devlist; dev; dev = dev->next) { char *tag_suffix = "", *link_suffix = ""; if (dev->host != host) continue; if (TLDEV(dev->type) && (dev->tagged_supported || linked_comm)) dev->queue_depth = tqd; else dev->queue_depth = utqd; if (TLDEV(dev->type)) { if (linked_comm && dev->queue_depth > 2) link_suffix = ", sorted"; else link_suffix = ", unsorted"; } if (tagged_comm && dev->tagged_supported && TLDEV(dev->type)) { dev->tagged_queue = 1; dev->current_tag = 1; } if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue) tag_suffix = ", tagged"; else if (dev->tagged_supported && TLDEV(dev->type)) tag_suffix = ", untagged";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -