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