eata.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,842 行 · 第 1/5 页
C
1,842 行
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. */ 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 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' */ unsigned char is_pci; /* TRUE is bus type is PCI */ struct pci_dev *pdev; /* pdev for PCI bus, NULL otherwise */ struct mssp *sp_cpu_addr; /* cpu addr for DMA buffer sp */ dma_addr_t sp_dma_addr; /* dma handle for DMA buffer sp */ struct mssp sp; /* Local copy of sp buffer */ };static struct Scsi_Host *sh[MAX_BOARDS + 1];static const char *driver_name = "EATA";static char sha[MAX_BOARDS];static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;/* 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[] = { /* 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)/* Device is Big Endian */#define H2DEV(x) cpu_to_be32(x)#define DEV2H(x) be32_to_cpu(x)#define H2DEV16(x) cpu_to_be16(x)#define DEV2H16(x) be16_to_cpu(x)/* But transfer orientation from the 16 bit data register is Little Endian */#define REG2H(x) le16_to_cpu(x)static irqreturn_t 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;static int ext_tran = FALSE;static int rev_scan = TRUE;#if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE)static int tag_mode = TAG_SIMPLE;#elsestatic int tag_mode = TAG_DISABLED;#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;#endif#if defined(CONFIG_ISA)static int isa_probe = TRUE;#elsestatic int isa_probe = FALSE;#endif#if defined(CONFIG_EISA)static int eisa_probe = TRUE;#elsestatic int eisa_probe = FALSE;#endif#if defined(CONFIG_PCI)static int pci_probe = TRUE;#elsestatic int pci_probe = FALSE;#endif#define MAX_INT_PARAM 10#define MAX_BOOT_OPTIONS_SIZE 256static char boot_options[MAX_BOOT_OPTIONS_SIZE];#if defined(MODULE)#include <linux/module.h>#include <linux/moduleparam.h>module_param_string(eata, boot_options, MAX_BOOT_OPTIONS_SIZE, 0);MODULE_PARM_DESC(eata, " equivalent to the \"eata=...\" kernel boot option." \" Example: modprobe eata \"eata=0x7410,0x230,lc:y,tm:0,mq:4,ep:n\"");MODULE_AUTHOR("Dario Ballabio");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("EATA/DMA SCSI Driver");#endifstatic int eata2x_slave_configure(Scsi_Device *dev) { int j, tqd, utqd; char *tag_suffix, *link_suffix; struct Scsi_Host *host = dev->host; j = ((struct hostdata *) host->hostdata)->board_number; utqd = MAX_CMD_PER_LUN; tqd = max_queue_depth; if (TLDEV(dev->type) && dev->tagged_supported) if (tag_mode == TAG_SIMPLE) { scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, tqd); tag_suffix = ", simple tags"; } else if (tag_mode == TAG_ORDERED) { scsi_adjust_queue_depth(dev, MSG_ORDERED_TAG, tqd); tag_suffix = ", ordered tags"; } else { scsi_adjust_queue_depth(dev, 0, tqd); tag_suffix = ", no tags"; } else if (TLDEV(dev->type) && linked_comm) { scsi_adjust_queue_depth(dev, 0, tqd); tag_suffix = ", untagged"; } else { scsi_adjust_queue_depth(dev, 0, utqd); tag_suffix = ""; } if (TLDEV(dev->type) && linked_comm && dev->queue_depth > 2) link_suffix = ", sorted"; else if (TLDEV(dev->type)) link_suffix = ", unsorted"; else link_suffix = ""; printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", BN(j), host->host_no, dev->channel, dev->id, dev->lun, dev->queue_depth, link_suffix, tag_suffix); return FALSE;}static int wait_on_busy(unsigned long iobase, unsigned int loop) { while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) { udelay(1L); if (--loop == 0) return TRUE; } return FALSE;}static int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) { unsigned char *byaddr; unsigned long devaddr; if (wait_on_busy(iobase, (addr ? MAXLOOP * 100 : MAXLOOP))) return TRUE; if (addr) { devaddr = H2DEV(addr); byaddr = (unsigned char *) &devaddr; outb(byaddr[3], iobase + REG_LOW); outb(byaddr[2], iobase + REG_LM); outb(byaddr[1], iobase + REG_MID); outb(byaddr[0], iobase + REG_MSB); } outb(cmd, iobase + REG_CMD); return FALSE;}static int read_pio(unsigned long iobase, ushort *start, ushort *end) { unsigned int loop = MAXLOOP; ushort *p; for (p = start; p <= end; p++) { while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) { udelay(1L); if (--loop == 0) return TRUE; } loop = MAXLOOP; *p = REG2H(inw(iobase)); } return FALSE;}static struct pci_dev *get_pci_dev(unsigned long port_base) {#if defined(CONFIG_PCI) unsigned int addr; struct pci_dev *dev = NULL; while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) { addr = pci_resource_start (dev, 0);#if defined(DEBUG_PCI_DETECT) printk("%s: get_pci_dev, bus %d, devfn 0x%x, addr 0x%x.\n", driver_name, dev->bus->number, dev->devfn, addr);#endif if (addr + PCI_BASE_ADDRESS_0 == port_base) return dev; }#endif /* end CONFIG_PCI */ return NULL;}static void enable_pci_ports(void) {#if defined(CONFIG_PCI) struct pci_dev *dev = NULL; while((dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) {#if defined(DEBUG_PCI_DETECT) printk("%s: enable_pci_ports, bus %d, devfn 0x%x.\n", driver_name, dev->bus->number, dev->devfn);#endif if (pci_enable_device (dev)) printk("%s: warning, pci_enable_device failed, bus %d devfn 0x%x.\n", driver_name, dev->bus->number, dev->devfn); }#endif /* end CONFIG_PCI */}static int port_detect \ (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) { unsigned char irq, dma_channel, subversion, i, is_pci = FALSE; unsigned char protocol_rev; struct eata_info info; char *bus_type, dma_name[16]; struct pci_dev *pdev; /* Allowed DMA channels for ISA (0 indicates reserved) */ unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; char name[16]; sprintf(name, "%s%d", driver_name, j); if (!request_region(port_base, REGION_SIZE, driver_name)) {#if defined(DEBUG_DETECT) printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);#endif goto fail; } spin_lock_irq(&driver_lock); if (do_dma(port_base, 0, READ_CONFIG_PIO)) {#if defined(DEBUG_DETECT) printk("%s: detect, do_dma failed at 0x%03lx.\n", name, port_base);#endif goto freelock; } /* Read the info structure */ if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) {#if defined(DEBUG_DETECT) printk("%s: detect, read_pio failed at 0x%03lx.\n", name, port_base);#endif goto freelock; } info.data_len = DEV2H(info.data_len); info.sign = DEV2H(info.sign); info.cp_pad_len = DEV2H16(info.cp_pad_len); info.cp_len = DEV2H(info.cp_len); info.sp_len = DEV2H(info.sp_len); info.scatt_size = DEV2H16(info.scatt_size); info.queue_size = DEV2H16(info.queue_size); /* Check the controller "EATA" signature */ if (info.sign != EATA_SIG_BE) {#if defined(DEBUG_DETECT) printk("%s: signature 0x%04x discarded.\n", name, info.sign);#endif goto freelock; } if (info.data_len < EATA_2_0A_SIZE) { printk("%s: config structure size (%d bytes) too short, detaching.\n", name, info.data_len); goto freelock; } else if (info.data_len == EATA_2_0A_SIZE) protocol_rev = 'A'; else if (info.data_len == EATA_2_0B_SIZE)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?