⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 u14-34f.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#define REG_SYS_MASK      2#define REG_SYS_INTR      3#define REG_PRODUCT_ID1   4#define REG_PRODUCT_ID2   5#define REG_CONFIG1       6#define REG_CONFIG2       7#define REG_OGM           8#define REG_ICM           12#define REGION_SIZE       13#define BSY_ASSERTED      0x01#define IRQ_ASSERTED      0x01#define CMD_RESET         0xc0#define CMD_OGM_INTR      0x01#define CMD_CLR_INTR      0x01#define CMD_ENA_INTR      0x81#define ASOK              0x00#define ASST              0x91#define YESNO(a) ((a) ? 'y' : 'n')#define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM)#define PACKED          __attribute__((packed))struct sg_list {   unsigned int address;                /* Segment Address */   unsigned int num_bytes;              /* Segment Length */   };/* MailBox SCSI Command Packet */struct mscp {   unsigned char opcode: 3;             /* type of command */   unsigned char xdir: 2;               /* data transfer direction */   unsigned char dcn: 1;                /* disable disconnect */   unsigned char ca: 1;                 /* use cache (if available) */   unsigned char sg: 1;                 /* scatter/gather operation */   unsigned char target: 3;             /* SCSI target id */   unsigned char channel: 2;            /* SCSI channel number */   unsigned char lun: 3;                /* SCSI logical unit number */   unsigned int data_address PACKED;    /* transfer data pointer */   unsigned int data_len PACKED;        /* length in bytes */   unsigned int link_address PACKED;    /* for linking command chains */   unsigned char clink_id;              /* identifies command in chain */   unsigned char use_sg;                /* (if sg is set) 8 bytes per list */   unsigned char sense_len;   unsigned char scsi_cdbs_len;         /* 6, 10, or 12 */   unsigned char scsi_cdbs[12];         /* SCSI commands */   unsigned char adapter_status;        /* non-zero indicates HA error */   unsigned char target_status;         /* non-zero indicates target error */   unsigned int sense_addr PACKED;   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 ESA */   unsigned char heads;   unsigned char sectors;   /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */   unsigned char slot;   };static struct Scsi_Host *sh[MAX_BOARDS + 1];static const char *driver_name = "Ux4F";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[] = {   /* Space for MAX_INT_PARAM ports usable while loading as a module */   SKIP,    SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,    SKIP,   /* Possible ISA/VESA ports */   0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140,   /* End of list */   0x0   };#define HD(board) ((struct hostdata *) &sh[board]->hostdata)#define BN(board) (HD(board)->board_name)#define SWAP_BYTE(x) ((unsigned long)( \        (((unsigned long)(x) & 0x000000ffU) << 24) | \        (((unsigned long)(x) & 0x0000ff00U) <<  8) | \        (((unsigned long)(x) & 0x00ff0000U) >>  8) | \        (((unsigned long)(x) & 0xff000000U) >> 24)))#if defined(__BIG_ENDIAN)#define H2DEV(x) SWAP_BYTE(x)#else#define H2DEV(x) (x)#endif#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;static int ext_tran = FALSE;static char *boot_options;#if defined(HAVE_OLD_UX4F_FIRMWARE)static int have_old_firmware = TRUE;#elsestatic int have_old_firmware = FALSE;#endif#if defined(CONFIG_SCSI_U14_34F_LINKED_COMMANDS)static int linked_comm = TRUE;#elsestatic int linked_comm = FALSE;#endif#if defined(CONFIG_SCSI_U14_34F_MAX_TAGS)static int max_queue_depth = CONFIG_SCSI_U14_34F_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;   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 (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue)         tag_suffix = ", soft-tagged";      else if (dev->tagged_supported && TLDEV(dev->type))         tag_suffix = ", tagged";      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;}static inline int wait_on_busy(unsigned long iobase, unsigned int loop) {   while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) {      udelay(1L);      if (--loop == 0) return TRUE;      }   return FALSE;}static int board_inquiry(unsigned int j) {   struct mscp *cpp;   unsigned int time, limit = 0;   cpp = &HD(j)->cp[0];   memset(cpp, 0, sizeof(struct mscp));   cpp->opcode = OP_HOST_ADAPTER;   cpp->xdir = DTD_IN;   cpp->data_address = V2DEV(HD(j)->board_id);   cpp->data_len = H2DEV(sizeof(HD(j)->board_id));   cpp->scsi_cdbs_len = 6;   cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {      printk("%s: board_inquiry, adapter busy.\n", BN(j));      return TRUE;      }   HD(j)->cp_stat[0] = IGNORE;   /* Clear the interrupt indication */   outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);   /* Store pointer in OGM address bytes */   outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);   /* Issue OGM interrupt */   outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);   SPIN_UNLOCK   time = jiffies;   while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L);   SPIN_LOCK   if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) {      HD(j)->cp_stat[0] = FREE;      printk("%s: board_inquiry, err 0x%x.\n", BN(j), cpp->adapter_status);      return TRUE;      }   return FALSE;}static inline int port_detect \      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) {   unsigned char irq, dma_channel, subversion, i;   unsigned char in_byte;   char *bus_type, dma_name[16];   /* Allowed BIOS base addresses (NULL indicates reserved) */   unsigned long bios_segment_table[8] = {      0,      0xc4000, 0xc8000, 0xcc000, 0xd0000,      0xd4000, 0xd8000, 0xdc000      };   /* Allowed IRQs */   unsigned char interrupt_table[4] = { 15, 14, 11, 10 };   /* Allowed DMA channels for ISA (0 indicates reserved) */   unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };   /* Head/sector mappings */   struct {      unsigned char heads;      unsigned char sectors;      } mapping_table[4] = {           { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 }           };   struct config_1 {      unsigned char bios_segment: 3;      unsigned char removable_disks_as_fixed: 1;      unsigned char interrupt: 2;      unsigned char dma_channel: 2;      } config_1;   struct config_2 {      unsigned char ha_scsi_id: 3;      unsigned char mapping_mode: 2;      unsigned char bios_drive_number: 1;      unsigned char tfr_port: 2;      } config_2;   char name[16];   sprintf(name, "%s%d", driver_name, j);   if(check_region(port_base, REGION_SIZE)) {#if defined(DEBUG_DETECT)      printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);#endif      return FALSE;      }   if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) return FALSE;   in_byte = inb(port_base + REG_PRODUCT_ID2);   if ((in_byte & 0xf0) != PRODUCT_ID2) return FALSE;   *(char *)&config_1 = inb(port_base + REG_CONFIG1);   *(char *)&config_2 = inb(port_base + REG_CONFIG2);   irq = interrupt_table[config_1.interrupt];   dma_channel = dma_channel_table[config_1.dma_channel];   subversion = (in_byte & 0x0f);   /* Board detected, allocate its IRQ */   if (request_irq(irq, do_interrupt_handler,             SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),             driver_name, (void *) &sha[j])) {      printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);      return FALSE;      }   if (subversion == ISA && request_dma(dma_channel, driver_name)) {      printk("%s: unable to allocate DMA channel %u, detaching.\n",             name, dma_channel);      free_irq(irq, &sha[j]);      return FALSE;      }   if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING;   sh[j] = scsi_register(tpnt, sizeof(struct hostdata));   if (sh[j] == NULL) {      printk("%s: unable to register host, detaching.\n", name);      free_irq(irq, &sha[j]);      if (subversion == ISA) free_dma(dma_channel);      return FALSE;      }   sh[j]->io_port = port_base;   sh[j]->unique_id = port_base;   sh[j]->n_io_port = REGION_SIZE;   sh[j]->base = bios_segment_table[config_1.bios_segment];   sh[j]->irq = irq;   sh[j]->sg_tablesize = MAX_SGLIST;   sh[j]->this_id = config_2.ha_scsi_id;   sh[j]->can_queue = MAX_MAILBOXES;   sh[j]->cmd_per_lun = MAX_CMD_PER_LUN;   sh[j]->select_queue_depths = select_queue_depths;#if defined(DEBUG_DETECT)   {   unsigned char sys_mask, lcl_mask;   sys_mask = inb(sh[j]->io_port + REG_SYS_MASK);   lcl_mask = inb(sh[j]->io_port + REG_LCL_MASK);   printk("SYS_MASK 0x%x, LCL_MASK 0x%x.\n", sys_mask, lcl_mask);   }#endif   /* Probably a bogus host scsi id, set it to the dummy value */   if (sh[j]->this_id == 0) sh[j]->this_id = -1;   /* If BIOS is disabled, force enable interrupts */   if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK);   /* Register the I/O space that we use */   request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name);   memset(HD(j), 0, sizeof(struct hostdata));   HD(j)->heads = mapping_table[config_2.mapping_mode].heads;   HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;   HD(j)->subversion = subversion;   HD(j)->board_number = j;   if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST;   if (HD(j)->subversion == ESA) {      sh[j]->unchecked_isa_dma = FALSE;      sh[j]->dma_channel = NO_DMA;      sprintf(BN(j), "U34F%d", j);      bus_type = "VESA";      }   else {      unsigned long flags;      scsi_register_blocked_host(sh[j]);      sh[j]->unchecked_isa_dma = TRUE;            flags=claim_dma_lock();      disable_dma(dma_channel);      clear_dma_ff(dma_channel);      set_dma_mode(dma_channel, DMA_MODE_CASCADE);      enable_dma(dma_channel);      release_dma_lock(flags);            sh[j]->dma_channel = dma_channel;      sprintf(BN(j), "U14F%d", j);      bus_type = "ISA";      }   sh[j]->max_channel = MAX_CHANNEL - 1;   sh[j]->max_id = MAX_TARGET;   sh[j]->max_lun = MAX_LUN;   if (HD(j)->subversion == ISA && !board_inquiry(j)) {      HD(j)->board_id[40] = 0;      if (strcmp(&HD(j)->board_id[32], "06000600")) {         printk("%s: %s.\n", BN(j), &HD(j)->board_id[8]);         printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n",                BN(j), &HD(j)->board_id[32]);         sh[j]->hostt->use_clustering = DISABLE_CLUSTERING;         sh[j]->sg_tablesize = MAX_SAFE_SGLIST;         }      }   if (dma_channel == NO_DMA) sprintf(dma_name, "%s", "BMST");   else                       sprintf(dma_name, "DMA %u", dma_channel);   for (i = 0; i < sh[j]->can_queue; i++)      if (! ((&HD(j)->cp[i])->sglist = kmalloc(            sh[j]->sg_tablesize * sizeof(struct sg_list),            (sh[j]->unchecked_isa_dma ? GFP_DMA : 0) | GFP_ATOMIC))) {         printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j), i);         u14_34f_release(sh[j]);         return FALSE;         }   if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN)       max_queue_depth = MAX_TAGGED_CMD_PER_LUN;   if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;   if (j == 0) {      printk("UltraStor 14F/34F: Copyright (C) 1994-2000 Dario Ballabio.\n");      printk("%s config options -> of:%c, lc:%c, mq:%d, et:%c.\n",             driver_name, YESNO(have_old_firmware), YESNO(linked_comm),

⌨️ 快捷键说明

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